# HG changeset patch # User Matti Hamalainen # Date 1594217347 -10800 # Node ID c6f389bef58eeff0849c551b75b32b14d63b71bd # Parent 028ee7efd4ffcd63078ff56e6b7d50fbe1ddceed feeds: Largely refactor feeds.tcl, bump version to 2.0. diff -r 028ee7efd4ff -r c6f389bef58e config.feeds.example --- a/config.feeds.example Wed Jul 08 13:23:48 2020 +0300 +++ b/config.feeds.example Wed Jul 08 17:09:07 2020 +0300 @@ -8,6 +8,37 @@ set feeds_dbfile "/home/niinuska/bot/feeds.sqlite" +proc feeds_cmd_pub_last {unick uhost uhand uchan utext} { + return [feeds_cmd $unick $uhost $uhand $uchan "last $utext" 1] +} + +proc feeds_cmd_msg_last {unick uhost uhand utext} { + return [feeds_cmd $unick $uhost $uhand "PRIV" "last $utext" 0] +} + + +proc feeds_cmd_pubm_last {unick uhost uhand uchan utext} { + return [feeds_cmd $unick $uhost $uhand $uchan "last [feeds_cmdm_split $utext]" 1] +} + +proc feeds_cmd_msgm_last {unick uhost uhand utext} { + return [feeds_cmd_msg $unick $uhost $uhand "PRIV" "last [feeds_cmdm_split $utext]" 0] +} + + +# Initialization proc called only by feeds.tcl +proc feeds_init { } { + # Bind commands + bind pubm - !feed* feeds_cmd_pubm + bind pub - !last feeds_cmd_pub_last + bind pubm - !lates* feeds_cmd_pubm_last + + bind msgm - !feed* feeds_cmd_msgm + bind msg - !last feeds_cmd_msg_last + bind msgm - !lates* feeds_cmd_msgm_last +} + + # Proc for fetching the feeds data, called by fetch_feeds.tcl proc feeds_fetch { } { #fetch_poliisi "http://www.poliisi.fi/oulu/tiedotteet/1/0?all1/0" "Poliisi/Oulu" "http://www.poliisi.fi" @@ -39,9 +70,8 @@ # "#channel" "feedname|feedname2" # feednames can use matching, e.g. "mtv3*" would match all beginning with "mtv3" array set feeds_channels { - "#mazmlame" "the adventurers|oots|mestari|blastwave" - "#fireball" "mestari" - "#tnsp" "the adventurers|oots|mestari" + "#mazmlame" "the adventurers|oots|mestari|effi" + "#fireball" "mestari|effi" } @@ -72,3 +102,25 @@ # Set 'user agent' string for HTTP. If empty or not set, default will be used. #set http_user_agent "Mozilla" + + +### +### Messages +### + +array set feeds_messages { + + "usage_full" {"usage_help"} + "usage_help" "@cmd@ \[latest \[\]|list|history\]" + + "chk_unsync_entries" "Epäsynkki." + "chk_new_entries" "@1@ uutta." + "chk_entry" "@1@: @4@ \002@2@\002 -- @3@" + + "search_latest_feed" "Uusin '@1@' / @2@: @3@ -- @4@" + "search_no_matches" "Ei osumia haulla '@1@'." + + "history_list" "Feedien historia: @1@" + "history_list_item" "@1@ (@2@)" + "history_list_sep" ", " +} diff -r 028ee7efd4ff -r c6f389bef58e feeds.tcl --- a/feeds.tcl Wed Jul 08 13:23:48 2020 +0300 +++ b/feeds.tcl Wed Jul 08 17:09:07 2020 +0300 @@ -1,6 +1,6 @@ ########################################################################## # -# FeedCheck v1.1 by Matti 'ccr' Hamalainen +# FeedCheck v2.0 by Matti 'ccr' Hamalainen # (C) Copyright 2008-2020 Tecnic Software productions (TNSP) # # Requires fetch_feeds.tcl to be run as a cronjob, for example @@ -29,21 +29,11 @@ package require sqlite3 set feeds_name "FeedCheck" -set feeds_message "$feeds_name v1.1 by ccr/TNSP" +set feeds_message "$feeds_name v2.0 by ccr/TNSP" -putlog "$feeds_message" -bind pub - !feeds feeds_pubfetch -bind pub - !last feeds_publast -bind pub - !latest feeds_publast # ------------------------------------------------------------------------ -proc feeds_smsg {uchan umsg} { - global feeds_preferredmsg - putserv "$feeds_preferredmsg $uchan :$umsg" -} - - proc feeds_log {umsg} { global feeds_logmsg feeds_name if {$feeds_logmsg != 0} { @@ -52,31 +42,37 @@ } -proc feeds_msg {utime ufeed uurl utitle} { - global feeds_channels - foreach {uchan ufilter} [array get feeds_channels] { - foreach umatch [split $ufilter "|"] { - if {[string match -nocase $umatch $ufeed]} { - feeds_smsg "$uchan" "$ufeed: \002$utitle\002 -- $uurl" - } - } +proc feeds_qm {uid} { + global feeds_messages + + if {[info exists feeds_messages($uid)]} { + return $feeds_messages($uid) + } else { + return $uid } } -### Open database, etc -if {[catch {sqlite3 feeds_dbh $feeds_dbfile} uerrmsg]} { - puts "Could not open SQLite3 database '$feeds_dbfile': $uerrmsg." - exit 2 +proc feeds_smsg {apublic anick achan amsg {aargs {}}} { + global feeds_preferredmsg + set amsg [string map [list "@cmd@" "!feeds"] $amsg] + utl_msg_args $feeds_preferredmsg $apublic $anick $achan $amsg $aargs +} + + +proc feeds_msg {apublic anick achan aid {aargs {}}} { + feeds_smsg $apublic $anick $achan [feeds_qm $aid] $aargs } # ------------------------------------------------------------------------ -proc feeds_check_start {} { - global feeds_dbfile + +proc feeds_check_do {uforce upublic unick uchan} { + global feeds_dbfile feeds_dbh feeds_sync_limit feeds_channels + # Get old time, if it exists set oldtime 0 - if {![catch {set ufile [open "$feeds_dbfile.time" r 0600]} uerrmsg]} { + if {![catch {set ufile [open "${feeds_dbfile}.time" r 0600]} uerrmsg]} { gets $ufile oldtime close $ufile } else { @@ -84,47 +80,156 @@ set oldtime [clock seconds] } - return $oldtime -} + # Check for new items + set usql "SELECT feed AS ufeed, title AS utitle, url AS uurl, utime AS utime FROM feeds WHERE utime > $oldtime ORDER BY utime ASC" + set nresult [feeds_dbh onecolumn "SELECT COUNT(*) FROM feeds WHERE utime > $oldtime"] + if {$nresult > $feeds_sync_limit} { + # Too many items, don't spam the channels + feeds_log "${nresult} new entries since [utl_ctime $oldtime], probably unsynchronized. Ignoring." + if {$uforce} { + feeds_msg $upublic $unick $uchan "chk_unsync_entries" [list $nresult $oldtime [utl_ctime $oldtime]] + } + } else { + # Spam the channels with new items + feeds_log "${nresult} new entries since [utl_ctime $oldtime] .." + if {$uforce} { + feeds_msg $upublic $unick $uchan "chk_new_entries" [list $nresult [utl_ctime $oldtime]] + } -proc feeds_check_end {} { - global feeds_dbfile + feeds_dbh eval $usql { + # Message all relevant channels + foreach {qchan ufilter} [array get feeds_channels] { + foreach umatch [split $ufilter "|"] { + if {[string match -nocase $umatch $ufeed]} { + feeds_msg 1 "NULL" $qchan "chk_entry" [list $ufeed $utitle $uurl [utl_ctime $utime]] + } + } + } + } + } - if {![catch {set ufile [open "$feeds_dbfile.time" w 0600]} uerrmsg]} { - puts $ufile [clock seconds] - close $ufile + if {$nresult > 0} { + if {![catch {set ufile [open "${feeds_dbfile}.time" w 0600]} uerrmsg]} { + puts $ufile [clock seconds] + close $ufile + } } } -# ------------------------------------------------------------------------ proc feeds_exec {} { - global feeds_dbh feeds_check_period feeds_running feeds_sync_limit - -# feeds_log "Timed feed check." - set oldtime [feeds_check_start] - set usql "SELECT feed AS ufeed, title AS utitle, url AS uurl, utime AS utime FROM feeds WHERE utime > $oldtime ORDER BY utime ASC" - set nresult [feeds_dbh onecolumn "SELECT COUNT(*) FROM feeds WHERE utime > $oldtime"] + global feeds_check_period feeds_running - if {$nresult > $feeds_sync_limit} { - feeds_log "${nresult} new entries, probably unsynchronized. Ignoring." - } else { - feeds_log "${nresult} new entries since ${oldtime} ( [utl_ctime $oldtime] ) .." - feeds_dbh eval $usql { - feeds_msg $utime $ufeed $uurl $utitle - } - } - - if {$nresult > 0} { - feeds_check_end - } + feeds_check_do 0 0 "NULL" "NULL" set feeds_running [clock seconds] timer $feeds_check_period feeds_exec } +# ------------------------------------------------------------------------ +proc feeds_cmd {unick uhost uhand uchan uargs upublic} { + global feeds_dbh feeds_messages + + # Check and handle arguments + set rarglist [::textutil::split::splitx $uargs {\s+}] + set rcmd [lindex $rarglist 0] + set rargs [lrange $rarglist 1 end] + + if {$rcmd == "?" || $rcmd == "help" || $rcmd == "apua"} { + foreach ukey $feeds_messages(usage_full) { + feeds_msg $upublic $unick $uchan $ukey + } + return 0 + } + + if {$rcmd == "last" || $rcmd == "latest" || $rcmd == "uusin"} { + # Show latest entry or latest entry of specified feed + set ufound 0 + set utext [string tolower [join $rargs " "]] + set usql "SELECT url AS uurl, feed AS ufeed, title AS utitle, utime AS utime FROM feeds WHERE feed LIKE '%[utl_escape $utext]%' ORDER BY utime DESC LIMIT 1" + feeds_dbh eval $usql { + feeds_msg $upublic $unick $uchan "search_latest_feed" [list $ufeed [utl_ctime $utime] $utitle $uurl] + set ufound 1 + } + + if {$ufound == 0} { + feeds_msg $upublic $unick $uchan "search_no_matches" [list $utext] + } + } elseif {[string match "forc*" $rcmd] || [string match "fet*" $rcmd]} { + # Force check for new entries + if {![matchattr $uhand n]} { + feeds_msg $upublic $unick $uchan "no_access" + } + feeds_check_do 1 $upublic $unick $uchan + } elseif {[string match "list*" $rcmd]} { + # List ... + feeds_smsg $upublic $unick $uchan "usage_help" + + } elseif {[string match "hist*" $rcmd]} { + # Show history of feeds + set ulistitem [feeds_qm "history_list_item"] + set ulistsep [feeds_qm "history_list_sep"] + set usql "SELECT feed AS ufeed, utime FROM feeds GROUP BY feed ORDER BY utime DESC,feed DESC" + set ulist {} + + feeds_dbh eval $usql { + lappend ulist [utl_str_map_values $ulistitem [list $ufeed [utl_ctime $utime]]] + } + + feeds_msg $upublic $unick $uchan "history_list" [list [join $ulist $ulistsep]] + } else { + feeds_msg $upublic $unick $uchan "usage_help" + } +} + + +#------------------------------------------------------------------------- +proc feeds_cmd_pub {unick uhost uhand uchan uargs} { + global feeds_channels + + foreach {ukey uvalue} [array get feeds_channels] { + if {[string match $ukey $uchan]} { + return [feeds_cmd $unick $uhost $uhand $uchan $uargs 1] + } + } + + return 1 +} + +proc feeds_cmd_msg {unick uhost uhand uargs} { + feeds_cmd $unick $uhost $uhand "PRIV" $uargs 0 + return 1 +} + + +#------------------------------------------------------------------------- +proc feeds_cmdm_split {uargs} { + set rarglist [::textutil::split::splitx $uargs {\s+}] + return [join [lrange $rarglist 1 end] " "] +} + +proc feeds_cmd_pubm {unick uhost uhand uchan uargs} { + return [feeds_cmd_pub $unick $uhost $uhand $uchan [feeds_cmdm_split $uargs]] +} + +proc feeds_cmd_msgm {unick uhost uhand uargs} { + return [feeds_cmd_msg $unick $uhost $uhand [feeds_cmdm_split $uargs]] +} + + +# ------------------------------------------------------------------------ +### +### Initializing .. +### +putlog "$feeds_message" + +if {[catch {sqlite3 feeds_dbh $feeds_dbfile} uerrmsg]} { + puts "Could not open SQLite3 database '$feeds_dbfile': $uerrmsg." + exit 2 +} + if {[info exists feeds_running]} { set feeds_last [expr [clock seconds] - $feeds_running] } else { @@ -132,49 +237,10 @@ } if {$feeds_last < 0 || $feeds_last > [expr $feeds_check_period * 60]} { - feeds_log "Starting timed feed check." + putlog " - Starting timed feed check." feeds_exec } - -# ------------------------------------------------------------------------ -proc feeds_pubfetch {unick uhost uhand uchan utext} { - global feeds_dbh feeds_sync_limit -# feeds_log "Manual check invoked on $uchan." - - set oldtime [feeds_check_start] - set nresult [feeds_dbh onecolumn "SELECT COUNT(*) FROM feeds WHERE utime > $oldtime"] - - if {$nresult > 0} { - feeds_check_end - if {$nresult > $feeds_sync_limit} { - feeds_smsg $uchan "$nresult uutta, tod. näk. epäsynkissä. Ignoorataan." - } else { - set usql "SELECT feed AS ufeed, title AS utitle, url AS uurl, utime AS utime FROM feeds WHERE utime > $oldtime ORDER BY utime ASC" - feeds_dbh eval $usql { - feeds_msg $utime $ufeed $uurl $utitle - set found 1 - } - feeds_smsg $uchan "$nresult uutta." - } - } else { - feeds_smsg $uchan "Ei uusia." - } -} - - -# ------------------------------------------------------------------------ -proc feeds_publast {unick uhost uhand uchan utext} { - global feeds_dbh - set ufound 0 - - set usql "SELECT url AS uurl, feed AS ufeed, title AS utitle, utime AS utime FROM feeds WHERE feed LIKE '%[string tolower [utl_escape $utext]]%' ORDER BY utime DESC LIMIT 1" - feeds_dbh eval $usql { - feeds_smsg $uchan "Uusin '$ufeed' / [utl_ctime $utime]: $utitle -- $uurl" - set ufound 1 - } - - if {$ufound == 0} { - feeds_smsg $uchan "Ei osumia haulla '${utext}'." - } -} +putlog " - Executing feeds_init()" +feeds_init +putlog " - feeds_init() done."