irc-logger-procs.tcl

Procs used by the irc-logger module.

Location:
packages/irc-logger/tcl/irc-logger-procs.tcl
Created:
2003-01-27
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
CVS Identification:
$Id: irc-logger-procs.tcl,v 1.12 2022/10/05 07:58:50 gustafn Exp $

Procedures in this file

Detailed information

dom::xpathFunc::irc::logger::user_link (public)

 dom::xpathFunc::irc::logger::user_link ctxNode pos nodeListType \
    nodeList [ args... ]

Create a link to the user account on this site where the IRC nick matches the user's screen name.

Rolf (rolf@pointsman.de) from the tDOM team on tDOM extension functions:

If an XPath expr (both for the selectNodes method and in XSLT stylesheets) uses a not standard XPath function name (you cannot 'overwrite' the C coded standard built-in functions), the engine looks, if there is a tcl proc with the given function name in the ::dom::xpathFunc:: namespace. In other words: all extension functions procs must reside in the namespace ::dom::xpathFunc or in a child namespace of that namespace. If the XPath extension function has a prefix, the prefix is expanded to the namespace URI and that namespace URI must be the name of the child namespace of the ::dom::xpathFunc namespace.

If there is such a proc, this proc is called with the following arguments: ctxNode pos nodeListType nodeList args. The 'args' are, as type/value pairs, the arguments, that are given to the extension functions. (E.g. if you have myExtensionFunction('foo'), you will get two args, the first "string" the second "foo").

The tcl proc, which implements the extension function must return a list of two elements: {<type> <value>}. The possible types at the moment are: "bool", "number", "string", "nodes".

But don't get confused by my probably (too) vague explanations. Just look at the examples in the xpath.test and tdom.tcl files. For almost all 'real life' needs, you should get it very fast, what to do from that usage examples.

Parameters:
ctxNode (required)
See tDOM documentation.
pos (required)
See tDOM documentation.
nodeListType (required)
See tDOM documentation.
nodeList (required)
See tDOM documentation.
Returns:
A single (type, value) pair with a link to the user account on the site. Or just the nick if no user account was found.
Error:
The empty string.
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-01-31

Partial Call Graph (max 5 caller/called nodes):
%3 ad_acs_kernel_id ad_acs_kernel_id (public) db_0or1row db_0or1row (public) export_vars export_vars (public) parameter::get parameter::get (public) dom::xpathFunc::irc::logger::user_link dom::xpathFunc::irc::logger::user_link dom::xpathFunc::irc::logger::user_link->ad_acs_kernel_id dom::xpathFunc::irc::logger::user_link->db_0or1row dom::xpathFunc::irc::logger::user_link->export_vars dom::xpathFunc::irc::logger::user_link->parameter::get

Testcases:
No testcase defined.

irc::logger::apply_xslt (public)

 irc::logger::apply_xslt -rdf_log rdf_log -xsl_style xsl_style \
    [ -package_id package_id ]

Transform the RDF IRC log to HTML using passed XSL stylesheet.

Switches:
-rdf_log (required)
The full path to the IRC log in RDF format
-xsl_style (required)
The full path to the XSL stylesheet to transform the RDF log into HTML with.
-package_id (optional)
Returns:
The transformed IRC log in HTML.
Error:
Return the empty string.
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-01-27

Partial Call Graph (max 5 caller/called nodes):
%3 irc::logger::update_log irc::logger::update_log (public) irc::logger::apply_xslt irc::logger::apply_xslt irc::logger::update_log->irc::logger::apply_xslt dom dom irc::logger::apply_xslt->dom

Testcases:
No testcase defined.

irc::logger::get_log (public)

 irc::logger::get_log -date date -package_id package_id

Check which .rdf file holds the current IRC log in RDF format as created by Dave Beckett's logger.

Switches:
-date (required)
The date in YYYY-MM-DD format to get the IRC log of.
-package_id (required)
The package_id of the mounted IRC logger instance to get the log for.
Returns:
The full path to the IRC log in RDF format.
Error:
Return the empty string
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-01-27

Partial Call Graph (max 5 caller/called nodes):
%3 irc::logger::update_log irc::logger::update_log (public) irc::logger::get_log irc::logger::get_log irc::logger::update_log->irc::logger::get_log parameter::get parameter::get (public) irc::logger::get_log->parameter::get

Testcases:
No testcase defined.

irc::logger::rotate_logs (public)

 irc::logger::rotate_logs -package_id package_id [ -all ]

Rotate the ETP pages so that the ETP page with the new log is listed first instead of last. Please be aware that changes to the sort order through of these logs through ETP might have undesired side effects to the order. This an artifact of ETP and not of the IRC logger.

Switches:
-package_id (required)
The package_id of the ETP instance that is the parent of the ETP log pages.
-all (optional, boolean)
Returns:
none
Error:
none
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-02-18

Partial Call Graph (max 5 caller/called nodes):
%3 irc::logger::update_log irc::logger::update_log (public) irc::logger::rotate_logs irc::logger::rotate_logs irc::logger::update_log->irc::logger::rotate_logs db_dml db_dml (public) irc::logger::rotate_logs->db_dml db_foreach db_foreach (public) irc::logger::rotate_logs->db_foreach db_map db_map (public) irc::logger::rotate_logs->db_map db_string db_string (public) irc::logger::rotate_logs->db_string

Testcases:
No testcase defined.

irc::logger::scheduled_update (public)

 irc::logger::scheduled_update -package_id package_id

Scheduled procedure to check for updates of today's IRC log.

Switches:
-package_id (required)
The package_id of the mounted IRC logger instance to get the log for.
Returns:
none
Error:
none
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-01-27

Partial Call Graph (max 5 caller/called nodes):
%3 irc::logger::update_log irc::logger::update_log (public) irc::logger::scheduled_update irc::logger::scheduled_update irc::logger::scheduled_update->irc::logger::update_log

Testcases:
No testcase defined.

irc::logger::update_log (public)

 irc::logger::update_log -date date -package_id package_id

Check the IRC log of the passed date associated with package_id. Transform the RDF log to HTML if the log has changed since the last time this proc was run. Then place the HTML log in an ETP page of the ETP instance that IRC logger is mounted under. The ETP page has the name of passed date.

Switches:
-date (required)
The date in YYYY-MM-DD format to get the IRC log of.
-package_id (required)
The package_id of the mounted IRC logger instance to get the log for.
Returns:
none
Error:
Write warning messages to the log were necessary.
Author:
Bart Teeuwisse <bart.teeuwisse@thecodemill.biz>
Created:
2003-01-27

Partial Call Graph (max 5 caller/called nodes):
%3 irc::logger::scheduled_update irc::logger::scheduled_update (public) irc::logger::update_log irc::logger::update_log irc::logger::scheduled_update->irc::logger::update_log packages/irc-logger/www/admin/update.tcl packages/irc-logger/ www/admin/update.tcl packages/irc-logger/www/admin/update.tcl->irc::logger::update_log acs_package_root_dir acs_package_root_dir (public) irc::logger::update_log->acs_package_root_dir apm_package_key_from_id apm_package_key_from_id (public) irc::logger::update_log->apm_package_key_from_id apm_package_url_from_id apm_package_url_from_id (public) irc::logger::update_log->apm_package_url_from_id db_0or1row db_0or1row (public) irc::logger::update_log->db_0or1row db_dml db_dml (public) irc::logger::update_log->db_dml

Testcases:
No testcase defined.
[ hide source ] | [ make this the default ]

Content File Source

ad_library {

     Procs used by the irc-logger module.

     @creation-date 2003-01-27
     @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)
     @cvs-id $Id: irc-logger-procs.tcl,v 1.12 2022/10/05 07:58:50 gustafn Exp $
     @arch-tag: 02bf231b-7b2f-4261-b671-ccb4d4b7a6f6
}

namespace eval irc::logger {

    # The namespace of the irc-logger module

}

d_proc -public irc::logger::get_log {
    -date:required
    -package_id:required
} {

    Check which .rdf file holds the current IRC log in RDF format as
    created by Dave Beckett's logger.

    @creation-date 2003-01-27
    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)

    @param date The date in YYYY-MM-DD format to get the IRC log of.

    @param package_id The package_id of the mounted IRC logger
    instance to get the log for.

    @return The full path to the IRC log in RDF format.

    @error Return the empty string

} {

    # Locate the RDF log of the given date

    foreach rdf_log [glob -nocomplain -directory [parameter::get \
                                                      -parameter irc_rdf_dir \
                                                      -package_id $package_id \
                                                      -default ""$date.rdf] {
        return $rdf_log
    }

    # Couldn't find the log, return the empty string.

    return ""
}

d_proc -public irc::logger::apply_xslt {
    -rdf_log:required
    -xsl_style:required
    {-package_id ""}
} {

    Transform the RDF IRC log to HTML using passed XSL stylesheet.

    @creation-date 2003-01-27
    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)

    @param rdf_log The full path to the IRC log in RDF format

    @param xsl_style The full path to the XSL stylesheet to
    transform the RDF log into HTML with.

    @return The transformed IRC log in HTML.

    @error Return the empty string.

} {

    # Parse the RDF log and the XSL style sheet into DOM trees.
    # Return the empty string if the XSL style could not be applied.
    set text ""

    # Return the empty string if the XSL style could not be applied.
    set text ""

    if {![catch {set rdf [dom parse [read [open $rdf_log r]]]} error_msg]} {
        if {![catch {set xsl [dom parse [read [open $xsl_style r]]]} error_msg]} {
    
            # Transform the RDF DOM tree to an HTML DOM tree
        
            if {![catch {set html [$rdf xslt $xsl]} error_msg]} {

                # Serialize the HTML DOM tree as HTML text

        set text [$html asHTML]

            } else {
                ns_log warning "irc::logger::apply_xslt - Could not transform RDF log '$rdf_log' to HTML with XSL sheet '$xsl_style': $error_msg"
            }
        } else {
            ns_log warning "irc::logger::apply_xslt - Could not parse $xsl_style: $error_msg"
        }
    $rdf delete
    } else {
        ns_log warning "irc::logger::apply_xslt - Could not parse $rdf_log: $error_msg"
    }
    
    # clean up the dom references, otherwise we have a mem leak.
    if {[info exists rdf]} {
    $rdf delete
    }
    if {[info exists xsl]} {
    $xsl delete
    }
    if {[info exists html]} {
    $html delete
    }
    return $text
}

d_proc -public irc::logger::rotate_logs {
    -package_id:required
    {-all:boolean}
} {

    Rotate the ETP pages so that the ETP page with the new log is
    listed first instead of last. Please be aware that changes to 
    the sort order through of these logs through ETP might have 
    undesired side effects to the order. This an artifact of ETP
    and not of the IRC logger.

    @creation-date 2003-02-18
    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)

    @param package_id The package_id of the ETP instance that is 
    the parent of the ETP log pages.

    @param -all Switch indicating wether all ETP instances should 
    be rotated or only the ETP log pages. This flag is used when
    the 'current' link has been created and needs to be rotated to 
    the top of the page.

    @return none

    @error none
} {

    # Get the ID of the parent folder of the ETP log pages.

    set parent_id [db_string get_parent_id {} -default {}]

    # Rotate all ETP pages or just the logs?

    if {$all_p} {
    set i1_select_criteria "true"
    set i2_select_criteria "true"
    } else {
    set i1_select_criteria [db_map i1_criteria]
    set i2_select_criteria [db_map i2_criteria]
    }

    # Rotate the logs by assigning the tree_sortkey of the next ETP
    # page to the current page. Assign the tree_sortkey of the first
    # page to the last (=new) page.

    db_foreach etp_logs {} {

        # Assign the tree_sortkey of the next ETP page to the current
        # page or the tree_sortkey of the first ETP to the last page.

        db_dml shift {}
    }
}

d_proc -public irc::logger::update_log {
    -date:required
    -package_id:required
} {

    Check the IRC log of the passed date associated with
    package_id. Transform the RDF log to HTML if the log has changed
    since the last time this proc was run. Then place the HTML log
    in an ETP page of the ETP instance that IRC logger is mounted
    under. The ETP page has the name of passed date.

    @creation-date 2003-01-27
    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)

    @param date The date in YYYY-MM-DD format to get the IRC log of.

    @param package_id The package_id of the mounted IRC logger
    instance to get the log for.

    @return none

    @error Write warning messages to the log were necessary.

} {

    # Check for an ETP parent node.

    set logger_url [apm_package_url_from_id $package_id]
    if {![empty_string_p $logger_url]} {
        set parent_package_id [site_node::get_object_id \
                                   -node_id [site_node::get_parent_id \
                                                 -node_id [site_node::get_node_id \
                                                               -url $logger_url]]]
        set parent_package_key [apm_package_key_from_id $parent_package_id]
        if {[string equal $parent_package_key "edit-this-page"]} {

            # Get the RDF log for today.

            set irc_rdf_log [irc::logger::get_log \
                                 -date $date \
                                 -package_id $package_id]
            if {![empty_string_p $irc_rdf_log]} {
                
                # Check if today's log has been modified. 

                if {[file mtime $irc_rdf_log] > [expr [clock seconds] - [parameter::get \
                                                                             -parameter irc_log_interval \
                                                                             -package_id $package_id \
                                                                             -default 600]]} {
                    
                    # Transform the RDF log to HTML.

                    set irc_html_log [irc::logger::apply_xslt \
                                          -rdf_log $irc_rdf_log \
                                          -xsl_style [parameter::get \
                                                          -parameter xsl_stylesheet \
                                                          -package_id $package_id \
                                                          -default "[acs_package_root_dir [apm_package_key_from_id $package_id]]/data/default.xsl"] \
                      -package_id $package_id]

                    if {![empty_string_p $irc_html_log]} {
                        
                        # The transformation was succesful. Time to create
                        # or update the ETP page.

                        set irc_channel_name "[parameter::get \
                                   -parameter irc_channel_name \
                                   -package_id $package_id \
                                   -default ""]"
                        set log_latest_revision_id [etp::get_latest_revision_id $parent_package_id $date]
                        set content_type [etp::get_content_type]
                        if {[empty_string_p $log_latest_revision_id]} {

                            # Create a new ETP page for the log.

                            db_exec_plsql page_create {}
                set log_live_revision_id [etp::get_live_revision_id $parent_package_id $date]

                # Rotate the logs so that the new log is
                # on top.

                irc::logger::rotate_logs -package_id $parent_package_id

                # Symlink 'current' to the latest log.

                set log_url "[site_node::get_url -node_id $parent_package_id]$date"
                if {![db_0or1row get_extlink {}]} {

                # Create a 'current' symlink to the
                # new log. As ETP symlinks don't
                # support labels the link is created
                # as an ETP extlink which do support
                # labels and descriptions.

                set link_label "current"
                set link_description "Current $irc_channel_name conversation log"
                db_exec_plsql create_extlink {}

                # Rotate the symlink to the top of the list.

                irc::logger::rotate_logs -package_id $parent_package_id -all

                } else {

                # Point the 'current' symlink to the new log.

                db_dml update_extlink {}

                }
                        } else {
                set log_live_revision_id [etp::get_live_revision_id $parent_package_id $date]
            }

                        # The update the existing ETP page for the log.
                        
                        set log_description "Conversation log of $irc_channel_name of $date"
                        db_dml update_revision {}

                        # Flush the cached page from memory

                        util_memoize_flush "etp::get_pa $parent_package_id $date $content_type"
                    }
                }
            }    
        } else {
            ns_log warning "irc::logger::update_log - IRC logger $logger_url is not directly mounted under an ETP instance but rather $parent_package_key"
        }
    } else {
        ns_log warning "irc::logger::update_log - IRC logger $package_id has been unmounted"
    }
}

d_proc -public irc::logger::scheduled_update {
    -package_id:required
} {

    Scheduled procedure to check for updates of today's IRC log.

    @creation-date 2003-01-27
    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)

    @param package_id The package_id of the mounted IRC logger
    instance to get the log for.

    @return none

    @error none

} {
    # The current log has the name of today's date in the GMT
    # timezone.

    set gmt_today [clock format [clock seconds] -format %Y-%m-%d -gmt true]
    irc::logger::update_log \
        -date $gmt_today \
        -package_id $package_id
}

namespace eval dom::xpathFunc::irc::logger {

    # The namespace of the tDOM XSLT extension functions for the
    # irc-logger module.

}

d_proc -public dom::xpathFunc::irc::logger::user_link {
    ctxNode 
    pos 
    nodeListType 
    nodeList 
    args
} {
        
    <p>Create a link to the user account on this site where the IRC
    nick matches the user's screen name.</p>

    <p>Rolf (rolf@pointsman.de) from the tDOM team on tDOM extension
    functions:</p>

    <blockquote>
    <p>If an XPath expr (both for the selectNodes method and in XSLT
    stylesheets) uses a not standard XPath function name (you cannot
    'overwrite' the C coded standard built-in functions), the engine
    looks, if there is a tcl proc with the given function name in
    the ::dom::xpathFunc:: namespace. In other words: all extension
    functions procs must reside in the namespace ::dom::xpathFunc or
    in a child namespace of that namespace. If the XPath extension
    function has a prefix, the prefix is expanded to the namespace
    URI and that namespace URI must be the name of the child
    namespace of the ::dom::xpathFunc namespace.</p>

    <p>If there is such a proc, this proc is called with the following
    arguments: ctxNode pos nodeListType nodeList args. The 'args'
    are, as type/value pairs, the arguments, that are given to the
    extension functions. (E.g. if you have
    myExtensionFunction('foo'), you will get two args, the first
    "string" the second "foo").</p>

    <p>The tcl proc, which implements the extension function must
    return a list of two elements: {&lt;type&gt; &lt;value&gt;}. The possible
    types at the moment are: "bool""number""string""nodes".</p>

    <p>But don't get confused by my probably (too) vague
    explanations. Just look at the examples in the xpath.test and
    tdom.tcl files. For almost all 'real life' needs, you should get
    it very fast, what to do from that usage examples.</p>
    </blockquote>

    @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz)
    @creation-date 2003-01-31

    @param ctxNode See <a href="http://www.tdom.org">tDOM</a> documentation.
    @param pos See <a href="http://www.tdom.org">tDOM</a> documentation.
    @param nodeListType See <a href="http://www.tdom.org">tDOM</a> documentation.
    @param nodeList See <a href="http://www.tdom.org">tDOM</a> documentation.

    @param args A single (type, value) pair of type 'attrnodes' with
    the nick of the IRC user.

    @return A single (type, value) pair with a link to the user
    account on the site. Or just the nick if no user account was found.

    @error The empty string.

} {

    # Default return value

    set link ""

    # Limited parameter checking. The tDOM related parameters don't
    # matter.

    if {[llength $args] == 2} {

        # Get argument type and value.

        foreach {type value} $args {
            break
        }
        
        # Check that the parameter an attribute node is and extract
        # the value of the attribute.

        if {[string equal $type "attrnodes"]} {
            set nick [lindex [lindex $value end] end]

            # Locate the first user with a screen name of 'nick' on this
            # site. DB caching reduces the number of hits on the DB
            # itself.
        
        # community_member_url was changed to require a conn
        # it always returned / for the subsite since we run from a 
        # scheduled proc. This needs to be smarter.

        set community_member_url "[parameter::get -package_id [ad_acs_kernel_id] -parameter CommunityMemberURL]?[export_vars {user_id}]"

            if {[db_0or1row get_user {}]} {
                set link "<a href=\"$community_member_url\" title=\"$name\">$nick</a>"
            } else {
                set link $nick
            }
        } else {
            ns_log warning "dom::xpathFunc::irc::logger::user_link wrong parameter type '$type($value)'; type should have been attrnodes"
        }
    } else {
        ns_log warning "dom::xpathFunc::irc::logger::user_link accepts only 1 parameter, received [llength $args] parameters"
    }

    return [list string $link]
}