# TivoWebPlus # # Search module by Jeff Keegan, http://www.keegan.org/jeff # # History: # First version, September 10, 2001 # September 10, 2001: Version 1.0 # # MelvinPurvis # Changed to use auto-generated genericgenre.js for dtvio case # resolves dependence on a static file that may not reflect the categories of the current tivo proc get_textindexsearch {searchstr searchby} { global guideindexdir set guidedir "/var/tmp/searchmodule/" catch { exec mkdir "$guidedir" } set searchbyfiles "Title TitleKeyword Keyword {TitleKeyword Keyword} Actor Director" set searchbyfilelist [lindex $searchbyfiles $searchby] # First, check to make sure the guide data files exist in # $guidedir, and that they're recent # If not, grab them from mfs foreach searchbyfile $searchbyfilelist { if {[catch {set fmoddate [file mtime "${guidedir}$searchbyfile"]}]} { set fmoddate "" } RetryTransaction { set fsid [lindex [mfs find "$guideindexdir/$searchbyfile"] 0] if {[catch {set moddate [mfs moddate $fsid]}]} { set moddate "" } if { $moddate > $fmoddate } { FromMfs "${guidedir}$searchbyfile" $fsid } } } if {$searchby < 4} { set searchstr [string toupper $searchstr] } set fsids [list] if {$searchby == 1 || $searchby == 2 || $searchby == 3} { set returntype 0 foreach sstr $searchstr { set fsids1 [list] # Can't deal with "s here regsub -all {\"} $sstr {} sstr set len [string length $sstr] incr len -1 if {[string index $sstr $len] == "*"} { set sstr [string range $sstr 0 [expr $len-1]] } else { append sstr "\t" } foreach searchbyfile $searchbyfilelist { set retval [catch {set grepresults [exec "$::bin_dir/bsearch" "${guidedir}${searchbyfile}" $sstr]} error] if {$retval != 1} { set grepresultslineslist [split $grepresults "\n\r"] if {[llength $grepresultslineslist] > 1} { foreach line $grepresultslineslist { foreach fsid [lindex [split $line "\t"] 1] { if {[lsearch $fsids1 $fsid] == -1} { lappend fsids1 $fsid } } } } else { set line [lindex $grepresultslineslist 0] foreach fsid [lindex [split $line "\t"] 1] { if {[lsearch $fsids1 $fsid] == -1} { lappend fsids1 $fsid } } } } else { regsub -all "\"" $error "\\\"" error return "-2 $error" } } if {$fsids == ""} { set fsids $fsids1 } else { set fsids2 [list] foreach fsid $fsids { if {[lsearch $fsids1 $fsid] != -1} { lappend fsids2 $fsid } } set fsids $fsids2 } } } else { set retval [catch {set grepresults [exec "$::bin_dir/bsearch" "${guidedir}${searchbyfile}" $searchstr]} error] if {$retval == 1} { regsub -all "\"" $error "\\\"" error return "-2 $error" } if {$grepresults == "" && $searchby >= 3 && [string first "," $searchstr] == -1 && [llength $searchstr] > 1} { set slist [split $searchstr " "] set slen [llength $slist] set sstr "[lindex $slist [expr $slen - 1]], [join [lrange $slist 0 [expr $slen - 2]]]" set retval [catch {set grepresults [exec "$::bin_dir/bsearch" "${guidedir}${searchbyfile}" $sstr]}] } if {$retval == 1} { return -2 } set grepresultslineslist [split $grepresults "\n\r"] if {[llength $grepresultslineslist] > 1 && $searchby >= 3} { foreach line $grepresultslineslist { lappend fsids [lindex [split $line "\t"] 0] } set returntype 1 } else { foreach line $grepresultslineslist { lappend fsids [split $line "\t"] } set returntype 2 } } if {$fsids == ""} { return -1 } else { return "$returntype $fsids" } } proc action_search {chan path env} { global db global cache_sp_fsid cache_sp_key global anyresultsdisplayed global images global url_prefix set searchby 0 set q "" set watch 1 set showemptyhits 0 set cat 0 set scat 0 set showthumb 0 set showrating 0 set submit "" set doingexactsearch 0 # Added in 1.4 set w 0 eval $env set searchbyvals "0 1 2 3 4 5" set searchbylabels "Title {Title Keyword} {Description Keyword} {Title/Description Keyword} Actor Director" if {$submit=="Add WishList"} { action_add-wishlist $chan $path $env return } set searchbylab [strim [lindex $searchbylabels $searchby]] if {$w == 0} { puts $chan [html_start "Search"] puts $chan [html_form_start "GET" "/search" "name=\"search\""] if { $::dtivo } { puts $chan "" #puts $chan "" } elseif { $::uktivo } { puts $chan "" } else { puts $chan "" } puts $chan [html_table_start "" "Search" "COLSPAN=2"] puts $chan [tr "" [td "Search By:"] [td "" [html_form_select "searchby" $searchbyvals $searchbylabels $searchby "onChange=\"searchhelp(this.options.selectedIndex)\""]]] puts $chan [tr "" [td "Category:"] [td [html_form_select "cat" "0" "All" 0 "onChange=\"loadscat(this.options.selectedIndex)\""]]] puts $chan [tr "" [td "Sub-Category:"] [td [html_form_select "scat" "0" "{Don't specify a sub-category}" 0]]] puts $chan "" puts $chan [tr "" [td "Search For:"] [td [html_form_text 1 35 "q" $q]]] if {$watch == 0} { puts $chan [tr "" [td "COLSPAN=2" "   Include Channels You Don't Watch"]] } else { puts $chan [tr "" [td "COLSPAN=2" "   Include Channels You Don't Watch"]] } if {$showemptyhits == 1} { puts $chan [tr "" [td "COLSPAN=2" "   Display Empty (No Upcoming Episodes) Hits"]] } else { puts $chan [tr "" [td "COLSPAN=2" "   Display Empty (No Upcoming Episodes) Hits"]] } puts $chan [html_table_end] puts $chan [html_form_input "submit" "submit" "Search"] puts $chan [html_form_input "submit" "submit" "Add WishList"] puts $chan [html_form_end] } # Now output search results if this was a search action if {[expr {$q != ""} || {$cat != 0}]} { #puts $chan "Running query" regsub -nocase {^(a|the) } $q {} modq if {$searchby == 0} { regsub -all {\$} $modq {} modq regsub -all {\*} $modq {} modq } else { regsub -all {\$} $modq {S} modq } if {$searchby == 1 || $searchby == 2 || $searchby == 3} { regsub -all {[-/.]} $modq { } modq } if {$searchby == 4 || $searchby == 5} { regsub -all -- {-} $modq { } modq regsub -all {[ ]*,[ ]*} $modq {, } modq } regsub -all {[^A-Za-z0-9\*\", ]} $modq {} modq if {$searchby == 1 || $searchby == 2 || $searchby == 3} { if {[string first "\"" $modq] != -1} { if {[string first " " $q] == -1} { # Not really an "exact" search! regsub -all {\"} $modq {} modq set doingexactsearch 0 } else { if {[string last "\"" $q] != [expr [string length $q] - 1]} { puts $chan [h2 "Error, unrecognised search format.: $q"] return } else { if {[string first "\"" [string range $q 1 [expr [string length $q] - 2]]] != -1} { puts $chan [h2 "Error, unrecognised search format: $q"] return } set doingexactsearch 1 } } } else { set doingexactsearch 0 } } else { regsub -all {\"} $modq {} modq } regsub "\t$" $modq {} dispq if {[string length $dispq] == 0} { if {$cat == ""} { puts $chan [h2 "Error, empty search query"] puts $chan [html_end] return } } else { if {[string length $dispq] < 2} { puts $chan [h2 "Error, require at least 2 characters in query"] puts $chan [html_end] return } } set searchResultsTitle [htmlEncode $dispq] set searchResultsTitle "Search Results for \"$searchResultsTitle\"" if {[expr {$q == ""} && {$cat != ""}]} { #puts $chan "DOING GENRESEARCH" set fsids [get_genresearch $cat $scat] set watch 0 } else { if {$doingexactsearch == 1} { set fsids [get_exactsearch $q $searchby $chan] } else { set fsids [get_textindexsearch $modq $searchby] } } if {[lindex $fsids 0] == -1} { if {$w == 0} { puts $chan [h2 $searchResultsTitle] puts $chan [html_table_start "" "Results" ""] puts $chan [tr "" [td "Sorry, no shows matched your query"]] } else { puts $chan [tr "" [td "colspan=10" "
No matching shows"]] } } elseif {[lindex $fsids 0] == -2} { if {$w == 0} { puts $chan [h2 $searchResultsTitle] puts $chan [html_table_start "" "Results" ""] } puts $chan [tr "" [td "An error was encountered running the search program"]] puts $chan [tr "" [td [lrange $fsids 1 end]]] } else { set anyresultsdisplayed 0 if {$searchby == 0} { update_sp_cache if {$w == 0} { puts $chan [h2 $searchResultsTitle] puts $chan [html_table_start "" "Results" "COLSPAN=3"] } foreach item [lrange $fsids 1 end] { set seriestitle [lindex $item 0] set fsid [lindex $item 1] set fsid [expr 0x$fsid] set genres [lindex $item 2] if {$cat != 0 && [genrematch $genres "$cat $scat"] == 0} { continue } regsub {^(.*), (A|The)$} $seriestitle {\2 \1} seriestitle set slists "" if {$showemptyhits == 0} { set slists [get_programshowings $fsid $watch] } if {$showemptyhits == 1 || $slists != ""} { set index [lsearch $cache_sp_key "$fsid|*"] if {$index > -1} { set imagestr [img "alt=\"\"" [lindex $images 11]] } else { set imagestr "" } set link "/series/$fsid" if {$watch != 1} { append link "?watch=0" } set thumbs "" if { $showthumb == 1} { RetryTransaction { set series [db $db openid $fsid] set title [strim [dbobj $series get Title]] set score [dbobj $series get ThumbData] set thumbs "" if { $score != "" } { set imagenum [get_thumbimage $score] if { $imagenum >= 0} { set imagef [lindex $images $imagenum] set thumbs [img "alt=\"\"" $imagef] } } } } puts $chan [tr "" [td $imagestr] [td [html_link $link [htmlEncode $seriestitle]]] [td $thumbs]] set anyresultsdisplayed 1 } } if {$anyresultsdisplayed == 0} { if {$w == 0} { puts $chan [tr "" [td "COLSPAN=2" "
Sorry, no shows matched your query
"]] } else { puts $chan [tr "" [td "COLSPAN=10" "
No matching shows"]] } } } elseif {$searchby >= 4 && [lindex $fsids 0] == 1} { puts $chan [h2 $searchResultsTitle] puts $chan [html_table_start "" "Results" ""] foreach name [lrange $fsids 1 end] { append name "\t" set link "/search?searchby=$searchby" if {$watch != 1} { append link "&watch=0" } if {$showemptyhits != 0} { append link "&showemptyhits=1" } if {$cat != 0} { append link "&cat=$cat" } if {$scat != 0} { append link "&scat=$scat" } append link "&q=[httpMapReply $name]" puts $chan [tr "" [td [html_link $link [htmlEncode $name]]]] set anyresultsdisplayed 1 } if {$anyresultsdisplayed == 0} { if {$w == 0} { puts $chan [tr "" [td "COLSPAN=2" "
Sorry, no shows matched your query
"]] } else { puts $chan [tr "" [td "COLSPAN=10" "
No matching shows"]] } } } else { update_sp_cache if {$searchby >= 4} { set item [lindex $fsids 1] set fsids "0 [lindex $item 1]" set searchResultsTitle [htmlEncode [lindex $item 0]] set searchResultsTitle "Search Results for \"$searchResultsTitle\"" } if {$w == 0} { puts $chan [h2 $searchResultsTitle] puts $chan [html_table_start "" "" ""] } set serproghits [list] foreach fsid [lrange $fsids 1 end] { set fsid [expr 0x$fsid] if {[catch { RetryTransaction { set program [db $db openid $fsid] set seriestitle [strim [dbobj $program get Title]] if {$cat != 0} { set genres [dbobj $program get Genre] } set series [dbobj $program get Series] set seriesfsid 0 if { $series != "" } { set seriesfsid [dbobj $series fsid] set episodic [defaultval 1 [dbobj $series get Episodic]] } else { set episodic 1 } } }] == 1} { #puts $chan [tr "" [td "Error $fsid"]] } else { if {$cat != 0} { if { !$::dtivo || $cat == 1 || $cat == 5 || $cat == 8 } { if {[lsearch $genres $cat] < 0} { continue } } if {$scat != 0 && [lsearch $genres $scat] < 0} { continue } } lappend serproghits [list $seriestitle $seriesfsid $episodic $fsid] } } set serproghits [lsort -index 0 -dictionary $serproghits] set lastseriesfsid "" set lastseries "" set numrows [llength $serproghits] set efsids "" puts $chan [tr "ALIGN=CENTER" [th ""] [th ""] [th "Episode"] [th "Num"] [th "Orig.Air Date"] [th "Chan"] [th "COLSPAN=2" "Date"] [th "Time"] [th "Mins"]] for {set i 0} {$i < $numrows} {incr i} { set sph [lindex $serproghits $i] set stitle [strim [lindex $sph 0]] set sfsid [lindex $sph 1] # original checks for episodic and doesn't show details for movies # TWP shows details for everything; much better. if {$sfsid != $lastseriesfsid} { set index [lsearch $cache_sp_key "$sfsid|*"] if {$index > -1} { set imagestr [img "" [lindex $images 11]] } else { set imagestr "" } set efsids "" set lastseriesfsid $sfsid set lastseries $stitle } lappend efsids [lindex $sph 3] if {$i == [expr $numrows - 1] || [lindex [lindex $serproghits [expr $i + 1]] 1] != $sfsid} { doShowingRow $chan $sfsid $stitle $efsids $watch $showemptyhits $imagestr } } if {$anyresultsdisplayed == 0} { if {$w == 0} { puts $chan [tr "" [td "COLSPAN=10" "
Sorry, no shows matched your query
"]] } else { puts $chan [tr "" [td "COLSPAN=10" "
No matching shows"]] } } } } puts $chan [html_table_end] set visibility "style=\"visibility: hidden\"" } else { set visibility "" } puts $chan "
" puts $chan [html_end] } proc doShowingRow {chan serfsid sertitle progfsids watch showemptyhits imagestr} { global db global anyresultsdisplayed set first 1 if {$showemptyhits == 1} { set link "/series/$serfsid" if {$watch != 1} { append link "?watch=0" } puts $chan [tr "" [td $imagestr] [td "COLSPAN=9" [html_link $link "[htmlEncode $sertitle]"]]] set first 0 set anyresultsdisplayed 1 } set slists "" foreach progfsid $progfsids { append slists " " [get_programshowings $progfsid $watch] } set slists [lsort -index 0 $slists] foreach slist $slists { set seconds [lindex $slist 0] set stationfsid [lindex $slist 1] set date [expr $seconds / 86400] set time [expr $seconds % 86400] set timestr [format "%05d" $time] set stationdayfsid "" RetryTransaction { set recfsid [lindex [get_fsidbyprefix "/Recording/Active" "4:$date:$timestr:"] 0] set stationdayfsid [lindex [get_fsidbyprefix "/Schedule" "$stationfsid:$date:"] 0] if {[catch {set stationday [db $db openid $stationdayfsid]}] == 0} { set showings [dbobj $stationday get Showing] foreach showing $showings { set stime [dbobj $showing get Time] if { $time == $stime } { # First, see if we've output the series title yet... ##################################################### if {$first == 1} { set link "/series/$serfsid" if {$watch != 1} { append link "?watch=0" } puts $chan [tr "" [td $imagestr] [td "COLSPAN=9" [html_link $link "[htmlEncode $sertitle]"]]] set first 0 } set lastseriesfsid $serfsid set lastseries $sertitle do_seriesrowtodo $chan $showing $recfsid 1 set anyresultsdisplayed 1 break } } } } } } register_module "search" "Search" "Search for TV shows"