comp.lang.tcl
Small NNTP viewer
- Location:
- /packages/acs-subsite/www/comp.lang.tcl
- Author:
- Gustaf Neumann
- Created:
- 2024-08-15
Related Files
[ hide source ] | [ make this the default ]
File Contents
ad_page_contract { Small NNTP viewer @author Gustaf Neumann @creation-date 2024-08-15 } { {thread_id:integer,notnull ""} } set nntp_group comp.lang.tcl if {$thread_id ne ""} { set single_thread $thread_id set doc(title) "Thread from $nntp_group" } else { set doc(title) "Recent Articles from $nntp_group" } set context [list $doc(title)] lassign [acs::dc list dbqd..get_group_info { select nntp_id from nntp_groups where name = :nntp_group }] nntp_id set tuples [acs::dc list_of_lists dbqd..get_articles { select article_id, dict from nntp_articles where nntp_id = :nntp_id order by article_id desc }] foreach tuple $tuples { lassign $tuple article_id article ns_log notice "work on $article_id" set msg_id [dict get $article MSG_ID] if {[info exists single_thread] && $single_thread == $article_id} { set single_thread_msg_id $msg_id } set secs [clock scan [dict get $article date]] lappend timeline_order $secs $msg_id dict set article POSTED_SECS $secs dict set article ARTICLE_ID $article_id dict set articles_dict $msg_id $article #if {![dict exists $article in-reply-to]} { # ns_log notice "ARTICLE $article_id $msg_id '[dict get $article subject]' is not a reply" #} else { # ns_log notice "ARTICLE $article_id $msg_id '[dict get $article subject]' is in reply to [dict exists $article in-reply-to]" #} if {![dict exists $article references]} { #ns_log notice "ARTICLE $article_id $msg_id '[dict get $article subject]' does not reference something else" } else { foreach reference [dict get $article references] { dict lappend referenced_by_dict $reference $msg_id dict lappend references_dict $msg_id $reference } } } #foreach key [dict keys $referenced_by_dict] { ns_log notice ... $key <- [dict get $referenced_by_dict $key]} #foreach key [dict keys $references_dict] { ns_log notice ... $key -> [dict get $references_dict $key]} # # Make one iteration ot update "referenced" and "referenced_by" # strutures for associating articles to threads. We get from the NNTP # server not necessarily the begin of the thread. # foreach msg_id [dict keys $articles_dict] { set referenced_by [expr {[dict exists $referenced_by_dict $msg_id] ? [dict get $referenced_by_dict $msg_id] : {} }] set references [expr {[dict exists $references_dict $msg_id] ? [dict get $references_dict $msg_id] : {} }] #set article_id [dict get $articles_dict $msg_id ARTICLE_ID] #ns_log notice "2nd work on $article_id msg_id $msg_id referenced_by_count [llength $referenced_by] references_count [llength $references]" dict set articles_dict $msg_id Referenced_by $referenced_by dict set articles_dict $msg_id References $references } if {[info exists single_thread]} { # # Build the collection of articles of a single thread. Order should be chronological # lappend timestamps [dict get $articles_dict $single_thread_msg_id POSTED_SECS] $single_thread_msg_id set replies [dict get $articles_dict $single_thread_msg_id Referenced_by] if {[llength $replies] == 0} { append doc(title) " (no replies yet)" } elseif {[llength $replies] == 1} { append doc(title) " (1 reply)" } else { append doc(title) " ([llength $replies] replies)" } foreach r [dict get $articles_dict $single_thread_msg_id Referenced_by] { lappend timestamps [dict get $articles_dict $r POSTED_SECS] $r } set timestamps [lsort -increasing -stride 2 $timestamps] } else { # # The begin of the posting overview are articles, that have no # references by themselves. For these compute the threads and the # "last_modified" entry (normally the newest response in a thread). # foreach msg_id [dict keys $articles_dict] { set article_id [dict get $articles_dict $msg_id ARTICLE_ID] set referenced_by [dict get $articles_dict $msg_id Referenced_by] set references [dict get $articles_dict $msg_id References] if {[llength $references] != 0} { continue } set last_modified_secs [dict get $articles_dict $msg_id POSTED_SECS] if {[llength $referenced_by] > 0} { set last_modified [dict get $articles_dict $msg_id date] foreach r $referenced_by { set modified_secs [dict get $articles_dict $r POSTED_SECS] if {$modified_secs > $last_modified_secs} { set last_modified_secs $modified_secs } } } lappend timestamps $last_modified_secs $msg_id } # # Sort the toplevel threads by the last_modified dates # set timestamps [lsort -decreasing -stride 2 $timestamps] } template::multirow create articles \ article_id date pretty_posted_date last_modified pretty_last_modified \ from subject \ body nr_replies last_contrib if {[info exists single_thread]} { set single_thread_msg_ids [dict get $articles_dict $single_thread_msg_id Referenced_by] lappend single_thread_msg_ids $single_thread_msg_id ns_log notice "MSGIDS single_thread_msg_ids $single_thread_msg_ids" foreach {timestamp msg_id} $timestamps { ns_log notice "... $msg_id ni $single_thread_msg_ids" if {$msg_id ni $single_thread_msg_ids} { continue } ns_log notice "NOT SKIPPING $msg_id" set article [dict get $articles_dict $msg_id] set posted_secs [dict get $article POSTED_SECS] set pretty_posted_date [::xowiki::utility pretty_age -levels 2 -timestamp $posted_secs] dict with article { template::multirow append articles \ [dict get $article ARTICLE_ID] \ [dict get $article date] \ $pretty_posted_date \ last_modified pretty_last_modified \ $from $subject \ $BODY \ [llength $Referenced_by] last_contrib } } ad_return_template nntp-thread } else { template::multirow create replies article_id msg_id from date pretty_date foreach {timestamp msg_id} $timestamps { set article [dict get $articles_dict $msg_id] set article_id [dict get $article ARTICLE_ID] set referenced_by [dict get $article Referenced_by] set references [dict get $article References] #ns_log notice "2nd work on $article_id msg_id $msg_id referenced_by_count [llength $referenced_by] references_count [llength $references]" if {[llength $references] != 0} { continue } set posted_secs [dict get $article POSTED_SECS] set pretty_posted_date [::xowiki::utility pretty_age -levels 2 -timestamp $posted_secs] set pretty_last_modified $pretty_posted_date set last_contrib $article_id set last_modified [dict get $article date] set last_modified_secs $posted_secs if {[llength $referenced_by] > 0} { set last_modified_date [dict get $article date] foreach r [dict get $referenced_by_dict $msg_id] { set modified_secs [dict get $articles_dict $r POSTED_SECS] template::multirow append replies \ $article_id $r \ [dict get $articles_dict $r from] \ [dict get $articles_dict $r date] \ [::xowiki::utility pretty_age -levels 2 -timestamp [dict get $articles_dict $r POSTED_SECS]] if {$modified_secs > $last_modified_secs} { set last_modified_secs $modified_secs set last_contrib [dict get $articles_dict $r ARTICLE_ID] set last_modified [dict get $articles_dict $r date] set pretty_last_modified [::xowiki::utility pretty_age -levels 2 -timestamp $last_modified_secs] } } } dict with article { template::multirow append articles \ $article_id $date $pretty_posted_date $last_modified $pretty_last_modified \ $from $subject $BODY [llength $referenced_by] $last_contrib } } ad_return_template nntp-view }