Event Log 0 "My first module us loaded"That's it, simpliest module is ready and can be included into ~/.alicq/alicqrc fiile:
module statusmonitorRun alicq and look at alicq.log file in alicq base directory. It should contain record like:
[25.03.2004 10:45:29]: My first module is loaded
# Find all contacts and invoke MonitorContact for each of # them. proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } } # Fake monitor installer - just log it was invoked. proc MonitorContact {contact} { Event Log 0 "Monitoring contact $contact" } InitMonitoring Event Log 0 "My first module is loaded"This module will work, but there is a problem. If contacts are loaded after this module, no contacts will be selected in InitMonitor procedre. There is a way to load the module after contacts, but this is not best solution. Normally, module should not depend on order of loading. There is Alicq event ConfigLoaded, which is sent after startup file was read and processed. At this moment all modules and contacts are loaded. Properly changed example is:
# Find all contacts and invoke MonitorContact for each of # them. proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } } # Fake monitor installer - just log it was invoked. proc MonitorContact {contact} { Event Log 0 "Monitoring contact $contact" } hook ConfigLoaded [namespace current]::InitMonitoring Event Log 0 "My first module is loaded"Now, MonitorContact will be invoked for all existing contacts. Seems everything is fine. But wait - what if contact is being added during work? It had not existed when InitMonitoring was invoked, and no monitoring is installed for it. Module should monitor creation of new contacts:
# Find all contacts and invoke MonitorContact for each of # them. proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } # Monitor new objects hook New:Contact:ICQ:* [namespace current]::MonitorContact } # Fake monitor installer - just log it was invoked. proc MonitorContact {contact} { Event Log 0 "Monitoring contact $contact" } hook ConfigLoaded [namespace current]::InitMonitoring Event Log 0 "My first module is loaded"Ok, now addition of contacts is monitored, but what about deletion of ones? It can be done, but there is no need in this for our purpose: status of deleted contact never changes and need not to be monitored.
# Find all contacts and invoke MonitorContact for each of # them. proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } hook New:Contact:ICQ:* [namespace current]::MonitorContact } proc MonitorContact {contact} { set ref [ref $contact] trace variable ${ref}(Status) w [nc StatusChanged $contact] Event Log 0 "Monitoring contact $contact" } proc StatusChanged {contact ref field args} { upvar 1 ${ref}($field) status Event Log 0 "Contact $contact changed status to $status" } hook ConfigLoaded [namespace current]::InitMonitoring Event Log 0 "My first module is loaded"This example monitors contacts status and logs it in Alicq log file. It can be not very conveniet, because log file can contain a lot of other information. It is better to save log into separate file.
# Find all contacts and invoke MonitorContact for each of # them. variable logname status.log proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } hook New:Contact:ICQ:* [namespace current]::MonitorContact } proc MonitorContact {contact} { set ref [ref $contact] trace variable ${ref}(Status) w [nc StatusChanged $contact] Event Log 0 "Monitoring contact $contact" } proc StatusChanged {contact ref field args} { upvar 1 ${ref}($field) status variable logname if {[catch { set fd [open $logname a+] puts $fd "$contact $status" close $fd } reason]} { Log 0 "Can not log status of $contact: $reason"} } hook ConfigLoaded [namespace current]::InitMonitoring Event Log 0 "My first module is loaded"
namespace eval meta { set description "Log changes of contact status into file" set name "Status logger" array set active { type boolean default no menu {Tools "Monitor Status"} description "Activate status logging" } array set logname { type file default status.log description "Log file name" } } # Find all contacts and invoke MonitorContact for each of # them. proc InitMonitoring {} { foreach contact [select Contact:ICQ] { MonitorContact $contact } hook New:Contact:ICQ:* [namespace current]::MonitorContact } proc MonitorContact {contact} { set ref [ref $contact] trace variable ${ref}(Status) w [nc StatusChanged $contact] Event Log 0 "Monitoring contact $contact" } proc StatusChanged {contact ref field args} { variable logname variable active # If monitoring is inactive, return without saving if {![string is true $active]} return upvar 1 ${ref}($field) status if {[catch { set fd [open $logname a+] puts $fd "$contact $status" close $fd } reason]} { Log 0 "Can not log status of $contact: $reason"} } hook ConfigLoaded [namespace current]::InitMonitoring Event Log 0 "My first module is loaded"After Alicq is loaded, new item, Tools -> Monitor Status appear in main menu, as well as page "Status logger" in configuration dialog.
proc StatusChanged {contact ref field args} { variable logname variable active # If monitoring is inactive, return without saving if {![string is true $active]} return # Check, if contact is member of monitor group if {![info exists ${ref}(Groups)] || [lsearch [set ${ref}(Groups)] monitor]==-1} return upvar 1 ${ref}($field) status if {[catch { set fd [open $logname a+] puts $fd "$contact $status" close $fd } reason]} { Log 0 "Can not log status of $contact: $reason"} }Now you can create group monitor, if it does not exist, and copy contacts you want to monitor there.