sweeper 2.0.0 + add and/or, tooltips, moveset
This commit is contained in:
parent
270701873d
commit
d5319e6f0d
|
@ -1 +0,0 @@
|
||||||
etc/sweeper.conf
|
|
|
@ -1,9 +1,9 @@
|
||||||
Package: sweeper
|
Package: sweeper
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Section: misc
|
Section: misc
|
||||||
Version: 1.0.19
|
Version: 2.0.0
|
||||||
Architecture: mipsel
|
Architecture: mipsel
|
||||||
Maintainer: af123@hummypkg.org.uk
|
Maintainer: af123@hummypkg.org.uk
|
||||||
Depends: webif(>=1.0.14-8)
|
Depends: webif(>=1.0.14-10)
|
||||||
Description: Sweeper is a package for managing recordings in a variety of ways using custom rules [Add delete action. Some online help.]
|
Description: Sweeper is a package for managing recordings in a variety of ways using custom rules [Add and/or clauses. See forum.]
|
||||||
Tags: http://hummy.tv/forum/threads/5138/
|
Tags: http://hummy.tv/forum/threads/5138/
|
||||||
|
|
|
@ -69,67 +69,135 @@ proc ::sweeper::strcontains {ref val} {
|
||||||
>= 0]
|
>= 0]
|
||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
proc ::sweeper::moveset {ts dst {op rename}} {
|
||||||
# Rule criteria
|
set file [$ts get file]
|
||||||
|
log "${op}set($file) -> $dst" 0
|
||||||
|
|
||||||
proc ::sweeper::flag {ts flag} {
|
# Handle alias for rename
|
||||||
|
if {$op eq "move"} { set op "rename" }
|
||||||
|
|
||||||
|
# Determine whether this is a cross-filesystem move.
|
||||||
|
file stat [$ts get file] sts
|
||||||
|
file stat $dst std
|
||||||
|
set xfs 0
|
||||||
|
if {$sts(dev) ne $std(dev)} {
|
||||||
|
log " Cross-filesystem - will copy then delete." 0
|
||||||
|
set xfs 1
|
||||||
|
}
|
||||||
|
|
||||||
|
set fset [lsort [$ts fileset]]
|
||||||
|
|
||||||
|
if {$xfs && $op eq "rename"} {
|
||||||
|
# For cross-filesystem moves, copy the whole file set
|
||||||
|
# and then delete the originals if all the copies were
|
||||||
|
# successful.
|
||||||
|
foreach f $fset {
|
||||||
|
set tail [file tail $f]
|
||||||
|
if {[catch {file copy $f "$dst/$tail"} msg]} {
|
||||||
|
log " ....... $f: XFS copy failed, $msg." 0
|
||||||
|
file delete -force "$dst/$tail"
|
||||||
|
log " .... Leaving originals intact." 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log " ....... $f: OK" 0
|
||||||
|
}
|
||||||
|
log " Now deleting original files." 0
|
||||||
|
foreach f $fset {
|
||||||
|
set tail [file tail $f]
|
||||||
|
if {[file exists "$dst/$tail"] &&
|
||||||
|
[file size "$dst/$tail"] ==
|
||||||
|
[file size $f]} {
|
||||||
|
file tdelete $f
|
||||||
|
log " ....... $f: OK" 0
|
||||||
|
} else {
|
||||||
|
log " ....... $f: ERROR, sizes differ." 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Otherwise - copy or local FS move.
|
||||||
|
|
||||||
|
foreach f $fset {
|
||||||
|
set tail [file tail $f]
|
||||||
|
if {$op eq "copy" && [file exists "$dst/$tail"]} {
|
||||||
|
if {[file size "$dst/$tail"] == [file size $f]} {
|
||||||
|
log " ....... $f: Already copied." 2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log "Deleting truncated copy $dst/$tail" 0
|
||||||
|
file tdelete "$dst/$tail"
|
||||||
|
}
|
||||||
|
log " ....... $f"
|
||||||
|
if {[catch {file $op $f "$dst/[file tail $f]"} msg]} {
|
||||||
|
log "$op failed, $msg.", 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Rule conditions
|
||||||
|
|
||||||
|
proc ::sweeper::flag {ts flag folder} {
|
||||||
return [$ts flag $flag]
|
return [$ts flag $flag]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::lcn {ts num} {
|
proc ::sweeper::lcn {ts num folder} {
|
||||||
return [::sweeper::intcomp [$ts get channel_num] $num]
|
return [::sweeper::intcomp [$ts get channel_num] $num]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::duration {ts dur} {
|
proc ::sweeper::duration {ts dur folder} {
|
||||||
return [::sweeper::intcomp [$ts duration] $dur]
|
return [::sweeper::intcomp [$ts duration] $dur]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::hour {ts str} {
|
proc ::sweeper::hour {ts str folder} {
|
||||||
set hour [clock format [$ts get start] -format "%H"]
|
set hour [clock format [$ts get start] -format "%H"]
|
||||||
return [::sweeper::intcomp $hour $str]
|
return [::sweeper::intcomp $hour $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::schedduration {ts dur} {
|
proc ::sweeper::schedduration {ts dur folder} {
|
||||||
return [::sweeper::intcomp [$ts get scheddur] $dur]
|
return [::sweeper::intcomp [$ts get scheddur] $dur]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::size {ts size} {
|
proc ::sweeper::size {ts size folder} {
|
||||||
return [::sweeper::intcomp [$ts size] $size]
|
return [::sweeper::intcomp [$ts size] $size]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::age {ts age} {
|
proc ::sweeper::age {ts age folder} {
|
||||||
set recage $(([clock seconds] - [$ts get end]) / 3600)
|
set recage $(([clock seconds] - [$ts get end]) / 3600)
|
||||||
log " ... Recording age: $recage" 2
|
log " ... Recording age: $recage" 2
|
||||||
return [::sweeper::intcomp $recage $age]
|
return [::sweeper::intcomp $recage $age]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::wage {ts age} {
|
proc ::sweeper::wage {ts age folder} {
|
||||||
set recage $(([clock seconds] - [$ts lastmod]) / 3600)
|
set recage $(([clock seconds] - [$ts lastmod]) / 3600)
|
||||||
log " ... Watched age: $recage" 2
|
log " ... Watched age: $recage" 2
|
||||||
return [::sweeper::intcomp $recage $age]
|
return [::sweeper::intcomp $recage $age]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::definition {ts def} {
|
proc ::sweeper::definition {ts def folder} {
|
||||||
return [::sweeper::strcontains [$ts get definition] $def]
|
return [::sweeper::strcontains [$ts get definition] $def]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::filename {ts str} {
|
proc ::sweeper::filename {ts str folder} {
|
||||||
return [::sweeper::strcontains [$ts bfile] $str]
|
return [::sweeper::strcontains [$ts bfile] $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::title {ts str} {
|
proc ::sweeper::title {ts str folder} {
|
||||||
return [::sweeper::strcontains [$ts get title] $str]
|
return [::sweeper::strcontains [$ts get title] $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::synopsis {ts str} {
|
proc ::sweeper::synopsis {ts str folder} {
|
||||||
return [::sweeper::strcontains [$ts get synopsis] $str]
|
return [::sweeper::strcontains [$ts get synopsis] $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::guidance {ts str} {
|
proc ::sweeper::guidance {ts str folder} {
|
||||||
return [::sweeper::strcontains [$ts get guidance] $str]
|
return [::sweeper::strcontains [$ts get guidance] $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::genre {ts genre} {
|
proc ::sweeper::genre {ts genre folder} {
|
||||||
set glist [ts genrelist]
|
set glist [ts genrelist]
|
||||||
|
|
||||||
set tsg [$ts get genre]
|
set tsg [$ts get genre]
|
||||||
|
@ -139,7 +207,7 @@ proc ::sweeper::genre {ts genre} {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::lock {ts g} {
|
proc ::sweeper::lock {ts g folder} {
|
||||||
if {$g} {
|
if {$g} {
|
||||||
if {![$ts flag Locked]} {
|
if {![$ts flag Locked]} {
|
||||||
log "Locked recording." 0
|
log "Locked recording." 0
|
||||||
|
@ -154,13 +222,13 @@ proc ::sweeper::lock {ts g} {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::folder_fflag {ts flag} {
|
proc ::sweeper::folder_fflag {ts flag folder} {
|
||||||
return [file exists "[file dirname [$ts get file]]/.$flag"]
|
return [file exists "[file dirname [$ts get file]]/.$flag"]
|
||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
proc ::sweeper::action {ts cmds} {
|
proc ::sweeper::action {ts cmds folder} {
|
||||||
global root
|
global root
|
||||||
|
|
||||||
lassign $cmds cmd rest
|
lassign $cmds cmd rest
|
||||||
|
@ -171,12 +239,19 @@ proc ::sweeper::action {ts cmds} {
|
||||||
continue { return 0 }
|
continue { return 0 }
|
||||||
stop { return 1 }
|
stop { return 1 }
|
||||||
preserve { return 1 }
|
preserve { return 1 }
|
||||||
|
copy -
|
||||||
|
copycreate -
|
||||||
move -
|
move -
|
||||||
movecreate {
|
movecreate {
|
||||||
set rest [::sweeper::expand $ts $rest]
|
set rest [::sweeper::expand $ts $rest]
|
||||||
set dir [::sweeper::resolvedir $rest]
|
set dir [::sweeper::resolvedir $rest]
|
||||||
|
set create 0
|
||||||
|
if {[string range $cmd end-5 end] eq "create"} {
|
||||||
|
set create 1
|
||||||
|
set cmd [string range $cmd 0 end-6]
|
||||||
|
}
|
||||||
if {![file isdirectory $dir]} {
|
if {![file isdirectory $dir]} {
|
||||||
if {$cmd eq "move"} {
|
if {!$create} {
|
||||||
log " ... No such directory $dir" 2
|
log " ... No such directory $dir" 2
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -190,14 +265,11 @@ proc ::sweeper::action {ts cmds} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log "Moving [$ts get file] to $rest" 0
|
log "$cmd [$ts get file] to $rest" 0
|
||||||
foreach f [$ts fileset] {
|
if {!$::sweeper::dryrun} {
|
||||||
log " ....... $f"
|
::sweeper::moveset $ts $dir $cmd
|
||||||
if {!$::sweeper::dryrun} {
|
if {"$dir" ni $::sweeper::recalc} {
|
||||||
file rename $f "$dir/[file tail $f]"
|
lappend ::sweeper::recalc $dir
|
||||||
if {"$dir" ni $::sweeper::recalc} {
|
|
||||||
lappend ::sweeper::recalc $dir
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
|
@ -291,7 +363,8 @@ proc ::sweeper::folder_apply {dir callback} {
|
||||||
|
|
||||||
proc ::sweeper:folder_merge {src dst {op rename}} {
|
proc ::sweeper:folder_merge {src dst {op rename}} {
|
||||||
if {$src eq $dst} return
|
if {$src eq $dst} return
|
||||||
log "Moving recordings from $src to $dst" 0
|
if {$op eq "move"} { set op "rename" }
|
||||||
|
log "$op recordings from $src to $dst" 0
|
||||||
foreach e [readdir -nocomplain $src] {
|
foreach e [readdir -nocomplain $src] {
|
||||||
if {![string match {*.ts} $e]} continue
|
if {![string match {*.ts} $e]} continue
|
||||||
set entry "$src/$e"
|
set entry "$src/$e"
|
||||||
|
@ -313,12 +386,7 @@ proc ::sweeper:folder_merge {src dst {op rename}} {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach f [$ts fileset] {
|
::sweeper::moveset $ts $dst $op
|
||||||
if {$op eq "copy" \
|
|
||||||
&& [file exists "$dst/[file tail $f]"]} continue
|
|
||||||
log " ....... $f"
|
|
||||||
file $op $f "$dst/[file tail $f]"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if {$op eq "rename" && ![system rmdir_if_empty $src]} {
|
if {$op eq "rename" && ![system rmdir_if_empty $src]} {
|
||||||
log "Failed to remove directory" 0
|
log "Failed to remove directory" 0
|
||||||
|
@ -331,7 +399,7 @@ proc ::sweeper:folder_merge {src dst {op rename}} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ::sweeper::folder_action {ts cmds} {
|
proc ::sweeper::folder_action {ts cmds folder} {
|
||||||
global root
|
global root
|
||||||
|
|
||||||
lassign $cmds cmd rest
|
lassign $cmds cmd rest
|
||||||
|
@ -345,12 +413,19 @@ proc ::sweeper::folder_action {ts cmds} {
|
||||||
continue { return 0 }
|
continue { return 0 }
|
||||||
stop { return 1 }
|
stop { return 1 }
|
||||||
preserve { return 1 }
|
preserve { return 1 }
|
||||||
|
copycreate -
|
||||||
|
copy -
|
||||||
movecreate -
|
movecreate -
|
||||||
move {
|
move {
|
||||||
set rest [::sweeper::expand $ts $rest]
|
set rest [::sweeper::expand $ts $rest]
|
||||||
set dir [::sweeper::resolvedir $rest]
|
set dir [::sweeper::resolvedir $rest]
|
||||||
|
set create 0
|
||||||
|
if {[string range $cmd end-5 end] eq "create"} {
|
||||||
|
set create 1
|
||||||
|
set cmd [string range $cmd 0 end-6]
|
||||||
|
}
|
||||||
if {![file isdirectory $dir]} {
|
if {![file isdirectory $dir]} {
|
||||||
if {$cmd eq "move"} {
|
if {!$create} {
|
||||||
log " ... No such directory $dir" 2
|
log " ... No such directory $dir" 2
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -365,7 +440,7 @@ proc ::sweeper::folder_action {ts cmds} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if {!$::sweeper::dryrun} {
|
if {!$::sweeper::dryrun} {
|
||||||
::sweeper:folder_merge $folder $dir
|
::sweeper:folder_merge $folder $dir $cmd
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -450,6 +525,64 @@ proc ::sweeper::folder_action {ts cmds} {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc ::sweeper::or {ts clause folder} {
|
||||||
|
log " --> OR:" 2
|
||||||
|
set ret 0
|
||||||
|
while {[llength $clause] > 1} {
|
||||||
|
set clause [lassign $clause cmd arg]
|
||||||
|
set ret [::sweeper::clause $folder $cmd $arg $ts]
|
||||||
|
if {$ret} {
|
||||||
|
log " <-- OR true." 2
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {!$ret} {
|
||||||
|
log " <-- OR false." 2
|
||||||
|
}
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
proc ::sweeper::and {ts clause folder} {
|
||||||
|
log " --> AND:" 2
|
||||||
|
set ret 0
|
||||||
|
while {[llength $clause] > 1} {
|
||||||
|
set clause [lassign $clause cmd arg]
|
||||||
|
set ret [::sweeper::clause $folder $cmd $arg $ts]
|
||||||
|
if {!$ret} {
|
||||||
|
log " <-- AND false." 2
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$ret} {
|
||||||
|
log " <-- AND true." 2
|
||||||
|
}
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
proc ::sweeper::clause {folder cmd arg ts} {
|
||||||
|
log " $cmd\($arg)" 2
|
||||||
|
|
||||||
|
if {[string index $cmd 0] eq "!"} {
|
||||||
|
set negate 1
|
||||||
|
set cmd [string range $cmd 1 end]
|
||||||
|
} else {
|
||||||
|
set negate 0
|
||||||
|
}
|
||||||
|
if {$folder && [exists -proc ::sweeper::folder_$cmd]} {
|
||||||
|
set ret [::sweeper::folder_$cmd $ts $arg $folder]
|
||||||
|
} else {
|
||||||
|
set ret [::sweeper::$cmd $ts $arg $folder]
|
||||||
|
}
|
||||||
|
if {$cmd eq "action"} { return $ret }
|
||||||
|
if {$negate} { set ret $(!$ret) }
|
||||||
|
if {!$ret} {
|
||||||
|
log " Nomatch" 2
|
||||||
|
} else {
|
||||||
|
log " MATCH" 2
|
||||||
|
}
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
proc ::sweeper::runrule {ts rule} {
|
proc ::sweeper::runrule {ts rule} {
|
||||||
log "Processing \[$rule]" 2
|
log "Processing \[$rule]" 2
|
||||||
|
|
||||||
|
@ -462,25 +595,9 @@ proc ::sweeper::runrule {ts rule} {
|
||||||
}
|
}
|
||||||
while {[llength $rule] > 1} {
|
while {[llength $rule] > 1} {
|
||||||
set rule [lassign $rule cmd arg]
|
set rule [lassign $rule cmd arg]
|
||||||
log " $cmd\($arg)" 2
|
set ret [::sweeper::clause $folder $cmd $arg $ts]
|
||||||
if {[string index $cmd 0] eq "!"} {
|
|
||||||
set negate 1
|
|
||||||
set cmd [string range $cmd 1 end]
|
|
||||||
} else {
|
|
||||||
set negate 0
|
|
||||||
}
|
|
||||||
if {$folder && [exists -proc ::sweeper::folder_$cmd]} {
|
|
||||||
set ret [::sweeper::folder_$cmd $ts $arg]
|
|
||||||
} else {
|
|
||||||
set ret [::sweeper::$cmd $ts $arg]
|
|
||||||
}
|
|
||||||
if {$cmd eq "action"} { return $ret }
|
if {$cmd eq "action"} { return $ret }
|
||||||
if {$negate} { set ret $(!$ret) }
|
if {!$ret} break
|
||||||
if {!$ret} {
|
|
||||||
log " Nomatch" 2
|
|
||||||
break
|
|
||||||
}
|
|
||||||
log " MATCH" 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -498,12 +615,18 @@ proc ::sweeper::apply {dir cf} {
|
||||||
$fp close
|
$fp close
|
||||||
|
|
||||||
set runfolder 0
|
set runfolder 0
|
||||||
|
set nrules 0
|
||||||
foreach rule $rules {
|
foreach rule $rules {
|
||||||
if {[lindex $rule 0] eq "folder"} { incr runfolder }
|
if {[lindex $rule 0] eq "folder"} { incr runfolder }
|
||||||
|
if {[string index $rule 0] ne "#" && [llength $rule] > 1} {
|
||||||
|
incr nrules
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if {!$nrules} return
|
||||||
|
|
||||||
log "" 2
|
log "" 2
|
||||||
log "--- SWEEP SCAN STARTING FOR $dir ---" 2
|
log "--- SWEEP SCAN STARTING FOR $dir ($nrules) ---" 2
|
||||||
log "" 2
|
log "" 2
|
||||||
|
|
||||||
foreach e [readdir -nocomplain $dir] {
|
foreach e [readdir -nocomplain $dir] {
|
||||||
|
@ -530,7 +653,7 @@ proc ::sweeper::apply {dir cf} {
|
||||||
|
|
||||||
foreach rule $rules {
|
foreach rule $rules {
|
||||||
if {[lindex $rule 0] eq "folder"} continue
|
if {[lindex $rule 0] eq "folder"} continue
|
||||||
if {[string index $rule 0] eq "#" || \
|
if {[string index $rule 0] eq "#" ||
|
||||||
[llength $rule] < 2} continue
|
[llength $rule] < 2} continue
|
||||||
if {[::sweeper::runrule $ts $rule]} break
|
if {[::sweeper::runrule $ts $rule]} break
|
||||||
}
|
}
|
||||||
|
@ -608,7 +731,7 @@ proc ::sweeper::apply {dir cf} {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach rule $rules {
|
foreach rule $rules {
|
||||||
if {[string index $rule 0] eq "#" || \
|
if {[string index $rule 0] eq "#" ||
|
||||||
[llength $rule] < 2} continue
|
[llength $rule] < 2} continue
|
||||||
if {[lindex $rule 0] ne "folder"} continue
|
if {[lindex $rule 0] ne "folder"} continue
|
||||||
if {[::sweeper::runrule $ts $rule]} break
|
if {[::sweeper::runrule $ts $rule]} break
|
||||||
|
|
|
@ -74,30 +74,29 @@ Add pre-defined ruleset:
|
||||||
</span>
|
</span>
|
||||||
<a class=enadisrule href=#>
|
<a class=enadisrule href=#>
|
||||||
<img src=img/disable.png
|
<img src=img/disable.png
|
||||||
alt="Enable/Disable Rule"
|
|
||||||
title="Enable/Disable Rule">
|
title="Enable/Disable Rule">
|
||||||
</a>
|
</a>
|
||||||
<a class=delrule href=#>
|
<a class=delrule href=#>
|
||||||
<img src=/img/context/delete.png
|
<img src=/img/context/delete.png
|
||||||
alt="Delete Rule" title="Delete Rule">
|
title="Delete Rule">
|
||||||
</a>
|
</a>
|
||||||
<a class=cprule href=#>
|
<a class=cprule href=#>
|
||||||
<img src=/img/context/page_white_copy.png
|
<img src=/img/context/page_white_copy.png
|
||||||
alt="Duplicate Rule" title="Duplicate Rule">
|
title="Duplicate Rule">
|
||||||
</a>
|
</a>
|
||||||
<a class=uprule href=#>
|
<a class=uprule href=#>
|
||||||
<img src=/img/nav/up.png
|
<img src=/img/nav/up.png
|
||||||
alt="Move Rule Up" title="Move Rule Up">
|
title="Move Rule Up">
|
||||||
</a>
|
</a>
|
||||||
<a class=downrule href=#>
|
<a class=downrule href=#>
|
||||||
<img src=/img/nav/down.png
|
<img src=/img/nav/down.png
|
||||||
alt="Move Rule Down" title="Move Rule Down">
|
title="Move Rule Down">
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</legend>
|
</legend>
|
||||||
<a href=# class=addcriterion>
|
<a href=# class=addcriterion>
|
||||||
<img src=/img/context/plus.png
|
<img src=img/plus.png
|
||||||
alt="Add condition" title="Add condition">
|
title="Add condition">
|
||||||
</a>
|
</a>
|
||||||
<div class=criteria>
|
<div class=criteria>
|
||||||
<table class="criteria"><tbody></tbody></table>
|
<table class="criteria"><tbody></tbody></table>
|
||||||
|
@ -153,7 +152,7 @@ Add pre-defined ruleset:
|
||||||
<select id=newcondition_cmd name=newcondition_cmd></select>
|
<select id=newcondition_cmd name=newcondition_cmd></select>
|
||||||
</td></tr><tr><th>Negate?</th><td>
|
</td></tr><tr><th>Negate?</th><td>
|
||||||
<input id=newcondition_negate name=newcondition_negate type=checkbox
|
<input id=newcondition_negate name=newcondition_negate type=checkbox
|
||||||
value='1' />
|
value='1' title="Invert the sense of the condition."/>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
source /mod/webif/lib/setup
|
||||||
|
require lock system.class ts.class pretty_size browse.class \
|
||||||
|
safe_delete settings.class plugin
|
||||||
|
|
||||||
|
proc log {msg {level 1}} {
|
||||||
|
puts "[\
|
||||||
|
clock format [clock seconds] -format "%d/%m/%Y %H:%M"\
|
||||||
|
] - $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc elapsed {start} {
|
||||||
|
return $(([clock milliseconds] - $start) / 1000.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
proc startclock {} {
|
||||||
|
set ::startclock_s [clock milliseconds]
|
||||||
|
}
|
||||||
|
|
||||||
|
proc endclock {size} {
|
||||||
|
set el [elapsed $::startclock_s]
|
||||||
|
set rate $($size / $el)
|
||||||
|
return "[pretty_size $size] in $el seconds - [pretty_size $rate]/s"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc register {args} {}
|
||||||
|
|
||||||
|
proc scan_run {dir flag callback} {
|
||||||
|
global dustbin
|
||||||
|
|
||||||
|
if {[string match {\[*} [file tail $dir]]} return
|
||||||
|
|
||||||
|
if {[file exists "$dir/.$flag"]} { $callback $dir }
|
||||||
|
|
||||||
|
foreach entry [readdir -nocomplain $dir] {
|
||||||
|
if {[file isdirectory "$dir/$entry"]} {
|
||||||
|
scan_run "$dir/$entry" $flag $callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set root [system mediaroot]
|
||||||
|
|
||||||
|
source auto.hook
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -6,6 +6,10 @@ require system.class
|
||||||
|
|
||||||
set dir [cgi_get dir ""]
|
set dir [cgi_get dir ""]
|
||||||
|
|
||||||
|
if {$dir eq "" && [llength $argv]} {
|
||||||
|
set dir [lindex $argv 0]
|
||||||
|
}
|
||||||
|
|
||||||
set root [system mediaroot]
|
set root [system mediaroot]
|
||||||
|
|
||||||
if {$dir eq "" || $dir eq $root} {
|
if {$dir eq "" || $dir eq $root} {
|
||||||
|
@ -45,8 +49,43 @@ proc quot {str} {
|
||||||
return [cgi_quote_html $str]
|
return [cgi_quote_html $str]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set composite {and or}
|
||||||
|
|
||||||
|
proc clause {cmd arg {indent 6}} {
|
||||||
|
global lockfound composite
|
||||||
|
|
||||||
|
set istr [string repeat " " $indent]
|
||||||
|
|
||||||
|
if {[string index $cmd 0] eq "!"} {
|
||||||
|
set negate 1
|
||||||
|
set cmd [string range $cmd 1 end]
|
||||||
|
} else {
|
||||||
|
set negate 0
|
||||||
|
}
|
||||||
|
if {$cmd eq "lock"} { set lockfound $arg }
|
||||||
|
|
||||||
|
add_json "$istr{\n"
|
||||||
|
add_json "$istr \"negate\": $negate,\n"
|
||||||
|
add_json "$istr \"cmd\": \"[quot $cmd]\",\n"
|
||||||
|
add_json "$istr \"arg\": \"[quot $arg]\""
|
||||||
|
if {$cmd in $composite} {
|
||||||
|
add_json ",\n"
|
||||||
|
add_json "$istr \"criteria\": \[\n"
|
||||||
|
set c 0
|
||||||
|
while {[llength $arg] > 1} {
|
||||||
|
set arg [lassign $arg subcmd subarg]
|
||||||
|
if {$c} { add_json ",\n" }
|
||||||
|
incr c
|
||||||
|
clause $subcmd $subarg $($indent + 6)
|
||||||
|
}
|
||||||
|
add_json "\n$istr ]"
|
||||||
|
}
|
||||||
|
add_json "\n"
|
||||||
|
add_json "$istr}"
|
||||||
|
}
|
||||||
|
|
||||||
proc rule {id rule} {
|
proc rule {id rule} {
|
||||||
global clausedescr lcomment
|
global lcomment lockfound
|
||||||
|
|
||||||
set enabled 1
|
set enabled 1
|
||||||
if {[lindex $rule 0] eq "##"} {
|
if {[lindex $rule 0] eq "##"} {
|
||||||
|
@ -76,22 +115,11 @@ proc rule {id rule} {
|
||||||
set lockfound -1
|
set lockfound -1
|
||||||
while {[llength $rule] > 1} {
|
while {[llength $rule] > 1} {
|
||||||
set rule [lassign $rule cmd arg]
|
set rule [lassign $rule cmd arg]
|
||||||
if {[string index $cmd 0] eq "!"} {
|
|
||||||
set negate 1
|
|
||||||
set cmd [string range $cmd 1 end]
|
|
||||||
} else {
|
|
||||||
set negate 0
|
|
||||||
}
|
|
||||||
if {$cmd eq "action"} break
|
if {$cmd eq "action"} break
|
||||||
if {$cmd eq "lock"} { set lockfound $arg }
|
|
||||||
if {$c} { add_json ",\n" }
|
if {$c} { add_json ",\n" }
|
||||||
incr c
|
incr c
|
||||||
|
|
||||||
add_json " {\n"
|
clause $cmd $arg
|
||||||
add_json " \"negate\": $negate,\n"
|
|
||||||
add_json " \"cmd\": \"[quot $cmd]\",\n"
|
|
||||||
add_json " \"arg\": \"[quot $arg]\"\n"
|
|
||||||
add_json " }"
|
|
||||||
}
|
}
|
||||||
add_json "\n"
|
add_json "\n"
|
||||||
if {$cmd ne "action"} {
|
if {$cmd ne "action"} {
|
||||||
|
|
|
@ -4,42 +4,49 @@ var schema = {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Logical Channel Number',
|
desc: 'Logical Channel Number',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
duration: {
|
duration: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Recording duration (in minutes)',
|
desc: 'Recording duration (in minutes)',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
schedduration: {
|
schedduration: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Scheduled duration (in minutes)',
|
desc: 'Scheduled duration (in minutes)',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Recording size (in bytes)',
|
desc: 'Recording size (in bytes)',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
hour: {
|
hour: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Hour in which the recording started',
|
desc: 'Hour in which the recording started',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
age: {
|
age: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Age (in hours)',
|
desc: 'Age (in hours)',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
wage: {
|
wage: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'int',
|
type: 'int',
|
||||||
desc: 'Time since last watched, or recorded (in hours)',
|
desc: 'Time since last watched, or recorded (in hours)',
|
||||||
|
negate: true,
|
||||||
def: "0"
|
def: "0"
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
|
@ -47,6 +54,7 @@ var schema = {
|
||||||
type: 'substr',
|
type: 'substr',
|
||||||
desc: 'Recording Title contains',
|
desc: 'Recording Title contains',
|
||||||
idesc: 'Recording Title does not contain',
|
idesc: 'Recording Title does not contain',
|
||||||
|
negate: true,
|
||||||
def: 'Enter text here...'
|
def: 'Enter text here...'
|
||||||
},
|
},
|
||||||
synopsis: {
|
synopsis: {
|
||||||
|
@ -54,6 +62,7 @@ var schema = {
|
||||||
type: 'substr',
|
type: 'substr',
|
||||||
desc: 'Synopsis contains',
|
desc: 'Synopsis contains',
|
||||||
idesc: 'Synopsis does not contain',
|
idesc: 'Synopsis does not contain',
|
||||||
|
negate: true,
|
||||||
def: 'Enter text here...'
|
def: 'Enter text here...'
|
||||||
},
|
},
|
||||||
guidance: {
|
guidance: {
|
||||||
|
@ -61,12 +70,14 @@ var schema = {
|
||||||
type: 'substr',
|
type: 'substr',
|
||||||
desc: 'Guidance Text contains',
|
desc: 'Guidance Text contains',
|
||||||
idesc: 'Guidance Text does not contain',
|
idesc: 'Guidance Text does not contain',
|
||||||
|
negate: true,
|
||||||
def: 'Enter text here...'
|
def: 'Enter text here...'
|
||||||
},
|
},
|
||||||
genre: {
|
genre: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
desc: 'Recording Genre',
|
desc: 'Recording Genre',
|
||||||
|
negate: true,
|
||||||
select: {
|
select: {
|
||||||
Unclassified: 'Unclassified',
|
Unclassified: 'Unclassified',
|
||||||
Film: 'Film',
|
Film: 'Film',
|
||||||
|
@ -84,6 +95,7 @@ var schema = {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
desc: 'Recording Definition',
|
desc: 'Recording Definition',
|
||||||
|
negate: true,
|
||||||
select: {
|
select: {
|
||||||
SD: 'Standard Definition',
|
SD: 'Standard Definition',
|
||||||
HD: 'High Definition'
|
HD: 'High Definition'
|
||||||
|
@ -95,6 +107,7 @@ var schema = {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
desc: 'Recording Flagged as',
|
desc: 'Recording Flagged as',
|
||||||
idesc: 'Recording not Flagged as',
|
idesc: 'Recording not Flagged as',
|
||||||
|
negate: true,
|
||||||
select: {
|
select: {
|
||||||
Locked: 'Locked',
|
Locked: 'Locked',
|
||||||
New: 'New',
|
New: 'New',
|
||||||
|
@ -110,6 +123,7 @@ var schema = {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
desc: 'Change Recording Lock',
|
desc: 'Change Recording Lock',
|
||||||
|
negate: true,
|
||||||
select: {
|
select: {
|
||||||
1: 'Lock Recording',
|
1: 'Lock Recording',
|
||||||
0: 'Unlock Recording'
|
0: 'Unlock Recording'
|
||||||
|
@ -121,6 +135,8 @@ var schema = {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
type: 'substr',
|
type: 'substr',
|
||||||
desc: 'Filename contains',
|
desc: 'Filename contains',
|
||||||
|
idesc: 'Filename does not contain',
|
||||||
|
negate: true,
|
||||||
def: 'Enter text here...'
|
def: 'Enter text here...'
|
||||||
},
|
},
|
||||||
fflag: {
|
fflag: {
|
||||||
|
@ -128,7 +144,24 @@ var schema = {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
desc: 'Folder flagged as',
|
desc: 'Folder flagged as',
|
||||||
idesc: 'Folder not flagged as',
|
idesc: 'Folder not flagged as',
|
||||||
|
negate: true,
|
||||||
def: 'nosweep'
|
def: 'nosweep'
|
||||||
|
},
|
||||||
|
'or': {
|
||||||
|
'class': 'all',
|
||||||
|
type: 'composite',
|
||||||
|
label: 'Or',
|
||||||
|
desc: 'If any of...',
|
||||||
|
negate: false,
|
||||||
|
def: ''
|
||||||
|
},
|
||||||
|
'and': {
|
||||||
|
'class': 'all',
|
||||||
|
type: 'composite',
|
||||||
|
label: 'And',
|
||||||
|
desc: 'If all of...',
|
||||||
|
negate: false,
|
||||||
|
def: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
|
@ -150,24 +183,24 @@ var schema = {
|
||||||
desc: 'Move recording to folder...',
|
desc: 'Move recording to folder...',
|
||||||
continues: false
|
continues: false
|
||||||
},
|
},
|
||||||
lock: {
|
|
||||||
'class': 'all',
|
|
||||||
argtype: 'none',
|
|
||||||
desc: 'Lock recordings',
|
|
||||||
continues: true
|
|
||||||
},
|
|
||||||
unlock: {
|
|
||||||
'class': 'all',
|
|
||||||
argtype: 'none',
|
|
||||||
desc: 'Unlock recordings',
|
|
||||||
continues: true
|
|
||||||
},
|
|
||||||
movecreate: {
|
movecreate: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
argtype: 'folder',
|
argtype: 'folder',
|
||||||
desc: 'Move recording to folder (creating if necessary)',
|
desc: 'Move recording to folder (creating if necessary)',
|
||||||
continues: false
|
continues: false
|
||||||
},
|
},
|
||||||
|
copy: {
|
||||||
|
'class': 'all',
|
||||||
|
argtype: 'folder',
|
||||||
|
desc: 'Copy recording to folder...',
|
||||||
|
continues: false
|
||||||
|
},
|
||||||
|
copycreate: {
|
||||||
|
'class': 'all',
|
||||||
|
argtype: 'folder',
|
||||||
|
desc: 'Copy recording to folder (creating if necessary)',
|
||||||
|
continues: false
|
||||||
|
},
|
||||||
fileunder: {
|
fileunder: {
|
||||||
'class': 'folder',
|
'class': 'folder',
|
||||||
argtype: 'folder',
|
argtype: 'folder',
|
||||||
|
@ -187,6 +220,18 @@ var schema = {
|
||||||
desc: 'Rename recording files to...',
|
desc: 'Rename recording files to...',
|
||||||
continues: true
|
continues: true
|
||||||
},
|
},
|
||||||
|
lock: {
|
||||||
|
'class': 'all',
|
||||||
|
argtype: 'none',
|
||||||
|
desc: 'Lock recordings',
|
||||||
|
continues: true
|
||||||
|
},
|
||||||
|
unlock: {
|
||||||
|
'class': 'all',
|
||||||
|
argtype: 'none',
|
||||||
|
desc: 'Unlock recordings',
|
||||||
|
continues: true
|
||||||
|
},
|
||||||
delete: {
|
delete: {
|
||||||
'class': 'all',
|
'class': 'all',
|
||||||
argtype: 'none',
|
argtype: 'none',
|
||||||
|
@ -216,47 +261,38 @@ var macros = {
|
||||||
example: {
|
example: {
|
||||||
desc: 'Example rules',
|
desc: 'Example rules',
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
"raw": "lcn {>= 70} lcn {<= 79} duration {>= 90} action {move Children/Films}",
|
"raw": "lcn {>= 70} lcn {<= 79} or {duration {>= 90} genre Film } action {move Children/Films}",
|
||||||
"name": "Move any Children's films (by length)",
|
"name": "Move any Children's films",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"enabled": "0",
|
"enabled": "0",
|
||||||
"criteria": [
|
"criteria": [
|
||||||
{
|
{
|
||||||
|
"negate": 0,
|
||||||
"cmd": "lcn",
|
"cmd": "lcn",
|
||||||
"arg": ">= 70"
|
"arg": ">= 70"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"negate": 0,
|
||||||
"cmd": "lcn",
|
"cmd": "lcn",
|
||||||
"arg": "<= 79"
|
"arg": "<= 79"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cmd": "duration",
|
"negate": 0,
|
||||||
"arg": ">= 90"
|
"cmd": "or",
|
||||||
}
|
"arg": "duration {>= 90} genre Film ",
|
||||||
],
|
"criteria": [
|
||||||
"action": {
|
{
|
||||||
"cmd": "move",
|
"negate": 0,
|
||||||
"arg": "Children/Films"
|
"cmd": "duration",
|
||||||
}
|
"arg": ">= 90"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"raw": "lcn {>= 70} lcn {<= 79} genre Film action {move Children/Films}",
|
"negate": 0,
|
||||||
"name": "Move any Children's films (by genre)",
|
"cmd": "genre",
|
||||||
"type": "file",
|
"arg": "Film"
|
||||||
"enabled": "0",
|
}
|
||||||
"criteria": [
|
]
|
||||||
{
|
|
||||||
"cmd": "lcn",
|
|
||||||
"arg": ">= 70"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "lcn",
|
|
||||||
"arg": "<= 79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "genre",
|
|
||||||
"arg": "Film"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"action": {
|
"action": {
|
||||||
|
|
|
@ -90,16 +90,20 @@ var getters = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function ruleconf(rule)
|
function clauseconf(clause)
|
||||||
{
|
{
|
||||||
var s = '';
|
var s = '';
|
||||||
|
|
||||||
if (rule.hasClass('ruledisabled'))
|
clause.find('tbody:first > tr.clause,tbody:first > tr.compositeclause')
|
||||||
s += '## ';
|
.each(function() {
|
||||||
if (rule.attr('type') == 'folder')
|
if ($(this).hasClass('compositeclause'))
|
||||||
s += 'folder ';
|
{
|
||||||
|
cc = clauseconf($(this).find('table:first'));
|
||||||
rule.find('tr.clause').each(function(i) {
|
cmd = $(this).attr('cmd');
|
||||||
|
if (cc && cc.length)
|
||||||
|
s += cmd + ' {' + cc + '} ';
|
||||||
|
return;
|
||||||
|
}
|
||||||
cmd = $(this).find('th.cmd').attr('cmd');
|
cmd = $(this).find('th.cmd').attr('cmd');
|
||||||
negate = $(this).find('th.cmd').attr('negate');
|
negate = $(this).find('th.cmd').attr('negate');
|
||||||
c = schema.criterion[cmd];
|
c = schema.criterion[cmd];
|
||||||
|
@ -111,6 +115,19 @@ function ruleconf(rule)
|
||||||
s += '!';
|
s += '!';
|
||||||
s += cmd + ' ' + quot(val) + ' ';
|
s += cmd + ' ' + quot(val) + ' ';
|
||||||
});
|
});
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ruleconf(rule)
|
||||||
|
{
|
||||||
|
var s = '';
|
||||||
|
|
||||||
|
if (rule.hasClass('ruledisabled'))
|
||||||
|
s += '## ';
|
||||||
|
if (rule.attr('type') == 'folder')
|
||||||
|
s += 'folder ';
|
||||||
|
|
||||||
|
s += clauseconf(rule);
|
||||||
|
|
||||||
act = rule.find('tr.action th.cmd').attr('cmd');
|
act = rule.find('tr.action th.cmd').attr('cmd');
|
||||||
arg = $.trim(rule.find('tr.action td.val').text());
|
arg = $.trim(rule.find('tr.action td.val').text());
|
||||||
|
@ -144,18 +161,23 @@ function rulerefresh(rule)
|
||||||
if (!showraw)
|
if (!showraw)
|
||||||
rule.find('.raw').hide();
|
rule.find('.raw').hide();
|
||||||
rule.find('.raw').html(ruleconf(rule));
|
rule.find('.raw').html(ruleconf(rule));
|
||||||
rule.find('tr.clause th.title').text('And:').first().text('If:');
|
rule.find('tr.clause th.title,tr.compositeclause th.title')
|
||||||
if (rule.find('tr.clause').length < 1)
|
.text('And:').first().text('If:');
|
||||||
|
rule.find('tr.compositeclause').each(function(e) {
|
||||||
|
cmd = $(this).attr('cmd');
|
||||||
|
label = schema.criterion[cmd].label;
|
||||||
|
$(this).find('table th.title').text(label + ':')
|
||||||
|
.first().text('If:');
|
||||||
|
});
|
||||||
|
if (rule.find('tr.clause,tr.compositeclause').length < 1)
|
||||||
{
|
{
|
||||||
rule.find('tr.action th.title').text('Always:');
|
rule.find('tr.action th.title').text('Always:');
|
||||||
rule.find('tr.otherwise').hide();
|
rule.find('tr.otherwise,div.criteria,div.arrow').hide();
|
||||||
rule.find('div.criteria,div.arrow').hide();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rule.find('tr.action th.title').text('Then:');
|
rule.find('tr.action th.title').text('Then:');
|
||||||
rule.find('tr.otherwise').show();
|
rule.find('tr.otherwise,div.criteria,div.arrow').show();
|
||||||
rule.find('div.criteria,div.arrow').show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +194,34 @@ function critdesc(cmd, negate)
|
||||||
return c.desc;
|
return c.desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
function criterion(data)
|
function composite_criterion(c, data)
|
||||||
|
{
|
||||||
|
s = '<tr class="compositeclause" cmd=' + data.cmd + '>' +
|
||||||
|
'<th class=title>And:</th>' +
|
||||||
|
'<td colspan=3>' +
|
||||||
|
'<table class=compositeclause>' +
|
||||||
|
'<tr><td colspan=4>' +
|
||||||
|
'<a href=# class=addsubcriterion>' +
|
||||||
|
'<img src=img/plus.png height=15 ' +
|
||||||
|
'title="Add condition to sub-clause"></a>' +
|
||||||
|
' ' +
|
||||||
|
'<a class=delsubclause href=# ' +
|
||||||
|
'title="Delete sub-clause and the conditions within it">' +
|
||||||
|
'<img src=/img/context/delete.png></a>' +
|
||||||
|
' ' +
|
||||||
|
c.desc +
|
||||||
|
'</td></tr>';
|
||||||
|
|
||||||
|
$.each(data.criteria, function(key, val) {
|
||||||
|
s += criterion(val, 'comp');
|
||||||
|
});
|
||||||
|
|
||||||
|
s += '</table></td></tr>';
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function criterion(data, classes)
|
||||||
{
|
{
|
||||||
var c = schema.criterion[data.cmd];
|
var c = schema.criterion[data.cmd];
|
||||||
var s;
|
var s;
|
||||||
|
@ -182,7 +231,12 @@ function criterion(data)
|
||||||
alert('Unknown Criterion (' + data.cmd + ')');
|
alert('Unknown Criterion (' + data.cmd + ')');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s = '<tr class=clause><th class=title>And:</th>' +
|
if (c.type == 'composite')
|
||||||
|
return composite_criterion(c, data);
|
||||||
|
|
||||||
|
s = '<tr class="clause';
|
||||||
|
if (classes) s += ' ' + classes;
|
||||||
|
s += '"><th class=title>And:</th>' +
|
||||||
'<th class=cmd negate=' + data.negate + ' cmd=' + data.cmd + '>' +
|
'<th class=cmd negate=' + data.negate + ' cmd=' + data.cmd + '>' +
|
||||||
critdesc(data.cmd, data.negate) + '</th><td class=val>';
|
critdesc(data.cmd, data.negate) + '</th><td class=val>';
|
||||||
|
|
||||||
|
@ -192,10 +246,10 @@ function criterion(data)
|
||||||
s += 'UNKNOWN (' + data.arg + ')';
|
s += 'UNKNOWN (' + data.arg + ')';
|
||||||
|
|
||||||
s += '</td><td>' +
|
s += '</td><td>' +
|
||||||
'<a class=editclause href=#>' +
|
'<a class=editclause href=# title="Edit condition">' +
|
||||||
'<img src=/img/context/edit.png></a>' +
|
'<img src=/img/context/edit.png></a>' +
|
||||||
' ' +
|
' ' +
|
||||||
'<a class=delclause href=#>' +
|
'<a class=delclause href=# title="Delete condition">' +
|
||||||
'<img src=/img/context/delete.png></a>' +
|
'<img src=/img/context/delete.png></a>' +
|
||||||
'</td></tr>';
|
'</td></tr>';
|
||||||
return s;
|
return s;
|
||||||
|
@ -264,8 +318,12 @@ function addrule(id, data)
|
||||||
$.each(data.criteria, function(key, val) {
|
$.each(data.criteria, function(key, val) {
|
||||||
if (val.cmd == 'lock' && (
|
if (val.cmd == 'lock' && (
|
||||||
data.action.cmd == 'lock' || data.action.cmd == 'unlock'))
|
data.action.cmd == 'lock' || data.action.cmd == 'unlock'))
|
||||||
|
{
|
||||||
|
alert('Removed legacy lock/unlock - ' +
|
||||||
|
'check rules before saving.');
|
||||||
return;
|
return;
|
||||||
$c.find('tbody').append(criterion(val));
|
}
|
||||||
|
$c.find('tbody:first').append(criterion(val));
|
||||||
});
|
});
|
||||||
$c.find('th.title:first').text('If:');
|
$c.find('th.title:first').text('If:');
|
||||||
|
|
||||||
|
@ -599,7 +657,7 @@ $('#macros').on('click', '#b_macro', function(e) {
|
||||||
|
|
||||||
changed(0);
|
changed(0);
|
||||||
|
|
||||||
function addcriterion(rule)
|
function addcriterion(rule, target)
|
||||||
{
|
{
|
||||||
var type = rule.attr('type');
|
var type = rule.attr('type');
|
||||||
|
|
||||||
|
@ -616,6 +674,7 @@ function addcriterion(rule)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
$('#newcondition_negate').prop('checked', false);
|
$('#newcondition_negate').prop('checked', false);
|
||||||
|
$('#newcondition_cmd').trigger('change');
|
||||||
|
|
||||||
$('#newcondition').dialog({
|
$('#newcondition').dialog({
|
||||||
height: 'auto', width: 'auto',
|
height: 'auto', width: 'auto',
|
||||||
|
@ -624,21 +683,22 @@ function addcriterion(rule)
|
||||||
position: {
|
position: {
|
||||||
my: 'bottom left',
|
my: 'bottom left',
|
||||||
at: 'top right',
|
at: 'top right',
|
||||||
of: rule
|
of: target
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
"Add Condition": function() {
|
"Add Condition": function() {
|
||||||
$(this).dialog('close');
|
$(this).dialog('close');
|
||||||
var id = rule.attr('id');
|
|
||||||
var val = $('#newcondition_cmd').val();
|
var val = $('#newcondition_cmd').val();
|
||||||
var negate = $('#newcondition_negate')
|
var negate = $('#newcondition_negate')
|
||||||
.prop('checked') ? '1' : '0';
|
.prop('checked') ? '1' : '0';
|
||||||
rule.find('table.criteria tbody')
|
var obj = {
|
||||||
.append(criterion({
|
|
||||||
cmd: val,
|
cmd: val,
|
||||||
negate: negate,
|
negate: negate,
|
||||||
arg: schema.criterion[val].def
|
arg: schema.criterion[val].def,
|
||||||
}));
|
criteria: []
|
||||||
|
};
|
||||||
|
target.find('tbody:first')
|
||||||
|
.append(criterion(obj));
|
||||||
changed(1);
|
changed(1);
|
||||||
rulerefresh(rule);
|
rulerefresh(rule);
|
||||||
},
|
},
|
||||||
|
@ -656,7 +716,8 @@ $('#ruleset')
|
||||||
})
|
})
|
||||||
.on('click', 'a.addcriterion', function(e) {
|
.on('click', 'a.addcriterion', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
addcriterion($(this).closest('div.rule'));
|
var rule = $(this).closest('div.rule');
|
||||||
|
addcriterion(rule, rule.find('table.criteria'));
|
||||||
})
|
})
|
||||||
.on('click', 'a.editcomment', function(e) {
|
.on('click', 'a.editcomment', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -827,6 +888,32 @@ $('#ruleset')
|
||||||
.html($('#empty_rulebase').html());
|
.html($('#empty_rulebase').html());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.on('click', 'a.delsubclause', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).dojConfirmAction({
|
||||||
|
question: 'Delete sub-condition?',
|
||||||
|
yesAnswer: 'Yes',
|
||||||
|
cancelAnswer: 'No'
|
||||||
|
}, function(el) {
|
||||||
|
var rule = $(el).closest('div.rule');
|
||||||
|
$(el).closest('tr.compositeclause')
|
||||||
|
.fadeOut('slow', function() {
|
||||||
|
$(this).remove();
|
||||||
|
rulerefresh(rule);
|
||||||
|
changed(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.on('click', 'a.addsubcriterion', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var rule = $(this).closest('div.rule');
|
||||||
|
var clause = $(this).closest('table.compositeclause');
|
||||||
|
addcriterion(rule, clause);
|
||||||
|
})
|
||||||
|
.on('dblclick', 'div.raw', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).toggleClass("rawvis");
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#edit_action_act').on('change', function(e) {
|
$('#edit_action_act').on('change', function(e) {
|
||||||
|
@ -837,7 +924,17 @@ $('#ruleset')
|
||||||
$('#edit_action_arg').enable();
|
$('#edit_action_arg').enable();
|
||||||
$('.edit_action_help').hide();
|
$('.edit_action_help').hide();
|
||||||
$('#edit_action_help_' + schema.action[cmd].argtype).show();
|
$('#edit_action_help_' + schema.action[cmd].argtype).show();
|
||||||
})
|
});
|
||||||
|
|
||||||
|
$('#newcondition_cmd').on('change', function(e) {
|
||||||
|
var cmd = $(this).val();
|
||||||
|
if (schema.criterion[cmd].negate)
|
||||||
|
$('#newcondition_negate').enable();
|
||||||
|
else
|
||||||
|
$('#newcondition_negate')
|
||||||
|
.prop('checked', false)
|
||||||
|
.disable();
|
||||||
|
});
|
||||||
|
|
||||||
// Set up macros
|
// Set up macros
|
||||||
$.each(macros, function(key, val) {
|
$.each(macros, function(key, val) {
|
||||||
|
@ -854,5 +951,7 @@ $('#ruleset')
|
||||||
});
|
});
|
||||||
|
|
||||||
loadrules($('span.dir').text());
|
loadrules($('span.dir').text());
|
||||||
|
|
||||||
|
$(document).tooltip();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,11 @@ div.raw
|
||||||
right: 12px;
|
right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.rawvis
|
||||||
|
{
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
div#buttons
|
div#buttons
|
||||||
{
|
{
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
|
@ -107,6 +112,7 @@ span.legendright
|
||||||
table
|
table
|
||||||
{
|
{
|
||||||
border: 0;
|
border: 0;
|
||||||
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
table th
|
table th
|
||||||
|
|
|
@ -1,50 +1,12 @@
|
||||||
#!/mod/bin/jimsh
|
#!/mod/bin/jimsh
|
||||||
|
|
||||||
source /mod/webif/lib/setup
|
source /mod/webif/plugin/sweeper/harness.jim
|
||||||
require lock system.class ts.class tdelete pretty_size browse.class \
|
|
||||||
safe_delete settings.class plugin
|
|
||||||
|
|
||||||
proc log {msg {level 1}} {
|
if {![llength $argv]} {
|
||||||
puts "[\
|
::sweeper::scan 0
|
||||||
clock format [clock seconds] -format "%d/%m/%Y %H:%M"\
|
} else {
|
||||||
] - $msg"
|
scan_run [lindex $argv 0] sweeper ::sweeper::sweep
|
||||||
}
|
}
|
||||||
|
|
||||||
proc elapsed {start} {
|
|
||||||
return $(([clock milliseconds] - $start) / 1000.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
proc startclock {} {
|
|
||||||
set ::startclock_s [clock milliseconds]
|
|
||||||
}
|
|
||||||
|
|
||||||
proc endclock {size} {
|
|
||||||
set el [elapsed $::startclock_s]
|
|
||||||
set rate $($size / $el)
|
|
||||||
return "[pretty_size $size] in $el seconds - [pretty_size $rate]/s"
|
|
||||||
}
|
|
||||||
|
|
||||||
proc register {args} {}
|
|
||||||
|
|
||||||
proc scan_run {dir flag callback} {
|
|
||||||
global dustbin
|
|
||||||
|
|
||||||
if {[string match {\[*} [file tail $dir]]} return
|
|
||||||
|
|
||||||
if {[file exists "$dir/.$flag"]} { $callback $dir }
|
|
||||||
|
|
||||||
foreach entry [readdir -nocomplain $dir] {
|
|
||||||
if {[file isdirectory "$dir/$entry"]} {
|
|
||||||
scan_run "$dir/$entry" $flag $callback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set root [system mediaroot]
|
|
||||||
|
|
||||||
source auto.hook
|
|
||||||
|
|
||||||
::sweeper::scan 0
|
|
||||||
#::sweeper::apply $::root $::sweeper::cf
|
#::sweeper::apply $::root $::sweeper::cf
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
#!/mod/bin/jimsh
|
#!/mod/bin/jimsh
|
||||||
|
|
||||||
package require cgi
|
package require cgi
|
||||||
source /mod/webif/lib/setup
|
source /mod/webif/plugin/sweeper/harness.jim
|
||||||
require lock system.class ts.class tdelete pretty_size browse.class \
|
|
||||||
safe_delete settings.class plugin
|
|
||||||
|
|
||||||
httpheader
|
httpheader
|
||||||
|
|
||||||
set dir [cgi_get dir ""]
|
set dir [cgi_get dir ""]
|
||||||
set root [system mediaroot]
|
|
||||||
|
|
||||||
set cf "/tmp/sweepertest.cf"
|
set cf "/tmp/sweepertest.cf"
|
||||||
|
|
||||||
|
@ -31,30 +28,6 @@ if {[catch {set fp [open $cf w]} msg]} {
|
||||||
$fp puts -nonewline $data
|
$fp puts -nonewline $data
|
||||||
close $fp
|
close $fp
|
||||||
|
|
||||||
proc log {msg {level 1}} {
|
|
||||||
puts $msg
|
|
||||||
}
|
|
||||||
|
|
||||||
proc elapsed {start} {
|
|
||||||
return $(([clock milliseconds] - $start) / 1000.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
proc startclock {} {
|
|
||||||
set ::startclock_s [clock milliseconds]
|
|
||||||
}
|
|
||||||
|
|
||||||
proc endclock {size} {
|
|
||||||
set el [elapsed $::startclock_s]
|
|
||||||
set rate $($size / $el)
|
|
||||||
return "[pretty_size $size] in $el seconds - [pretty_size $rate]/s"
|
|
||||||
}
|
|
||||||
|
|
||||||
proc register {args} {}
|
|
||||||
|
|
||||||
set root [system mediaroot]
|
|
||||||
|
|
||||||
source auto.hook
|
|
||||||
|
|
||||||
set ::sweeper::dryrun 1
|
set ::sweeper::dryrun 1
|
||||||
::sweeper::apply $dir $cf
|
::sweeper::apply $dir $cf
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue