Files
mt/trunk/mt.php

341 lines
12 KiB
PHP

<?php
$secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
$port = ($secure && $_SERVER['SERVER_PORT'] == 443) || $_SERVER['SERVER_PORT'] == 80 ? '' : ":" . $_SERVER['SERVER_PORT'];
$self = 'http' .
($secure ? 's' : '') .
'://' .
$_SERVER['SERVER_NAME'] .
$port .
preg_replace('/^(.*)\?.*$/', '$1', $_SERVER['REQUEST_URI']);
$flexgetCmd = 'sudo -u transmission -H /var/transmission/flexget-dev/bin/flexget';
$messages = array();
$errors = array();
$currentSeries = array();
if (isset($_POST['action'])) {
$action = $_POST['action'];
switch ($action) {
case 'inject':
if (!isset($_POST['inject'])) {
$errors[] = 'No inject parameter specified';
break;
}
$injectTitle = escapeshellarg($_POST['inject']);
$injectUrl = escapeshellarg($_POST['injecturl']);
$runCmd = '';
# if there's an url, have it downloaded, else just learn the title
if (preg_match("#https?://.*#", $injectUrl)) {
$runCmd = "{$flexgetCmd} --inject {$injectTitle} {$injectUrl} ACCEPT";
} else {
$runCmd = "{$flexgetCmd} --inject {$injectTitle} --learn";
}
$output = '';
$returnValue = 0;
exec($runCmd, $output, $returnValue);
if ($returnValue) {
$error = urlencode('Failed to inject ' . $_POST['inject'] . "\n" . join("\n", $output));
header("Location: {$self}?error={$error}");
exit(0);
} else {
# Redirect and display a success message
$message = urlencode('Successfully injected ' . $_POST['inject']);
header("Location: {$self}?message={$message}");
exit(0);
}
break;
case 'series-forget':
if (!isset($_POST['series'])) {
$errors[] = 'No series parameter specified';
break;
}
if (!isset($_POST['episode'])) {
$errors[] = 'No episode parameter specified';
break;
} else {
if (!$_POST['episode']) {
$errors[] = 'No episode number specified';
break;
}
}
$forgetSeriesArg = escapeshellarg($_POST['series']);
$forgetEpisodeArg = escapeshellarg($_POST['episode']);
# The database may have multiple entries, so keep removing until it no longer matches anything
do {
$runCmd = "{$flexgetCmd} --series-forget $forgetSeriesArg $forgetEpisodeArg";
$output = '';
$returnValue = 0;
exec($runCmd, $output, $returnValue);
} while (preg_match("/^Removed/", $output[0]));
if ($returnValue) {
$error = urlencode('Failed to forget about ' . $_POST['series'] . ' ' . $_POST['episode'] . "\n" . join("\n", $output));
header("Location: {$self}?error={$error}");
exit(0);
} else {
$message = urlencode('Successfully forgot about ' . $_POST['series'] . ' ' . $_POST['episode']);
header("Location: {$self}?message={$message}");
exit(0);
}
break;
default:
$error = urlencode('Unsupported action: ' . $_POST['action']);
header("Location: {$self}?error={$error}");
exit(0);
}
} else {
if (isset($_GET['message'])) {
$messages[] = $_GET['message'];
}
if (isset($_GET['error'])) {
$errors[] = $_GET['error'];
}
}
# Grab the up-to-date list of tv series for display
$runCmd = "{$flexgetCmd} --series";
$output = '';
$returnValue = 0;
exec($runCmd, $output, $returnValue);
if (!$returnValue) {
// Ignore the first and last two lines from the output
assert('count($output) >= 4; // Expecting at least four lines of output from flexget');
$output = array_slice($output, 2, -2);
/*
Name Latest Status
-------------------------------------------------------------------------------
castle s02e10 *hdtv-Proper
*/
foreach ($output as $line) {
$matches = array();
if (!preg_match('/^\s(?P<series>.{1,30})\s+(?P<episode>.{1,20})\s+(?P<quality>.*)\s+/', $line, $matches)) {
$errors[] = "Failed to parse '$line'";
continue;
}
$currentSeries[trim($matches['series'])] = array(
'episode' => trim($matches['episode']),
'quality' => trim($matches['quality']),
);
}
ksort($currentSeries);
} else {
$errors[] = 'Unable to get the current series/episode list. (Maybe flexget is currently running?)';
}
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Sihnon bittorrent utilities</title>
<script lang="javascript">
function addEvent(obj, eventname, func, name) {
if (obj.attachEvent) {
//IE
obj.attachEvent('on'+eventname, func);
} else {
//Non-IE (Firefox, Netscape, W3C standard)
obj.addEventListener(eventname, func, false);
}
}
addEvent(window, 'load', function() {
addSimpleFormEvents([id('inject')]);
addSimpleFormEvents([id('forgetSeries'), id('forgetEpisode')]);
});
function addSimpleFormEvents(inputFields) {
for (var i = 0; i < inputFields.length; ++i) {
var field = inputFields[i];
addEvent(field, 'focus', function() {
if (this.value == field.defaultValue) {
this.value = "";
removeClass(this, "default");
}
});
addEvent(field, 'blur', function() {
if (this.value == "") {
this.value = this.defaultValue;
addClass(this, "default");
}
});
}
}
function id(elementId) {
return document.getElementById(elementId);
}
function addClass(element, newclass) {
//Return it immediately if it already exists
if (element.className.indexOf(newclass) > -1)
return;
//Split it into an array, separated by spaces
var classes = element.className.split(' ');
//Add the new class
classes.push(newclass);
//Then return the array joined back into a string with spaces
element.className = classes.join(' ');
}
function removeClass(element, oldclass) {
//Split the class list into an array by spaces
var classes = element.className.split(' ');
for (var cls in classes) {
//Iterate through the array of classes...
if (classes[cls] == oldclass) {
//...removing that class if it exists
classes[cls] = undefined;
}
}
//Then join the array back together and return.
//We remove double-spaces as "delete" doesn't seem to delete the element entirely
element.className = classes.join(' ').replace(' ',' ');
}
function seriesForget(series, episode) {
id("listAction").value = "series-forget";
id("listForgetSeries").value = series;
id("listForgetEpisode").value = episode;
id("listOperations").submit();
}
</script>
<style>
body {
font-family: verdana, helvetica, sans-serif;
}
a {
color: gray;
}
label {
margin-left: 1em;
margin-right: 1em;
}
#errors {
border: 1px solid firebrick;
background: peachpuff;
color: darkred;
margin: 1em;
}
#messages {
border: 1px solid cornflowerblue;
background: lightcyan;
color: darkblue;
margin: 1em;
}
.default {
background: beige;
color: darkgray;
font-style: italic;
}
.icon {
height: 16px;
width: 16px;
}
</style>
</head>
<body>
<h1>Sihnon bittorrent utilities</h1>
<?php if ($errors) { ?>
<div id="errors">
<ul>
<?php foreach ($errors as $error) { ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php } ?>
</ul>
</div>
<?php } ?>
<?php if ($messages) { ?>
<div id="messages">
<ul>
<?php foreach ($messages as $message) { ?>
<li><?php echo htmlspecialchars($message); ?></li>
<?php } ?>
</ul>
</div>
<?php } ?>
<h2>Inject a seen episode title into the flexget seen list</h2>
<form action="<?=$self?>" method="post">
<fieldset>
<legend>Inject an entry into the list of seen TV episodes, and optionally download it</legend>
<p>If an URL is provided, the episode will be injected into the list of seen episodes, and also downloaded immediately. If the URL is left blank, the episode will be learned only.</p>
<input type="hidden" name="action" value="inject" />
<label for="inject">Title:</label><input type="text" id="inject" name="inject" value="some.show.s01e01.quality" class="default" />
<label for="injecturl">Url:</label><input type="text" id="injecturl" name="injecturl" value="http://" class="default" />
<input type="submit" id="injectSubmit" name="submit" value="Send" />
</fieldset>
</form>
<h2>Forget about an already seen episode</h2>
<form action="<?=$self?>" method="post">
<fieldset>
<legend>Forget about an already seen episode</legend>
<input type="hidden" name="action" value="series-forget" />
<label for="forgetSeries">Series:</label><input type="text" id="forgetSeries" name="series" value="some show" class="default" />
<label for="forgetEpisode">Episode:</label><input type="text" id="forgetEpisode" name="episode" value="s01e01" class="default" />
<input type="submit" id="forgetSubmit" name="submit" value="Send" />
</fieldset>
</form>
<h2>Currently known series/episodes</h2>
<form action="<?$self?>" method="post" id="listOperations">
<fieldset>
<legend></legend>
<input type="hidden" id="listAction" name="action" value="" />
<input type="hidden" id="listForgetSeries" name="series" value="" />
<input type="hidden" id="listForgetEpisode" name="episode" value="" />
<table id="seriesList">
<thead>
<tr>
<th>Series Name</th>
<th>Current episode</th>
<th>Qualities seen</th>
<th>Operations</th>
</tr>
</thead>
<?php foreach ($currentSeries as $series => $details) {?>
<tr>
<td><?=htmlspecialchars($series)?></td>
<td><?=htmlspecialchars($details['episode'])?></td>
<td><?=htmlspecialchars($details['quality'])?></td>
<td><a title="Forget" onclick="seriesForget('<?=htmlspecialchars($series)?>','<?=htmlspecialchars($details['episode'])?>')"><img class="icon" src="bin.png" /></td>
</tr>
<?php } ?>
</table>
</fieldset>
</body>
</html>