checkpoint sweeper
This commit is contained in:
parent
17ed75c684
commit
047bdc208f
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
for f in webif/plugin/sweeper/; do
|
||||
rsync -avr humax:/mod/$f ./$f
|
||||
rsync -avr --delete --exclude=.svn humax:/mod/$f ./$f
|
||||
done
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@ proc ::sweeper::unknown {cmd args} {
|
|||
return 0
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Helper functions
|
||||
|
||||
proc ::sweeper::expand {ts str} {
|
||||
if {[string first "%" $str] == -1} {
|
||||
return $str
|
||||
|
@ -140,6 +143,8 @@ proc ::sweeper::action {ts cmds} {
|
|||
log "ACTION: $cmd\($rest)" 2
|
||||
|
||||
switch $cmd {
|
||||
continue { return 0 }
|
||||
stop { return 1 }
|
||||
preserve { return 1 }
|
||||
move -
|
||||
movecreate {
|
||||
|
@ -241,6 +246,8 @@ proc ::sweeper::folder_action {ts cmds} {
|
|||
log "FOLDER ACTION: $cmd\($rest) @\[$folder]" 2
|
||||
|
||||
switch $cmd {
|
||||
continue { return 0 }
|
||||
stop { return 1 }
|
||||
preserve { return 1 }
|
||||
movecreate -
|
||||
move {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class
|
||||
source helper
|
||||
|
||||
set dir [cgi_get dir ""]
|
||||
|
||||
|
@ -14,99 +13,38 @@ if {$dir eq ""} {
|
|||
set cf "[system mediaroot]/$dir/.rulelist"
|
||||
}
|
||||
|
||||
jscss {schema.js script.js} style.css
|
||||
header
|
||||
|
||||
# Load rules
|
||||
if {![file exists $cf]} {
|
||||
set rules {}
|
||||
} else {
|
||||
if {[catch {set fp [open $cf r]} msg]} {
|
||||
log "Error opening sweeper ruleset ($cf), $msg" 0
|
||||
exit
|
||||
}
|
||||
set rules [split [$fp read] "\n"]
|
||||
}
|
||||
|
||||
jscss script.js style.css
|
||||
|
||||
puts "
|
||||
<fieldset width=100%>
|
||||
<legend>Sweeper rules for $dir</legend>
|
||||
<h3>
|
||||
<img src=img/icon22.png> Sweeper rules for
|
||||
<span class=dir>$dir</span>
|
||||
</h3>
|
||||
<div id=ruleset> </div>
|
||||
"
|
||||
|
||||
set lcomment ""
|
||||
proc comment {id comment} {
|
||||
set ::lcomment $comment
|
||||
}
|
||||
|
||||
proc rule {id rule} {
|
||||
global clausedescr lcomment
|
||||
|
||||
if {$lcomment eq ""} { set lcomment "Unnamed rule" }
|
||||
|
||||
puts "<div id=\"rule_${id}\"><fieldset width=100%><legend>"
|
||||
|
||||
puts "<div id=\"comment_${id}\" class=comment>$lcomment"
|
||||
puts "<img class=editbutton src=/img/context/edit.png></div>"
|
||||
puts "<div id=\"comment_${id}_edit\" class=\"commentedit edit hidden\">
|
||||
<input id=\"${id}_comment\" name=\"${id}_comment\"
|
||||
value=\"$lcomment\" size=120 maxlength=255></div>"
|
||||
|
||||
set lcomment ""
|
||||
|
||||
puts "</legend><table class=\"keyval cleft\">"
|
||||
set c 0
|
||||
while {[llength $rule] > 1} {
|
||||
incr c
|
||||
set rule [lassign $rule cmd arg]
|
||||
if {$cmd eq "action"} break
|
||||
|
||||
if {[dict exists $clausedescr $cmd]} {
|
||||
set title $clausedescr($cmd)
|
||||
} else {
|
||||
set title [string totitle $cmd]
|
||||
}
|
||||
puts "<tr><th nowrap>$title</th><td>"
|
||||
puts "<div id=\"rule_${id}_${c}\">"
|
||||
set broken 0
|
||||
if {[catch {::display::$cmd $id $arg}]} {
|
||||
puts "<i>$arg</i>"
|
||||
set broken 1
|
||||
}
|
||||
if {!$broken} {
|
||||
puts "<img class=editbutton src=/img/context/edit.png>"
|
||||
puts "</div>"
|
||||
puts "<div id=\"rule_${id}_${c}_edit\"
|
||||
class=\"clauseedit edit\" hidden>"
|
||||
::edit::$cmd "rule_${id}_${c}" $arg
|
||||
}
|
||||
puts "</div>"
|
||||
puts "</td></tr>"
|
||||
}
|
||||
puts "</table><table class=\"keyval left padleft\">
|
||||
<tr><th>Action</th><td>"
|
||||
puts $arg
|
||||
puts "</td></tr></table>"
|
||||
puts "</fieldset></div>"
|
||||
}
|
||||
|
||||
set n 0
|
||||
foreach rule $rules {
|
||||
incr n
|
||||
if {[string index $rule 0] eq "#"} {
|
||||
if {[string index $rule 1] ne "#"} {
|
||||
comment $n [string range $rule 1 end]
|
||||
}
|
||||
continue
|
||||
}
|
||||
if {[llength $rule] < 2} continue
|
||||
rule $n $rule
|
||||
}
|
||||
|
||||
puts "
|
||||
</table>
|
||||
puts {
|
||||
<div id=rule_template class="rule hidden">
|
||||
<fieldset class=rule>
|
||||
<legend class=comment>
|
||||
<span class=comment>Unnamed rule</span>
|
||||
<img class=edit src=/img/context/edit.png>
|
||||
</legend>
|
||||
<div class=criteria>
|
||||
<table class="criteria keyval"><tbody>
|
||||
<tr><th colspan=3 class=title>If all of:</th></tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<div class=action>
|
||||
<table class="action keyval"><tbody>
|
||||
<tr><th colspan=2 class=title>Then:</th></tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<div class="raw cleft"></div>
|
||||
</fieldset>
|
||||
"
|
||||
</div>
|
||||
}
|
||||
|
||||
footer
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
|
||||
proc ::edit::unknown {cmd args} {
|
||||
puts "Unhandled clause, $cmd"
|
||||
}
|
||||
|
||||
proc ::display::unknown {cmd args} {
|
||||
puts "Unhandled clause, $cmd"
|
||||
}
|
||||
|
||||
proc ::display::int {id val} {
|
||||
lassign $val op num
|
||||
|
||||
if {$num eq ""} {
|
||||
set num $op
|
||||
set op "=="
|
||||
}
|
||||
|
||||
puts [cgi_quote_html "$op $num"]
|
||||
}
|
||||
|
||||
proc ::edit::int {id val} {
|
||||
lassign $val op num
|
||||
|
||||
if {$num eq ""} {
|
||||
set num $op
|
||||
set op "=="
|
||||
}
|
||||
|
||||
puts "<select id=op_$id name=op_$id>"
|
||||
foreach pop {== > < >= <=} {
|
||||
set qpop [cgi_quote_html $pop]
|
||||
puts -nonewline "<option value=\"$qpop\""
|
||||
if {$op eq $pop} { puts -nonewline " selected" }
|
||||
puts ">$qpop"
|
||||
}
|
||||
puts "</select>"
|
||||
puts "<input name=\"num_$id\" type=number min=1 size=10 maxlength=10
|
||||
value=\"$num\">"
|
||||
}
|
||||
|
||||
proc ::display::substr {id val} {
|
||||
puts "contains '$val'"
|
||||
}
|
||||
|
||||
proc ::edit::substr {id val} {
|
||||
puts "<input name=\"str_$id\" type=text min=1
|
||||
size=40 maxlength=80 value=\"$val\">"
|
||||
}
|
||||
|
||||
set clausedescr {}
|
||||
|
||||
proc clause {id handler descr} {
|
||||
set ::clausedescr($id) $descr
|
||||
|
||||
alias ::display::$id ::display::$handler
|
||||
alias ::edit::$id ::edit::$handler
|
||||
}
|
||||
|
||||
source schema.def
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 612 B |
Binary file not shown.
After Width: | Height: | Size: 953 B |
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1,108 @@
|
|||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class
|
||||
|
||||
set dir [cgi_get dir ""]
|
||||
|
||||
set root [system mediaroot]
|
||||
|
||||
if {$dir eq "" || $dir eq $root} {
|
||||
set dir $root
|
||||
set cf "/mod/etc/sweeper.conf"
|
||||
} else {
|
||||
set cf "[system mediaroot]/$dir/.sweeper"
|
||||
}
|
||||
|
||||
httpheader "application/json"
|
||||
|
||||
# Load rules
|
||||
if {![file exists $cf]} {
|
||||
set rules {}
|
||||
} else {
|
||||
if {[catch {set fp [open $cf r]} msg]} {
|
||||
log "Error opening sweeper ruleset ($cf), $msg" 0
|
||||
exit
|
||||
}
|
||||
set rules [split [$fp read] "\n"]
|
||||
}
|
||||
|
||||
set lcomment ""
|
||||
proc comment {id comment} {
|
||||
set ::lcomment [string trim $comment]
|
||||
}
|
||||
|
||||
set json ""
|
||||
|
||||
proc add_json {str} {
|
||||
global json
|
||||
|
||||
append json $str
|
||||
}
|
||||
|
||||
proc quot {str} {
|
||||
return [cgi_quote_html $str]
|
||||
}
|
||||
|
||||
proc rule {id rule} {
|
||||
global clausedescr lcomment
|
||||
|
||||
if {$lcomment eq ""} { set lcomment "Unnamed rule" }
|
||||
if {[lindex $rule 0] eq "folder"} {
|
||||
set type "folder"
|
||||
set rule [lrange $rule 1 end]
|
||||
} else {
|
||||
set type "file"
|
||||
}
|
||||
|
||||
if {$id > 1} { add_json ",\n" }
|
||||
add_json " {\n"
|
||||
add_json " \"raw\": \"[quot $rule]\",\n"
|
||||
add_json " \"name\": \"[quot $lcomment]\",\n"
|
||||
add_json " \"type\": \"$type\",\n"
|
||||
add_json " \"criteria\": \[\n"
|
||||
|
||||
set lcomment ""
|
||||
|
||||
set c 0
|
||||
while {[llength $rule] > 1} {
|
||||
set rule [lassign $rule cmd arg]
|
||||
if {$cmd eq "action"} break
|
||||
if {$c} { add_json ",\n" }
|
||||
incr c
|
||||
|
||||
add_json " {\n"
|
||||
add_json " \"cmd\": \"[quot $cmd]\",\n"
|
||||
add_json " \"arg\": \"[quot $arg]\"\n"
|
||||
add_json " }"
|
||||
}
|
||||
add_json "\n"
|
||||
if {$cmd ne "action"} { set arg "continue" }
|
||||
lassign $arg cmd arg
|
||||
if {$cmd eq "preserve"} { set cmd 'stop' }
|
||||
add_json " ],\n"
|
||||
add_json " \"action\": {\n"
|
||||
add_json " \"cmd\": \"[quot $cmd]\",\n"
|
||||
add_json " \"arg\": \"[quot $arg]\"\n"
|
||||
add_json " }\n"
|
||||
add_json " }"
|
||||
}
|
||||
|
||||
add_json "\[\n"
|
||||
set n 0
|
||||
foreach rule $rules {
|
||||
if {[string index $rule 0] eq "#"} {
|
||||
if {[string index $rule 1] ne "#"} {
|
||||
comment $n [string range $rule 1 end]
|
||||
}
|
||||
continue
|
||||
}
|
||||
if {[llength $rule] < 2} continue
|
||||
incr n
|
||||
rule $n $rule
|
||||
}
|
||||
add_json "\n]\n"
|
||||
|
||||
puts $json
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
clause lcn int "Channel Number"
|
||||
clause duration int "Recording duration (in minutes)"
|
||||
clause schedduration int "Scheduled duration (in minutes)"
|
||||
clause size int "Recording size (in bytes)"
|
||||
#clause definition \
|
||||
# {select {{SD "Standard Definition"} {HD "High Definition"}} \
|
||||
# "Recording definition"
|
||||
clause title substr "Part of the recording title"
|
||||
clause synopsis substr "Part of the synopsis"
|
||||
clause guidance substr "Part of the guidance text"
|
||||
#clause flag tsflag "Recording flag"
|
||||
#clause genre tsgenre "Recording genre"
|
||||
#action preserve 0 "Leave recording alone"
|
||||
#action move folderpicker "Move recording to..."
|
|
@ -0,0 +1,122 @@
|
|||
var schema = {
|
||||
criterion: {
|
||||
lcn: {
|
||||
type: 'int',
|
||||
desc: 'Channel Number'
|
||||
},
|
||||
duration: {
|
||||
type: 'int',
|
||||
desc: 'Recording duration (in minutes)'
|
||||
},
|
||||
schedduration: {
|
||||
type: 'int',
|
||||
desc: 'Scheduled duration (in minutes)'
|
||||
},
|
||||
size: {
|
||||
type: 'int',
|
||||
desc: 'Recording size (in bytes)'
|
||||
},
|
||||
hour: {
|
||||
type: 'int',
|
||||
desc: 'Hour in which the recording started'
|
||||
},
|
||||
age: {
|
||||
type: 'int',
|
||||
desc: 'Age (in hours)'
|
||||
},
|
||||
wage: {
|
||||
type: 'int',
|
||||
desc: 'Time since last watched, or recorded (in hours)'
|
||||
},
|
||||
title: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the recording title'
|
||||
},
|
||||
synopsis: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the synopsis'
|
||||
},
|
||||
guidance: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the guidance text'
|
||||
},
|
||||
genre: {
|
||||
type: 'select',
|
||||
desc: 'Recording genre',
|
||||
select: {
|
||||
Unclassified: 'Unclassified',
|
||||
Film: 'Film',
|
||||
Children: 'Children',
|
||||
'News & Factual': 'News & Factual',
|
||||
Entertainment: 'Entertainment',
|
||||
Sport: 'Sport',
|
||||
Education: 'Education',
|
||||
Lifestyle: 'Lifestyle',
|
||||
Drama: 'Drama'
|
||||
}
|
||||
},
|
||||
definition: {
|
||||
type: 'select',
|
||||
desc: 'Recording definition',
|
||||
select: {
|
||||
SD: 'Standard Definition',
|
||||
HD: 'High Definition'
|
||||
}
|
||||
},
|
||||
flag: {
|
||||
type: 'select',
|
||||
desc: 'Recording flag',
|
||||
select: {
|
||||
Locked: 'Locked',
|
||||
New: 'New',
|
||||
Encrypted: 'Encrypted',
|
||||
Guidance: 'Guidance',
|
||||
ODEncrypted: 'Encrypted On-Disk',
|
||||
Shrunk: 'Shrunk',
|
||||
Deduped: 'De-duplicated'
|
||||
}
|
||||
},
|
||||
lock: {
|
||||
type: 'select',
|
||||
desc: 'Change recording lock',
|
||||
select: {
|
||||
1: 'Lock Recording',
|
||||
0: 'Unlock Recording'
|
||||
}
|
||||
}
|
||||
},
|
||||
action: {
|
||||
continue: {
|
||||
class: 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Continue to next rule'
|
||||
},
|
||||
stop: {
|
||||
class: 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Do nothing and stop processing rules'
|
||||
},
|
||||
move: {
|
||||
class: 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder...'
|
||||
},
|
||||
movecreate: {
|
||||
class: 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder (create folder if necessary)'
|
||||
},
|
||||
fileunder: {
|
||||
class: 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Scan for folder of same name and merge'
|
||||
},
|
||||
fileundercreate: {
|
||||
class: 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Scan for folder of same name and merge ' +
|
||||
'(create folder if necessary)'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,18 +1,99 @@
|
|||
|
||||
var printers = {
|
||||
int: function(cmd, a) {
|
||||
var b = a.split(" ");
|
||||
if (b.length == 1)
|
||||
{
|
||||
op = '=';
|
||||
val = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = b[0];
|
||||
val = b[1];
|
||||
}
|
||||
return op + ' ' + val;
|
||||
},
|
||||
substr: function(cmd, a) {
|
||||
return a;
|
||||
},
|
||||
select: function(cmd, a) {
|
||||
return schema.criterion[cmd].select[a];
|
||||
}
|
||||
};
|
||||
|
||||
function criterion(data)
|
||||
{
|
||||
var c = schema.criterion[data.cmd];
|
||||
var s;
|
||||
|
||||
s = '<tr><th>' + c.desc + '</th><td>';
|
||||
|
||||
if (printers[c.type])
|
||||
s += printers[c.type](data.cmd, data.arg);
|
||||
else
|
||||
s += 'RAW (' + data.arg + ')';
|
||||
|
||||
s += '</td><td>' +
|
||||
'<img class=edit src=/img/context/edit.png>' +
|
||||
' ' +
|
||||
'<img class=delete src=/img/context/delete.png>' +
|
||||
'</td></tr>';
|
||||
return s;
|
||||
}
|
||||
|
||||
function action(data)
|
||||
{
|
||||
var c = schema.action[data.cmd];
|
||||
var s;
|
||||
|
||||
s = '<tr>' +
|
||||
'<th>' + c.desc + '</th>' +
|
||||
'<td>' + data.arg + '</td>' +
|
||||
'</tr>';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function addrule(id, data)
|
||||
{
|
||||
var rule = $('#rule_template')
|
||||
.clone()
|
||||
.attr('id', 'rule_' + id)
|
||||
.removeClass('hidden');
|
||||
rule.find('span.comment').text(data.name);
|
||||
|
||||
var $c = rule.find('table.criteria');
|
||||
$.each(data.criteria, function(key, val) {
|
||||
$($c).find('tbody').append(criterion(val));
|
||||
});
|
||||
|
||||
var $a = rule.find('table.action');
|
||||
$($a).find('tbody').append(action(data.action));
|
||||
|
||||
rule.find('.raw').html(data.raw);
|
||||
|
||||
// rule.find('.raw').append('<pre>' + JSON.stringify(data) + '</pre>');
|
||||
|
||||
$('#ruleset').append(rule);
|
||||
}
|
||||
|
||||
function loadrules(dir)
|
||||
{
|
||||
$('#ruleset')
|
||||
.html('<img src=/img/loading.gif> Loading rules...');
|
||||
$.getJSON('rules_json.jim', 'dir=' + dir, function(data) {
|
||||
$('#ruleset').empty();
|
||||
$.each(data, function(key, val) {
|
||||
addrule(key, val);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
$('img.editbutton').hover(
|
||||
function() { $(this).css('cursor', 'pointer'); },
|
||||
function() { $(this).css('cursor', 'auto'); }
|
||||
).on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var id = $(this).parent().attr('id');
|
||||
console.log('%O', id);
|
||||
$('.edit').hide('fast');
|
||||
$('#' + id + '_edit').show('slow');
|
||||
});;
|
||||
loadrules($('span.dir').text());
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,35 @@
|
|||
|
||||
fieldset
|
||||
{
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
div.action
|
||||
{
|
||||
padding-left: 1em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.criteria
|
||||
{
|
||||
clear: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.raw
|
||||
{
|
||||
font-style: italic;
|
||||
color: #ff4000;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
th.title
|
||||
{
|
||||
line-height: 1em;
|
||||
text-align: left !important;
|
||||
background: #eee !important;
|
||||
}
|
||||
|
||||
div.comment
|
||||
{
|
||||
font-style: italic;
|
||||
|
|
Loading…
Reference in New Issue