Page MenuHomeDevCentral

D4012.diff
No OneTemporary

D4012.diff

diff --git a/.arcconfig b/.arcconfig
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,5 +1,4 @@
{
- "phabricator.uri": "https://devcentral.nasqueron.org/",
- "repository.callsign": "VIPER"
+ "phabricator.uri": "https://devcentral.nasqueron.org/",
+ "repository.callsign": "VIPER"
}
-
diff --git a/BBS/vt100.tcl b/BBS/vt100.tcl
--- a/BBS/vt100.tcl
+++ b/BBS/vt100.tcl
@@ -6,86 +6,86 @@
set protect-telnet 0
proc listen:vt100 {newidx} {
- putcmdlog "Serving vt100 for idx $newidx."
- listen:vt100:welcome $newidx
- control $newidx control:vt100
+ putcmdlog "Serving vt100 for idx $newidx."
+ listen:vt100:welcome $newidx
+ control $newidx control:vt100
}
proc listen:vt100:welcome {idx} {
- #Menu files in 3 cols
- set txtroot [registry get bbs.vt100.txtroot]
- set files [split [glob $txtroot/*.vt]]
- set pos [strlen $txtroot]
- set cols 3
- set rows [expr [llength $files].0 / $cols]
- set rowsc [expr ceil($rows)]
- set rows [expr floor($rows)]
- for {set i 0} {$i < $rowsc} {incr i} {
- set line ""
- for {set j 0} {$j < $cols} {incr j} {
- set item [string range [lindex $files [expr int ($i + $j * $rows)]] $pos+1 end-3]
- append line [completestring $item 24]
- }
- putdcc $idx $line
- }
- putdcc $idx [string repeat _ 72]
- putdcc $idx "Text to read: "
- return 1
+ #Menu files in 3 cols
+ set txtroot [registry get bbs.vt100.txtroot]
+ set files [split [glob $txtroot/*.vt]]
+ set pos [strlen $txtroot]
+ set cols 3
+ set rows [expr [llength $files].0 / $cols]
+ set rowsc [expr ceil($rows)]
+ set rows [expr floor($rows)]
+ for {set i 0} {$i < $rowsc} {incr i} {
+ set line ""
+ for {set j 0} {$j < $cols} {incr j} {
+ set item [string range [lindex $files [expr int ($i + $j * $rows)]] $pos+1 end-3]
+ append line [completestring $item 24]
+ }
+ putdcc $idx $line
+ }
+ putdcc $idx [string repeat _ 72]
+ putdcc $idx "Text to read: "
+ return 1
}
#Plays the relevant file to $idx, cleans and exit
proc vt100:play {idx} {
- putcmdlog "(vt100) Playing file for idx $idx"
- global vt100
- set txtroot [registry get bbs.vt100.txtroot]
+ putcmdlog "(vt100) Playing file for idx $idx"
+ global vt100
+ set txtroot [registry get bbs.vt100.txtroot]
- set fd [open $txtroot/[dict get $vt100($idx) file].vt r]
- set i 0
- while {![eof $fd] && $i < 1000} {
- #Wait time: 0.0005s
- putdcc $idx [gets $fd]
- after 3
- incr i
- }
- if {$i == 5000} {
- putdcc $idx "Stop at 5000th line."
- putcmdlog "(vt100) Stopping at 5000th line for idx $idx"
- }
- close $fd
- putcmdlog "(vt100) End play file for idx $idx"
+ set fd [open $txtroot/[dict get $vt100($idx) file].vt r]
+ set i 0
+ while {![eof $fd] && $i < 1000} {
+ #Wait time: 0.0005s
+ putdcc $idx [gets $fd]
+ after 3
+ incr i
+ }
+ if {$i == 5000} {
+ putdcc $idx "Stop at 5000th line."
+ putcmdlog "(vt100) Stopping at 5000th line for idx $idx"
+ }
+ close $fd
+ putcmdlog "(vt100) End play file for idx $idx"
- #Cleans and exit
- unset vt100($idx)
- killdcc $idx
+ #Cleans and exit
+ unset vt100($idx)
+ killdcc $idx
}
#Controls the telnet connection
proc control:vt100 {idx text} {
- global vt100
- set txtroot [registry get bbs.vt100.txtroot]
- if ![info exists vt100($idx)] {
- if [file exists $txtroot/$text.vt] {
- #Reads file
- set vt100($idx) [dict create file $text]
+ global vt100
+ set txtroot [registry get bbs.vt100.txtroot]
+ if ![info exists vt100($idx)] {
+ if [file exists $txtroot/$text.vt] {
+ #Reads file
+ set vt100($idx) [dict create file $text]
- #Prints file
- vt100:play $idx
- } {
- putdcc $idx "Not a valid file"
- }
- } {
- switch $text {
- exit {
- putdcc $idx "Ja mata!"
+ #Prints file
+ vt100:play $idx
+ } {
+ putdcc $idx "Not a valid file"
+ }
+ } {
+ switch $text {
+ exit {
+ putdcc $idx "Ja mata!"
- #Cleans and exit
- unset vt100($idx)
- return 1
- }
- default {
- putdcc $idx "Unknown command: $text"
- }
- }
- }
- return 0
+ #Cleans and exit
+ unset vt100($idx)
+ return 1
+ }
+ default {
+ putdcc $idx "Unknown command: $text"
+ }
+ }
+ }
+ return 0
}
diff --git a/Daeghrefn/Channel.tcl b/Daeghrefn/Channel.tcl
--- a/Daeghrefn/Channel.tcl
+++ b/Daeghrefn/Channel.tcl
@@ -11,40 +11,40 @@
#Determines if the URL matches a video site url:getvideotitle can handle
proc url:isvideo {url} {
- foreach site "youtu.be metacafe.com dailymotion video.google.com photobucket.com video.yahoo.com youtube.com depositfiles.com vimeo.com" {
- if {[string first $site $url] > -1} {
- return 1
- }
- }
- return 0
+ foreach site "youtu.be metacafe.com dailymotion video.google.com photobucket.com video.yahoo.com youtube.com depositfiles.com vimeo.com" {
+ if {[string first $site $url] > -1} {
+ return 1
+ }
+ }
+ return 0
}
#Gets video title
proc url:getvideotitle {url} {
- set title ""
- catch {
- set title [exec -- yt-dlp --no-warnings --remote-components ejs:npm -e --extractor-args "youtube:player_client=web" --extractor-args "youtube:visitor_data=[registry get video.youtube.visitor_data.tcl]" $url]
- }
- return $title
+ set title ""
+ catch {
+ set title [exec -- yt-dlp --no-warnings --remote-components ejs:npm -e --extractor-args "youtube:player_client=web" --extractor-args "youtube:visitor_data=[registry get video.youtube.visitor_data.tcl]" $url]
+ }
+ return $title
}
#This proc allows to handle URLs in lines
#Currently, it prints the video title when not provided with the URL
#TODO: checks 402/403/404/500 error codes
proc pubm:url {nick uhost handle channel text} {
- if {![channel get $channel parse-url]} {
- return 0
- }
- foreach url [geturls $text] {
- if [url:isvideo $url] {
- #Prints video information on the channel
- #if it's not already in $text
- set info [url:getvideotitle $url]
- if {[string length [string trim $info]] > 0 && [string first $info $text] == -1} {
- putserv "PRIVMSG $channel :\[Vid\] $info"
- }
- }
- }
+ if {![channel get $channel parse-url]} {
+ return 0
+ }
+ foreach url [geturls $text] {
+ if [url:isvideo $url] {
+ #Prints video information on the channel
+ #if it's not already in $text
+ set info [url:getvideotitle $url]
+ if {[string length [string trim $info]] > 0 && [string first $info $text] == -1} {
+ putserv "PRIVMSG $channel :\[Vid\] $info"
+ }
+ }
+ }
}
#
@@ -52,72 +52,72 @@
#
proc isbotnetsuspecthost {host} {
- if [isip $host] {
- return 1
- }
- foreach domain [registry get protection.botnet.hosts] {
- if [string match $domain $host] {
- return 1
- }
- }
- return 0
+ if [isip $host] {
+ return 1
+ }
+ foreach domain [registry get protection.botnet.hosts] {
+ if [string match $domain $host] {
+ return 1
+ }
+ }
+ return 0
}
proc isfloodquitmessage {reason} {
- foreach floodreason [registry get protection.botnet.reasons] {
- if [string match $reason $floodreason] {
- return 1
- }
- }
- return 0
+ foreach floodreason [registry get protection.botnet.reasons] {
+ if [string match $reason $floodreason] {
+ return 1
+ }
+ }
+ return 0
}
proc sign:excessflood {nick uhost handle channel reason} {
- # We're interested by unknown users quitting with Excess Flood message.
- if {![isfloodquitmessage $reason] || $handle != "*"} {
- return
- }
-
- # Botnet nicks have 3 to 5 characters
- set len [strlen $nick]
- if {$len < 3 || $len > 5} {
- return
- }
-
- # And belong to specific ISPs
- set host [gethost $uhost]
- if [isbotnetsuspecthost $host] {
- add_botnet_ban $host
- }
+ # We're interested by unknown users quitting with Excess Flood message.
+ if {![isfloodquitmessage $reason] || $handle != "*"} {
+ return
+ }
+
+ # Botnet nicks have 3 to 5 characters
+ set len [strlen $nick]
+ if {$len < 3 || $len > 5} {
+ return
+ }
+
+ # And belong to specific ISPs
+ set host [gethost $uhost]
+ if [isbotnetsuspecthost $host] {
+ add_botnet_ban $host
+ }
}
proc dcc:botnet {handle idx arg} {
- if {$arg == ""} {
- putdcc $idx "Usage: .botnet <nick>"
- return
- }
-
- set nick $arg
- set uhost [getchanhost $nick]
-
- if {$uhost == ""} {
- putdcc $idx "User unknown: $nick"
- return
- }
-
- set host [gethost $uhost]
- if [isbotnetsuspecthost $host] {
- add_botnet_ban $host
- return 1
- } {
- putdcc $idx "Not a botnet suspect."
- return
- }
+ if {$arg == ""} {
+ putdcc $idx "Usage: .botnet <nick>"
+ return
+ }
+
+ set nick $arg
+ set uhost [getchanhost $nick]
+
+ if {$uhost == ""} {
+ putdcc $idx "User unknown: $nick"
+ return
+ }
+
+ set host [gethost $uhost]
+ if [isbotnetsuspecthost $host] {
+ add_botnet_ban $host
+ return 1
+ } {
+ putdcc $idx "Not a botnet suspect."
+ return
+ }
}
proc add_botnet_ban {host} {
- global botname
+ global botname
- newchanban [registry get protection.botnet.channel] *!*@$host $botname [registry get protection.botnet.banreason] [registry get protection.botnet.banduration] sticky
- sql "INSERT INTO log_flood (host, `count`) VALUES ('[sqlescape $host]', 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1;"
+ newchanban [registry get protection.botnet.channel] *!*@$host $botname [registry get protection.botnet.banreason] [registry get protection.botnet.banduration] sticky
+ sql "INSERT INTO log_flood (host, `count`) VALUES ('[sqlescape $host]', 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1;"
}
diff --git a/Daeghrefn/Communication.tcl b/Daeghrefn/Communication.tcl
--- a/Daeghrefn/Communication.tcl
+++ b/Daeghrefn/Communication.tcl
@@ -1,7 +1,7 @@
-bind dcc - sms dcc:sms
-bind dcc - mail dcc:mail
+bind dcc - sms dcc:sms
+bind dcc - mail dcc:mail
bind pub - !sms pub:sms
-bind pub - !identica pub:identica
+bind pub - !identica pub:identica
#
# SMS
@@ -10,117 +10,117 @@
#Sends a SMS to $to with $message as text and $from as source
#Returns "" if SMS were sent, the error message otherwise
proc sendsms {from to message} {
- switch [set mode [registry get sms.$to.mode]] {
- 1 {
- #Triskel/Wolfplex form
- set url [registry get sms.$to.url]
- set pass [registry get sms.$to.pass]
- set xtra [registry get sms.$to.xtra]
- if {$url == ""} {return "URL inconnue pour $to"}
-
- #Check length
- set len [string length $from$message]
- if {$len > 113} {
- return "Message trop long, réduisez-le de [expr $len-113] caractère[s $len-113]."
- }
-
- #Posts form
- set query [::http::formatQuery m $from p $message v $pass envoi Envoyer]
- if {$xtra != ""} {append query &$xtra}
- set tok [::http::geturl $url -query $query]
- set result [::http::data $tok]
- ::http::cleanup $tok
-
- #Parses reply
- if {[string first "Impossible d'envoyer" $result] != -1} {
- return "Le formulaire web indique qu'il est immpossible d'envoyer le message."
- } elseif {[string first "Tu as subtilement" $result] != -1} {
- return "Pass incorrect : $pass, regardez sur $url si la question antibot n'a pas été modifiée."
- } elseif {[string first "envoi \[ Ok \]" $result] != -1} {
- return ""
- } {
- putdebug $result
- return "D'après la réponse du formulaire, il n'est pas possible de déterminer si oui ou non il a été envoyé."
- }
- }
-
- "" {
- return "$to n'a pas activé la fonction SMS."
- }
-
- default {
- return "Unknown sms mode: $mode."
- }
- }
+ switch [set mode [registry get sms.$to.mode]] {
+ 1 {
+ #Triskel/Wolfplex form
+ set url [registry get sms.$to.url]
+ set pass [registry get sms.$to.pass]
+ set xtra [registry get sms.$to.xtra]
+ if {$url == ""} {return "URL inconnue pour $to"}
+
+ #Check length
+ set len [string length $from$message]
+ if {$len > 113} {
+ return "Message trop long, réduisez-le de [expr $len-113] caractère[s $len-113]."
+ }
+
+ #Posts form
+ set query [::http::formatQuery m $from p $message v $pass envoi Envoyer]
+ if {$xtra != ""} {append query &$xtra}
+ set tok [::http::geturl $url -query $query]
+ set result [::http::data $tok]
+ ::http::cleanup $tok
+
+ #Parses reply
+ if {[string first "Impossible d'envoyer" $result] != -1} {
+ return "Le formulaire web indique qu'il est immpossible d'envoyer le message."
+ } elseif {[string first "Tu as subtilement" $result] != -1} {
+ return "Pass incorrect : $pass, regardez sur $url si la question antibot n'a pas été modifiée."
+ } elseif {[string first "envoi \[ Ok \]" $result] != -1} {
+ return ""
+ } {
+ putdebug $result
+ return "D'après la réponse du formulaire, il n'est pas possible de déterminer si oui ou non il a été envoyé."
+ }
+ }
+
+ "" {
+ return "$to n'a pas activé la fonction SMS."
+ }
+
+ default {
+ return "Unknown sms mode: $mode."
+ }
+ }
}
#.sms
proc dcc:sms {handle idx arg} {
- # The SMS configuration is stored in the following registry variables:
- # sms.$destinataire.mode 1 Triskel or Wolfplex form
- #
- # For mode 1:
- # sms.$destinataire.url form URL
- # sms.$destinataire.pass e.g. rose
- # sms.$destinataire.xtra not needed for triskel forms, who=Darkknow needed for Wolfplex form
-
- if {$arg == "" || $arg == "config"} {
- #Prints config
- switch [set mode [registry get sms.$handle.mode]] {
- 1 {
- putdcc $idx "URL ..... [registry get sms.$handle.url]"
- if {[set pass [registry get sms.$handle.pass]] != ""]} {
- putdcc $idx "Pass .... $pass"
- }
- if {[set xtra [registry get sms.$handle.xtra]] != ""} {
- putdcc $idx "Extra ... $xtra"
- }
- }
- "" {
- putdcc $idx "Vous n'avez pas encore configuré votre fonctionnalité SMS."
- }
- default {
- putdcc $idx "Unknown sms mode: $mode"
- }
- }
- return 1
- } elseif {[string range $arg 0 6] == "config "} {
- putdcc $idx "Le script interactif de configuration n'est pas encore prêt."
- putcmdlog "#$handle# sms config ..."
- return 0
- } else {
- #Sends a SMS
- set to [lindex $arg 0]
- #TODO: use a proc to remove the first word instead and keep $arg as string
- set message [lrange $arg 1 end]
- if {[set result [sendsms $handle $to $message]] == ""} {
- putdcc $idx "Envoyé."
- putcmdlog "#$handle# sms ..."
- } {
- putdcc $idx $result
- }
- }
- return 0
+ # The SMS configuration is stored in the following registry variables:
+ # sms.$destinataire.mode 1 Triskel or Wolfplex form
+ #
+ # For mode 1:
+ # sms.$destinataire.url form URL
+ # sms.$destinataire.pass e.g. rose
+ # sms.$destinataire.xtra not needed for triskel forms, who=Darkknow needed for Wolfplex form
+
+ if {$arg == "" || $arg == "config"} {
+ #Prints config
+ switch [set mode [registry get sms.$handle.mode]] {
+ 1 {
+ putdcc $idx "URL ..... [registry get sms.$handle.url]"
+ if {[set pass [registry get sms.$handle.pass]] != ""]} {
+ putdcc $idx "Pass .... $pass"
+ }
+ if {[set xtra [registry get sms.$handle.xtra]] != ""} {
+ putdcc $idx "Extra ... $xtra"
+ }
+ }
+ "" {
+ putdcc $idx "Vous n'avez pas encore configuré votre fonctionnalité SMS."
+ }
+ default {
+ putdcc $idx "Unknown sms mode: $mode"
+ }
+ }
+ return 1
+ } elseif {[string range $arg 0 6] == "config "} {
+ putdcc $idx "Le script interactif de configuration n'est pas encore prêt."
+ putcmdlog "#$handle# sms config ..."
+ return 0
+ } else {
+ #Sends a SMS
+ set to [lindex $arg 0]
+ #TODO: use a proc to remove the first word instead and keep $arg as string
+ set message [lrange $arg 1 end]
+ if {[set result [sendsms $handle $to $message]] == ""} {
+ putdcc $idx "Envoyé."
+ putcmdlog "#$handle# sms ..."
+ } {
+ putdcc $idx $result
+ }
+ }
+ return 0
}
#!sms
proc pub:sms {nick uhost handle chan text} {
- #Sends a SMS
- if {$handle == "" || $handle == "*"} {
- set from $nick
- } {
- set from $handle
- }
- set to [lindex $text 0]
- #TODO: use a proc to remove the first word instead and keep $arg as string
- set message [lrange $text 1 end]
- if {[set result [sendsms $from $to $message]] == ""} {
- putquick "PRIVMSG $chan :$nick, c'est envoyé."
- putcmdlog "!$nick! sms ..."
- } {
- putquick "PRIVMSG $chan :$nick, $result."
- }
- return 0
+ #Sends a SMS
+ if {$handle == "" || $handle == "*"} {
+ set from $nick
+ } {
+ set from $handle
+ }
+ set to [lindex $text 0]
+ #TODO: use a proc to remove the first word instead and keep $arg as string
+ set message [lrange $text 1 end]
+ if {[set result [sendsms $from $to $message]] == ""} {
+ putquick "PRIVMSG $chan :$nick, c'est envoyé."
+ putcmdlog "!$nick! sms ..."
+ } {
+ putquick "PRIVMSG $chan :$nick, $result."
+ }
+ return 0
}
#
@@ -129,12 +129,12 @@
#Posts $message on the identi.ca $account account
proc identicapost {account message} {
- package require base64
- set row [lindex [sql "SELECT account_username, account_password FROM identica_accounts WHERE account_code = '$account'"] 0]
- set auth "Basic [base64::encode [join $row :]]"
- set tok [::http::geturl http://identi.ca/api/statuses/update.xml -headers [list Authorization $auth] -query [::http::formatQuery status $message]]
- #putdebug [::http::data $tok]
- ::http::cleanup $tok
+ package require base64
+ set row [lindex [sql "SELECT account_username, account_password FROM identica_accounts WHERE account_code = '$account'"] 0]
+ set auth "Basic [base64::encode [join $row :]]"
+ set tok [::http::geturl http://identi.ca/api/statuses/update.xml -headers [list Authorization $auth] -query [::http::formatQuery status $message]]
+ #putdebug [::http::data $tok]
+ ::http::cleanup $tok
}
#.identica
@@ -144,7 +144,7 @@
#!identica
proc pub:identica {nick uhost handle chan text} {
- putquick "NOTICE $nick :!identica is currently disabled. Is identi.ca still usable since pump.io migration? If so, please request the command."
+ putquick "NOTICE $nick :!identica is currently disabled. Is identi.ca still usable since pump.io migration? If so, please request the command."
}
#
@@ -216,9 +216,9 @@
if {$from != ""} {
puts $fd "From: $from"
}
- puts $fd "To: $to"
- puts $fd "Subject: $subject"
- puts $fd
+ puts $fd "To: $to"
+ puts $fd "Subject: $subject"
+ puts $fd
puts $fd "$message"
flush $fd
close $fd
diff --git a/Daeghrefn/GIS.tcl b/Daeghrefn/GIS.tcl
--- a/Daeghrefn/GIS.tcl
+++ b/Daeghrefn/GIS.tcl
@@ -4,64 +4,64 @@
bind dcc - fantoir dcc:fantoir
namespace eval fantoir {
- #Path to the FANTOIR file
- variable file_all [registry get fantoir.files.all]
+ #Path to the FANTOIR file
+ variable file_all [registry get fantoir.files.all]
- #Path to the FANTOIR file, containing only streets
- variable file_streets [registry get fantoir.files.streets]
+ #Path to the FANTOIR file, containing only streets
+ variable file_streets [registry get fantoir.files.streets]
- # Performs a search
- #
- # @param text The text to search
- # @return the number of lines in the file matching the expression
- proc search {text} {
- variable file_all
- variable file_streets
+ # Performs a search
+ #
+ # @param text The text to search
+ # @return the number of lines in the file matching the expression
+ proc search {text} {
+ variable file_all
+ variable file_streets
- if {[catch {set count_all [exec -- grep -a -c "$text" $file_all]}]} {
- set count_all 0
- }
- set count_all [string trim $count_all]
- set reply "$count_all occurrence[s $count_all]"
- if {$count_all > 0} {
- if {[catch {set count_voies [exec -- grep -a -c "$text" $file_streets]}]} {
- set count_voies 0
- }
- set count_voies [string trim $count_voies]
- append reply " (dont $count_voies voie[s $count_voies])"
- } {
- return $reply
- }
- }
+ if {[catch {set count_all [exec -- grep -a -c "$text" $file_all]}]} {
+ set count_all 0
+ }
+ set count_all [string trim $count_all]
+ set reply "$count_all occurrence[s $count_all]"
+ if {$count_all > 0} {
+ if {[catch {set count_voies [exec -- grep -a -c "$text" $file_streets]}]} {
+ set count_voies 0
+ }
+ set count_voies [string trim $count_voies]
+ append reply " (dont $count_voies voie[s $count_voies])"
+ } {
+ return $reply
+ }
+ }
- # Determines if a search expression is valid
- #
- # @param $expression The expression to check
- # @return 1 if the expression is valid; otherwise, 0
- proc is_valid_search_expression {expression} {
- #TODO: allow some regexp
- expr [regexp "^\[A-Z0-9 ]*\$" $expression] && [string length $expression] < 100
- }
+ # Determines if a search expression is valid
+ #
+ # @param $expression The expression to check
+ # @return 1 if the expression is valid; otherwise, 0
+ proc is_valid_search_expression {expression} {
+ #TODO: allow some regexp
+ expr [regexp "^\[A-Z0-9 ]*\$" $expression] && [string length $expression] < 100
+ }
}
# Handles fantoir dcc bind
proc dcc:fantoir {handle idx arg} {
- set text [string toupper $arg]
- if {![::fantoir::is_valid_search_expression $text]} {
- putdcc $idx "Format incorrect, !fantoir <chaîne de texte à rechercher, sans accent>"
- return 0
- }
- putdcc $idx [::fantoir::search $text]
- return 1
+ set text [string toupper $arg]
+ if {![::fantoir::is_valid_search_expression $text]} {
+ putdcc $idx "Format incorrect, !fantoir <chaîne de texte à rechercher, sans accent>"
+ return 0
+ }
+ putdcc $idx [::fantoir::search $text]
+ return 1
}
# Handles !fantoir pub bind
proc pub:fantoir {nick uhost handle chan text} {
- set text [string toupper $text]
- if {![::fantoir::is_valid_search_expression $text]} {
- puthelp "NOTICE $nick :Format incorrect, !fantoir <chaîne de texte à rechercher, sans accent>"
- return 0
- }
- putserv "PRIVMSG $chan :$nick: [::fantoir::search $text]"
- return 1
+ set text [string toupper $text]
+ if {![::fantoir::is_valid_search_expression $text]} {
+ puthelp "NOTICE $nick :Format incorrect, !fantoir <chaîne de texte à rechercher, sans accent>"
+ return 0
+ }
+ putserv "PRIVMSG $chan :$nick: [::fantoir::search $text]"
+ return 1
}
diff --git a/Daeghrefn/Gerrit.tcl b/Daeghrefn/Gerrit.tcl
--- a/Daeghrefn/Gerrit.tcl
+++ b/Daeghrefn/Gerrit.tcl
@@ -11,565 +11,565 @@
#
namespace eval ::ssh:: {
- proc set_agent {{tryToStartAgent 1}} {
- global env
- set file $env(HOME)/bin/ssh-agent-session
-
- if {![file exists $file]} {
- putcmdlog "Can't find SSH agent information - $file doesn't exist."
- }
-
- #TCSH rules -> set through env array
- set fp [open $file]
- fconfigure $fp -buffering line
- gets $fp line
- while {$line != ""} {
- foreach "command variable value" [split $line] {}
- if {$command == "setenv"} {
- set env($variable) [string range $value 0 end-1]
- }
- gets $fp line
- }
- close $fp
-
- #Checks if agent exists
- if {[string first ssh-agent [get_processname $env(SSH_AGENT_PID)]] == -1} {
- putcmdlog "SSH agent isn't running"
- if {$tryToStartAgent} {
- putdebug "Trying to launch SSH agent..."
- exec -- ssh-agent -c | grep -v echo > $env(HOME)/bin/ssh-agent-session
- if {![add_key]} {
- # TODO: send a note to relevant people key should manually added
- # something like sendNoteToGroup $username T "Key sould be manually added"
- }
- set_agent 0
- }
- }
- }
-
- proc add_key {{key ""}} {
- if {$key == ""} { set key [registry get ssh.key] }
- if {$key != ""} {
- catch { exec -- ssh-add $key } result
- putdebug "Adding SSH key: $result"
- expr [string first "Identity added" $result] > -1
- } {
- return 0
- }
-
- }
-
- proc get_processname {pid} {
- set processes [exec ps xw]
- foreach process [split $processes \n] {
- set current_pid [lindex $process 0]
- set command [lrange $process 4 end]
- if {$pid == $current_pid} { return $command }
- }
- }
-
- # Gets appropriate connection parameter
- #
- # @param $server The server to connect
- # @return The server domain name, prepent by SSH options
- proc get_connection_parameter {server} {
- #TODO: return -p 29418 username@review.anothersite.com when appropriate instead to create SSH config alias
- return $server
- }
+ proc set_agent {{tryToStartAgent 1}} {
+ global env
+ set file $env(HOME)/bin/ssh-agent-session
+
+ if {![file exists $file]} {
+ putcmdlog "Can't find SSH agent information - $file doesn't exist."
+ }
+
+ #TCSH rules -> set through env array
+ set fp [open $file]
+ fconfigure $fp -buffering line
+ gets $fp line
+ while {$line != ""} {
+ foreach "command variable value" [split $line] {}
+ if {$command == "setenv"} {
+ set env($variable) [string range $value 0 end-1]
+ }
+ gets $fp line
+ }
+ close $fp
+
+ #Checks if agent exists
+ if {[string first ssh-agent [get_processname $env(SSH_AGENT_PID)]] == -1} {
+ putcmdlog "SSH agent isn't running"
+ if {$tryToStartAgent} {
+ putdebug "Trying to launch SSH agent..."
+ exec -- ssh-agent -c | grep -v echo > $env(HOME)/bin/ssh-agent-session
+ if {![add_key]} {
+ # TODO: send a note to relevant people key should manually added
+ # something like sendNoteToGroup $username T "Key sould be manually added"
+ }
+ set_agent 0
+ }
+ }
+ }
+
+ proc add_key {{key ""}} {
+ if {$key == ""} { set key [registry get ssh.key] }
+ if {$key != ""} {
+ catch { exec -- ssh-add $key } result
+ putdebug "Adding SSH key: $result"
+ expr [string first "Identity added" $result] > -1
+ } {
+ return 0
+ }
+
+ }
+
+ proc get_processname {pid} {
+ set processes [exec ps xw]
+ foreach process [split $processes \n] {
+ set current_pid [lindex $process 0]
+ set command [lrange $process 4 end]
+ if {$pid == $current_pid} { return $command }
+ }
+ }
+
+ # Gets appropriate connection parameter
+ #
+ # @param $server The server to connect
+ # @return The server domain name, prepent by SSH options
+ proc get_connection_parameter {server} {
+ #TODO: return -p 29418 username@review.anothersite.com when appropriate instead to create SSH config alias
+ return $server
+ }
}
namespace eval ::gerrit:: {
- ## Queries a Gerrit server
- ##
- ## @param $server The Gerrit server
- ## @param $query The query to send
- ## @seealso http://gerrit-documentation.googlecode.com/svn/Documentation/2.5/cmd-query.html
- proc query {server query} {
- exec -- ssh [ssh::get_connection_parameter $server] gerrit query $query
- }
-
- ## Queries a Gerrit server, searching changes with an expression
- ##
- ## @param $server The Gerrit server
- ## @param $project The project
- ## @param $query The query
- proc search {server project query} {
- set query "message:$query"
- if {$project != "*" } {
- append query " project:$project"
- }
- set results ""
- putdebug $query
- foreach line [split [query $server "--format json $query"] "\n"] {
- set c [json::json2dict $line]
- if {![dict exists $c type]} {
- lappend results "\[[dg $c project]\] <[dg $c owner.name]> [dg $c subject] ([status [dg $c status]]) - [dg $c number]"
- }
- }
- return $results
- }
-
- # Gets the approvals for a specified change
- proc approvals {server change} {
- set change [query $server "--format JSON --all-approvals $change"]
- #We exploit here a bug: parsing stops after correct item closure, so \n new json message is ignored
- set change [json::json2dict $change]
- set lastPatchset [lindex [dg $change patchSets] end]
- dg $lastPatchset approvals
- }
-
- proc approvals2xml {approvals {indentLevel 0} {ignoreSubmit 1}} {
- set indent [string repeat "\t" $indentLevel]
- append xml "$indent<approvals>\n"
- foreach approval $approvals {
- set type [dg $approval type]
- if {$type == "SUBM" && $ignoreSubmit} { continue }
- append xml "$indent\t<approval type=\"$type\">
- $indent<user email=\"[dg $approval by.email]\">[dg $approval by.name]</user>
- $indent<date>[dg $approval grantedOn]</date>
- $indent<value>[numberSign [dg $approval value]]</value>
- $indent</approval>\n"
- }
- append xml "$indent</approvals>"
- }
-
- # Gets a string representation of the API status
- #
- # @param $status the API status string code
- # @return the textual representation of the status
- proc status {status} {
- switch $status {
- "NEW" { return "Review in progress" }
- default { return $status }
- }
- }
-
- ## Launches a socket to monitor Gerrit events in real time and initializes events.
- ## This uses a node gateway.
- ##
- ## @seealso http://gerrit-documentation.googlecode.com/svn/Documentation/2.5/cmd-stream-events.html
- proc setup_stream_events {server} {
- set idx [connect [registry get gerrit.$server.streamevents.host] [registry get gerrit.$server.streamevents.port]]
- control $idx gerrit::listen:stream_event
- }
-
- # Listens to a Gerrit stream event
- #
- # @param $idx The connection idx
- # @param $text The message received
- # @return 0 if we continue to control this connection; otherwise, 1
- proc listen:stream_event {idx text} {
- # To ensure a better system stability, we don't directly handle
- # a processus calling the 'ssh' command, but use a lightweight
- # non blocking socket connection:
- #
- # This script <--socket--> Node proxy <--SSH--> Gerrit server
- #
- # We receive line of texts from the proxy. There are chunks of a
- # JSON message (we convert it to a dictionary, to be used here).
- #
- # As the json objects are rather long, it is generally truncated
- # in several lines. Immediately after, a line with "--" is sent:
- #
- # 1. {"type":"comment-added","change":......................
- # 2. ................,"comment":"Dark could be the night."}
- # 3. --
- # 4. {"type":"patchset-created",...........................}
- # 5. --
- # 6. ........
- #
- # Text is stored in a global array, shared with others control
- # procs, called $buffers. The message is to add in the idx key.
- # It should be cleared after, as the idx could be reassigned.
- #
- # When a message is received, we sent the decoded json message
- # to gerrit::callevent, which has the job to fire events and
- # to call event callback procedures.
-
- global buffers
-
- if {$text == ""} {
- putdebug "Connection to Gerrit stream-events gateway closed."
- if [info exists buffers($idx)] { unset buffers($idx) }
- } elseif {$text == "--"} {
- # Process gerrit event
- set event [json::json2dict $buffers($idx)]
- set buffers($idx) ""
- set type [dict get $event type]
- #todo: handle here multiservers
- if { [catch { callevent wmreview $type $event } err] } {
- global errorInfo
- putdebug "A general error occured during the Gerrit event processing."
- putdebug $errorInfo
- }
- } {
- append buffers($idx) $text
- }
- return 0
- }
-
- # Registers a new event
- #
- proc event {type callback} {
- dict lappend gerrit::events $type $callback
- }
-
- # Calls an event proc
- #
- # @param $type the Gerrit type
- # @param $message a dict representation of the JSON message sent by Gerrit
- proc callevent {server type message} {
- # Gerrit events could be from two types:
- #
- # (1) Generic events
- # ------------------
- # They are created with "gerrit::event all callbackproc".
- # The callback procedure args are server, type & message.
- #
- # Every Gerrit event is sent to them.
- #
- # (2) Specific events
- # -------------------
- # Similar create way: "gerrit::event type callbackproc".
- #
- # Only Gerrit events of matching type are sent to them.
- # The callback procedure arguments varie with the type.
- #
- # patchset-created ... server change patchSet uploader
- # change-abandoned ... server change patchSet abandoner reason
- # change-restored .... server change patchSet restorer
- # change-merged ...... server change patchSet submitter
- # comment-added ...... server change patchSet author approvals comment
- # ref-updated ........ server submitter refUpdate
- #
- # The documentation of these structures can be found at this URL:
- # http://gerrit-documentation.googlecode.com/svn/Documentation/2.5.1/json.html
- #
- # The callback procedures are all stored in the global ditionary
- # $gerrit::events.
- #
- # Generic events are fired before specific ones. They can't edit
- # the message. They can't say "no more processing".
- #
-
- if [dict exists $gerrit::events all] {
- foreach procname [dict get $gerrit::events all] {
- if [catch {$procname $server $type $message} err] {
- putdebug "An error occured in $procname (called by a $type event):"
- global errorInfo
- putdebug $errorInfo
- putdebug $message
- }
- }
- }
-
- if [dict exists $gerrit::events $type] {
- # Determines the proc arguments from the Gerrit message type
- switch $type {
- "patchset-created" { set params "change patchSet uploader" }
- "change-abandoned" { set params "change patchSet abandoner reason" }
- "change-restored" { set params "change patchSet restorer" }
- "change-merged" { set params "change patchSet submitter" }
- "comment-added" { set params "change patchSet author approvals comment" }
- "ref-updated" { set params "submitter refUpdate" }
-
- default {
- putdebug "Unknown Gerrit type in gerrit::callevent: $type"
- return
- }
- }
-
- # Gets the values of the proc arguments
- set args $server
- foreach param $params {
- if [dict exists $message $param] {
- lappend args [dict get $message $param]
- } {
- lappend args ""
- }
- }
-
- # Calls callbacks procs
- foreach procname [dict get $gerrit::events $type] {
- if [catch {$procname {*}$args} err] {
- global errorInfo
- putdebug "An error occured in $procname (called by a $type event):"
- putdebug $errorInfo
- putdebug $message
- }
- }
- }
- }
-
- # The events callback methods
- set events {}
-
- # # # # # # # # # # # # # # #
-
- # Handles statistics
- proc stats {server type message} {
- registry incr gerrit.stats.type.$type
- }
-
- # Announces a call
- proc debug {server type message} {
- putdebug "$server -> $type +1"
- }
-
- proc onNewPatchset {server change patchset uploader} {
- # Gets relevant variables from change, patchset & uploader
- set who [dict get $uploader name]
- foreach var "project branch topic subject url topic id" {
- set $var [dg $change $var]
- }
- set patchsetNumber [dict get $patchset number]
-
- #IRC notification
- if {$server == "wmreview" && $who != "L10n-bot"} {
- set message "\[$project] $who uploaded a [numeric2ordinal $patchsetNumber] patchset to change '$subject'"
- if {$branch != "master"} { append message " in branch $branch" }
- append message " - $url"
- }
- #if {[string range $project 0 9] == "mediawiki/"} {
- # puthelp "PRIVMSG #mediawiki :$message"
- #}
-
- # Activity feed
- set email [dict get $uploader email]
- set item " <item type=\"patchset\">
- <date>[unixtime]</date>
- <user email=\"$email\">$who</user>
- <project>$project</project>
- <branch>$branch</branch>
- <topic>$topic</topic>
- <change id=\"$id\">[xmlescape $subject]</change>
- </item>"
- writeActivityFeeds $email $project $item
- }
-
- proc onChangeAbandoned {server change patchSet abandoner reason} {
+ ## Queries a Gerrit server
+ ##
+ ## @param $server The Gerrit server
+ ## @param $query The query to send
+ ## @seealso http://gerrit-documentation.googlecode.com/svn/Documentation/2.5/cmd-query.html
+ proc query {server query} {
+ exec -- ssh [ssh::get_connection_parameter $server] gerrit query $query
+ }
+
+ ## Queries a Gerrit server, searching changes with an expression
+ ##
+ ## @param $server The Gerrit server
+ ## @param $project The project
+ ## @param $query The query
+ proc search {server project query} {
+ set query "message:$query"
+ if {$project != "*" } {
+ append query " project:$project"
+ }
+ set results ""
+ putdebug $query
+ foreach line [split [query $server "--format json $query"] "\n"] {
+ set c [json::json2dict $line]
+ if {![dict exists $c type]} {
+ lappend results "\[[dg $c project]\] <[dg $c owner.name]> [dg $c subject] ([status [dg $c status]]) - [dg $c number]"
+ }
+ }
+ return $results
+ }
+
+ # Gets the approvals for a specified change
+ proc approvals {server change} {
+ set change [query $server "--format JSON --all-approvals $change"]
+ #We exploit here a bug: parsing stops after correct item closure, so \n new json message is ignored
+ set change [json::json2dict $change]
+ set lastPatchset [lindex [dg $change patchSets] end]
+ dg $lastPatchset approvals
+ }
+
+ proc approvals2xml {approvals {indentLevel 0} {ignoreSubmit 1}} {
+ set indent [string repeat "\t" $indentLevel]
+ append xml "$indent<approvals>\n"
+ foreach approval $approvals {
+ set type [dg $approval type]
+ if {$type == "SUBM" && $ignoreSubmit} { continue }
+ append xml "$indent\t<approval type=\"$type\">
+ $indent<user email=\"[dg $approval by.email]\">[dg $approval by.name]</user>
+ $indent<date>[dg $approval grantedOn]</date>
+ $indent<value>[numberSign [dg $approval value]]</value>
+ $indent</approval>\n"
+ }
+ append xml "$indent</approvals>"
+ }
+
+ # Gets a string representation of the API status
+ #
+ # @param $status the API status string code
+ # @return the textual representation of the status
+ proc status {status} {
+ switch $status {
+ "NEW" { return "Review in progress" }
+ default { return $status }
+ }
+ }
+
+ ## Launches a socket to monitor Gerrit events in real time and initializes events.
+ ## This uses a node gateway.
+ ##
+ ## @seealso http://gerrit-documentation.googlecode.com/svn/Documentation/2.5/cmd-stream-events.html
+ proc setup_stream_events {server} {
+ set idx [connect [registry get gerrit.$server.streamevents.host] [registry get gerrit.$server.streamevents.port]]
+ control $idx gerrit::listen:stream_event
+ }
+
+ # Listens to a Gerrit stream event
+ #
+ # @param $idx The connection idx
+ # @param $text The message received
+ # @return 0 if we continue to control this connection; otherwise, 1
+ proc listen:stream_event {idx text} {
+ # To ensure a better system stability, we don't directly handle
+ # a processus calling the 'ssh' command, but use a lightweight
+ # non blocking socket connection:
+ #
+ # This script <--socket--> Node proxy <--SSH--> Gerrit server
+ #
+ # We receive line of texts from the proxy. There are chunks of a
+ # JSON message (we convert it to a dictionary, to be used here).
+ #
+ # As the json objects are rather long, it is generally truncated
+ # in several lines. Immediately after, a line with "--" is sent:
+ #
+ # 1. {"type":"comment-added","change":......................
+ # 2. ................,"comment":"Dark could be the night."}
+ # 3. --
+ # 4. {"type":"patchset-created",...........................}
+ # 5. --
+ # 6. ........
+ #
+ # Text is stored in a global array, shared with others control
+ # procs, called $buffers. The message is to add in the idx key.
+ # It should be cleared after, as the idx could be reassigned.
+ #
+ # When a message is received, we sent the decoded json message
+ # to gerrit::callevent, which has the job to fire events and
+ # to call event callback procedures.
+
+ global buffers
+
+ if {$text == ""} {
+ putdebug "Connection to Gerrit stream-events gateway closed."
+ if [info exists buffers($idx)] { unset buffers($idx) }
+ } elseif {$text == "--"} {
+ # Process gerrit event
+ set event [json::json2dict $buffers($idx)]
+ set buffers($idx) ""
+ set type [dict get $event type]
+ #todo: handle here multiservers
+ if { [catch { callevent wmreview $type $event } err] } {
+ global errorInfo
+ putdebug "A general error occured during the Gerrit event processing."
+ putdebug $errorInfo
+ }
+ } {
+ append buffers($idx) $text
+ }
+ return 0
+ }
+
+ # Registers a new event
+ #
+ proc event {type callback} {
+ dict lappend gerrit::events $type $callback
+ }
+
+ # Calls an event proc
+ #
+ # @param $type the Gerrit type
+ # @param $message a dict representation of the JSON message sent by Gerrit
+ proc callevent {server type message} {
+ # Gerrit events could be from two types:
+ #
+ # (1) Generic events
+ # ------------------
+ # They are created with "gerrit::event all callbackproc".
+ # The callback procedure args are server, type & message.
+ #
+ # Every Gerrit event is sent to them.
+ #
+ # (2) Specific events
+ # -------------------
+ # Similar create way: "gerrit::event type callbackproc".
+ #
+ # Only Gerrit events of matching type are sent to them.
+ # The callback procedure arguments varie with the type.
+ #
+ # patchset-created ... server change patchSet uploader
+ # change-abandoned ... server change patchSet abandoner reason
+ # change-restored .... server change patchSet restorer
+ # change-merged ...... server change patchSet submitter
+ # comment-added ...... server change patchSet author approvals comment
+ # ref-updated ........ server submitter refUpdate
+ #
+ # The documentation of these structures can be found at this URL:
+ # http://gerrit-documentation.googlecode.com/svn/Documentation/2.5.1/json.html
+ #
+ # The callback procedures are all stored in the global ditionary
+ # $gerrit::events.
+ #
+ # Generic events are fired before specific ones. They can't edit
+ # the message. They can't say "no more processing".
+ #
+
+ if [dict exists $gerrit::events all] {
+ foreach procname [dict get $gerrit::events all] {
+ if [catch {$procname $server $type $message} err] {
+ putdebug "An error occured in $procname (called by a $type event):"
+ global errorInfo
+ putdebug $errorInfo
+ putdebug $message
+ }
+ }
+ }
+
+ if [dict exists $gerrit::events $type] {
+ # Determines the proc arguments from the Gerrit message type
+ switch $type {
+ "patchset-created" { set params "change patchSet uploader" }
+ "change-abandoned" { set params "change patchSet abandoner reason" }
+ "change-restored" { set params "change patchSet restorer" }
+ "change-merged" { set params "change patchSet submitter" }
+ "comment-added" { set params "change patchSet author approvals comment" }
+ "ref-updated" { set params "submitter refUpdate" }
+
+ default {
+ putdebug "Unknown Gerrit type in gerrit::callevent: $type"
+ return
+ }
+ }
+
+ # Gets the values of the proc arguments
+ set args $server
+ foreach param $params {
+ if [dict exists $message $param] {
+ lappend args [dict get $message $param]
+ } {
+ lappend args ""
+ }
+ }
+
+ # Calls callbacks procs
+ foreach procname [dict get $gerrit::events $type] {
+ if [catch {$procname {*}$args} err] {
+ global errorInfo
+ putdebug "An error occured in $procname (called by a $type event):"
+ putdebug $errorInfo
+ putdebug $message
+ }
+ }
+ }
+ }
+
+ # The events callback methods
+ set events {}
+
+ # # # # # # # # # # # # # # #
+
+ # Handles statistics
+ proc stats {server type message} {
+ registry incr gerrit.stats.type.$type
+ }
+
+ # Announces a call
+ proc debug {server type message} {
+ putdebug "$server -> $type +1"
+ }
+
+ proc onNewPatchset {server change patchset uploader} {
+ # Gets relevant variables from change, patchset & uploader
+ set who [dict get $uploader name]
+ foreach var "project branch topic subject url topic id" {
+ set $var [dg $change $var]
+ }
+ set patchsetNumber [dict get $patchset number]
+
+ #IRC notification
+ if {$server == "wmreview" && $who != "L10n-bot"} {
+ set message "\[$project] $who uploaded a [numeric2ordinal $patchsetNumber] patchset to change '$subject'"
+ if {$branch != "master"} { append message " in branch $branch" }
+ append message " - $url"
+ }
+ #if {[string range $project 0 9] == "mediawiki/"} {
+ # puthelp "PRIVMSG #mediawiki :$message"
+ #}
+
+ # Activity feed
+ set email [dict get $uploader email]
+ set item " <item type=\"patchset\">
+ <date>[unixtime]</date>
+ <user email=\"$email\">$who</user>
+ <project>$project</project>
+ <branch>$branch</branch>
+ <topic>$topic</topic>
+ <change id=\"$id\">[xmlescape $subject]</change>
+ </item>"
+ writeActivityFeeds $email $project $item
+ }
+
+ proc onChangeAbandoned {server change patchSet abandoner reason} {
if {$server == "wmreview"} {
- foreach var "id project branch topic subject" { set $var [dg $change $var] }
- set itemBase "
- <date>[unixtime]</date>
- <user email=\"[dg $abandoner email]\">[dg $abandoner name]</user>
- <project>$project</project>
- <branch>$branch</branch>
- <topic>$topic</topic>
- <change id=\"$id\">[xmlescape $subject]</change>
- <message>$reason</message>"
- set item "\t<item type=\"abandon\">$itemBase\n\t</item>"
- set itemMerged "\t<item type=\"abandoned\">\n\t\t<owner email=\"[dg $change owner.email]\">[dg $change owner.name]</owner>$itemBase\n\t</item>"
-
- set dir [registry get gerrit.feeds.path]
- writeActivityFeed $dir/user/[guidmd5 [dg $abandoner email]].xml $item
- if {[dg $change owner.email] != [dg $abandoner email]} {
- writeActivityFeed $dir/user/[guidmd5 [dg $change owner.email]].xml $itemMerged
- }
- writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $itemMerged
- }
- }
-
- proc onCommentAdded {server change patchset author approvals comment} {
- # Gets relevant variables from change, patchset & uploader
- set who [dict get $author name]
- foreach var "project branch topic subject url id status" {
- if [dict exists $change $var] {
- set $var [dict get $change $var]
- } {
- set $var ""
- }
- }
- set CR 0
- if {$approvals != ""} {
- foreach approval $approvals {
- if {[dict get $approval type] == "CRVW"} {
- set CR [dict get $approval value]
- break
- }
- }
- }
-
- #Wikimedia: IRC notification, activity feed
- if {$server == "wmreview" && $who != "jenkins-bot"} {
- # English message
- set verbs {
- "\0034puts a veto on\003"
- "\0034suggests improvement on\003"
- "comments"
- "\0033approves\003"
- "\0033definitely approves\003"
- }
- set verb [lindex $verbs [expr $CR + 2]]
- regexp "\[a-z\\s\]+" $verb plainVerb
- set message "\[$project] $who $verb change '$subject'"
- if {$comment != ""} {
- if {[strlen $message] > 160} {
- append message ": '[string range $comment 0 158]...'"
- } {
- append message ": '$comment'"
- }
- }
- append message " - $url"
-
- # IRC notification
- if 0 {
- if {[string range $project 0 9] == "mediawiki/" && ($comment != "" || $CR < 0)} {
- puthelp "PRIVMSG #mediawiki :$message"
- } {
- putdebug "Not on IRC -> $message"
- }
- }
-
- # Activity feed
- set message [string map [list $verb $plainVerb] $message]
- set email [dict get $author email]
- set item " <item type=\"comment\">
- <date>[unixtime]</date>
- <user email=\"$email\">$who</user>
- <project>$project</project>
- <change id=\"$id\">[xmlescape $subject]</change>
- <message cr=\"$CR\">[xmlescape $comment]</message>
- </item>"
- writeActivityFeeds $email $project $item
- }
- }
-
- # Called when a Gerrit change ismerged
- proc onChangeMerged {server change patchSet submitter} {
+ foreach var "id project branch topic subject" { set $var [dg $change $var] }
+ set itemBase "
+ <date>[unixtime]</date>
+ <user email=\"[dg $abandoner email]\">[dg $abandoner name]</user>
+ <project>$project</project>
+ <branch>$branch</branch>
+ <topic>$topic</topic>
+ <change id=\"$id\">[xmlescape $subject]</change>
+ <message>$reason</message>"
+ set item "\t<item type=\"abandon\">$itemBase\n\t</item>"
+ set itemMerged "\t<item type=\"abandoned\">\n\t\t<owner email=\"[dg $change owner.email]\">[dg $change owner.name]</owner>$itemBase\n\t</item>"
+
+ set dir [registry get gerrit.feeds.path]
+ writeActivityFeed $dir/user/[guidmd5 [dg $abandoner email]].xml $item
+ if {[dg $change owner.email] != [dg $abandoner email]} {
+ writeActivityFeed $dir/user/[guidmd5 [dg $change owner.email]].xml $itemMerged
+ }
+ writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $itemMerged
+ }
+ }
+
+ proc onCommentAdded {server change patchset author approvals comment} {
+ # Gets relevant variables from change, patchset & uploader
+ set who [dict get $author name]
+ foreach var "project branch topic subject url id status" {
+ if [dict exists $change $var] {
+ set $var [dict get $change $var]
+ } {
+ set $var ""
+ }
+ }
+ set CR 0
+ if {$approvals != ""} {
+ foreach approval $approvals {
+ if {[dict get $approval type] == "CRVW"} {
+ set CR [dict get $approval value]
+ break
+ }
+ }
+ }
+
+ #Wikimedia: IRC notification, activity feed
+ if {$server == "wmreview" && $who != "jenkins-bot"} {
+ # English message
+ set verbs {
+ "\0034puts a veto on\003"
+ "\0034suggests improvement on\003"
+ "comments"
+ "\0033approves\003"
+ "\0033definitely approves\003"
+ }
+ set verb [lindex $verbs [expr $CR + 2]]
+ regexp "\[a-z\\s\]+" $verb plainVerb
+ set message "\[$project] $who $verb change '$subject'"
+ if {$comment != ""} {
+ if {[strlen $message] > 160} {
+ append message ": '[string range $comment 0 158]...'"
+ } {
+ append message ": '$comment'"
+ }
+ }
+ append message " - $url"
+
+ # IRC notification
+ if 0 {
+ if {[string range $project 0 9] == "mediawiki/" && ($comment != "" || $CR < 0)} {
+ puthelp "PRIVMSG #mediawiki :$message"
+ } {
+ putdebug "Not on IRC -> $message"
+ }
+ }
+
+ # Activity feed
+ set message [string map [list $verb $plainVerb] $message]
+ set email [dict get $author email]
+ set item " <item type=\"comment\">
+ <date>[unixtime]</date>
+ <user email=\"$email\">$who</user>
+ <project>$project</project>
+ <change id=\"$id\">[xmlescape $subject]</change>
+ <message cr=\"$CR\">[xmlescape $comment]</message>
+ </item>"
+ writeActivityFeeds $email $project $item
+ }
+ }
+
+ # Called when a Gerrit change ismerged
+ proc onChangeMerged {server change patchSet submitter} {
if {$server == "wmreview" && [dg $submitter name] != "L10n-bot"} {
- foreach var "id project branch topic subject" { set $var [dg $change $var] }
- set itemBase "
- <date>[unixtime]</date>
- <user email=\"[dg $submitter email]\">[dg $submitter name]</user>
- <project>$project</project>
- <branch>$branch</branch>
- <topic>$topic</topic>
- <change id=\"$id\">[xmlescape $subject]</change>\n"
- set approvals [approvals $server $id]
- append itemBase [gerrit::approvals2xml $approvals 2 1]
- set item "\t<item type=\"merge\">$itemBase\n\t</item>"
- set itemMerged "\t<item type=\"merged\">\n\t\t<owner email=\"[dg $change owner.email]\">[dg $change owner.name]</owner>$itemBase\n\t</item>"
-
- set dir [registry get gerrit.feeds.path]
- writeActivityFeed $dir/user/[guidmd5 [dg $submitter email]].xml $item
- if {[dg $change owner.email] != [dg $submitter email]} {
- writeActivityFeed $dir/user/[guidmd5 [dg $change owner.email]].xml $itemMerged
- }
- writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $itemMerged
- #TODO: OPW
- }
- }
-
- # Writes an activity feed item to the relevant feeds
- #
- # @param $who The user e-mail
- # @param $project The project
- # @param $item The XML item
- proc writeActivityFeeds {who project item} {
- set dir [registry get gerrit.feeds.path]
- writeActivityFeed $dir/user/[guidmd5 $who].xml $item
- writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $item
- #TODO: opw feed
- }
-
- # Writes an activity feed item to the specifief file
- #
- # @param $file The output file
- # @param $item The XML item
- proc writeActivityFeed {file item} {
- if ![file exists $file] {
- set fd [open $file w]
- puts $fd "<items>"
- puts $fd $item
- puts $fd "</items>"
- } {
- set fd [open $file {RDWR CREAT}]
- set header [read $fd 4096]
- set startFound 0
- set pos [string first "<items" $header]
- if {$pos > -1} {
- set pos [string first ">" $header $pos]
- if {$pos > -1} {
- set startFound 1
- incr pos
- }
- }
- if $startFound {
- # Appends <item> block after <items>
- # Prepare our file in a temporary $fdtmp
- set fdtmp [file tempfile]
- seek $fd 0 start
- puts $fdtmp [read $fd $pos]
- puts -nonewline $fdtmp $item
- puts -nonewline $fdtmp [read $fd]
- flush $fdtmp
- seek $fdtmp 0 start
- seek $fd 0 start
- puts $fd [string trim [read $fdtmp]]
- close $fdtmp
- } {
- # Adds a comment at the end of the file
- seek $fd 0 end
- puts $fd "<!-- Can't find <items> / added at [unixtime]:"
- puts $fd $item
- puts $fd "-->"
- }
- }
- flush $fd
- close $fd
-
- }
+ foreach var "id project branch topic subject" { set $var [dg $change $var] }
+ set itemBase "
+ <date>[unixtime]</date>
+ <user email=\"[dg $submitter email]\">[dg $submitter name]</user>
+ <project>$project</project>
+ <branch>$branch</branch>
+ <topic>$topic</topic>
+ <change id=\"$id\">[xmlescape $subject]</change>\n"
+ set approvals [approvals $server $id]
+ append itemBase [gerrit::approvals2xml $approvals 2 1]
+ set item "\t<item type=\"merge\">$itemBase\n\t</item>"
+ set itemMerged "\t<item type=\"merged\">\n\t\t<owner email=\"[dg $change owner.email]\">[dg $change owner.name]</owner>$itemBase\n\t</item>"
+
+ set dir [registry get gerrit.feeds.path]
+ writeActivityFeed $dir/user/[guidmd5 [dg $submitter email]].xml $item
+ if {[dg $change owner.email] != [dg $submitter email]} {
+ writeActivityFeed $dir/user/[guidmd5 [dg $change owner.email]].xml $itemMerged
+ }
+ writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $itemMerged
+ #TODO: OPW
+ }
+ }
+
+ # Writes an activity feed item to the relevant feeds
+ #
+ # @param $who The user e-mail
+ # @param $project The project
+ # @param $item The XML item
+ proc writeActivityFeeds {who project item} {
+ set dir [registry get gerrit.feeds.path]
+ writeActivityFeed $dir/user/[guidmd5 $who].xml $item
+ writeActivityFeed $dir/project/[string map {/ . - _} $project].xml $item
+ #TODO: opw feed
+ }
+
+ # Writes an activity feed item to the specifief file
+ #
+ # @param $file The output file
+ # @param $item The XML item
+ proc writeActivityFeed {file item} {
+ if ![file exists $file] {
+ set fd [open $file w]
+ puts $fd "<items>"
+ puts $fd $item
+ puts $fd "</items>"
+ } {
+ set fd [open $file {RDWR CREAT}]
+ set header [read $fd 4096]
+ set startFound 0
+ set pos [string first "<items" $header]
+ if {$pos > -1} {
+ set pos [string first ">" $header $pos]
+ if {$pos > -1} {
+ set startFound 1
+ incr pos
+ }
+ }
+ if $startFound {
+ # Appends <item> block after <items>
+ # Prepare our file in a temporary $fdtmp
+ set fdtmp [file tempfile]
+ seek $fd 0 start
+ puts $fdtmp [read $fd $pos]
+ puts -nonewline $fdtmp $item
+ puts -nonewline $fdtmp [read $fd]
+ flush $fdtmp
+ seek $fdtmp 0 start
+ seek $fd 0 start
+ puts $fd [string trim [read $fdtmp]]
+ close $fdtmp
+ } {
+ # Adds a comment at the end of the file
+ seek $fd 0 end
+ puts $fd "<!-- Can't find <items> / added at [unixtime]:"
+ puts $fd $item
+ puts $fd "-->"
+ }
+ }
+ flush $fd
+ close $fd
+
+ }
}
#
# Gerrit binds
-#
+#
# .gerrit query
# .gerrit stats
# .gerrit search <project> <query to searh in commit message>
proc dcc:gerrit {handle idx arg} {
- set server [registry get gerrit.defaultserver]
-
- switch [lindex $arg 0] {
- "" {
- putdcc $idx "Usage: .gerrit <query>"
- putdcc $idx "Cmds: .gerrit stats"
- putdcc $idx "Cmds: .gerrit search <project> <query to searh in commit message>"
- return 0
- }
-
- "stats" {
- foreach row [sql "SELECT SUBSTRING(data, 19), value FROM registry WHERE LEFT(data, 18) = 'gerrit.stats.type.'"] {
- putdcc $idx $row
- }
- return 1
- }
-
- "search" {
- set nbResults 0
- set project [lindex $arg 1]
- set query [lrange $arg 2 end]
- foreach result [gerrit::search $server $project $query] {
- putdcc $idx $result
- incr nbResults
- }
- if {$nbResults == 0} {
- putdcc $idx ":/"
- } {
- putcmdlog "#$handle# gerrit search ..."
- }
- return 0
- }
-
- default {
- # TODO: support several Gerrit servers
- putdcc $idx [gerrit::query $server $arg]
- putcmdlog "#$handle# gerrit ..."
- return 0
- }
- }
+ set server [registry get gerrit.defaultserver]
+
+ switch [lindex $arg 0] {
+ "" {
+ putdcc $idx "Usage: .gerrit <query>"
+ putdcc $idx "Cmds: .gerrit stats"
+ putdcc $idx "Cmds: .gerrit search <project> <query to searh in commit message>"
+ return 0
+ }
+
+ "stats" {
+ foreach row [sql "SELECT SUBSTRING(data, 19), value FROM registry WHERE LEFT(data, 18) = 'gerrit.stats.type.'"] {
+ putdcc $idx $row
+ }
+ return 1
+ }
+
+ "search" {
+ set nbResults 0
+ set project [lindex $arg 1]
+ set query [lrange $arg 2 end]
+ foreach result [gerrit::search $server $project $query] {
+ putdcc $idx $result
+ incr nbResults
+ }
+ if {$nbResults == 0} {
+ putdcc $idx ":/"
+ } {
+ putcmdlog "#$handle# gerrit search ..."
+ }
+ return 0
+ }
+
+ default {
+ # TODO: support several Gerrit servers
+ putdcc $idx [gerrit::query $server $arg]
+ putcmdlog "#$handle# gerrit ..."
+ return 0
+ }
+ }
}
#
diff --git a/Daeghrefn/Last.fm.tcl b/Daeghrefn/Last.fm.tcl
--- a/Daeghrefn/Last.fm.tcl
+++ b/Daeghrefn/Last.fm.tcl
@@ -5,63 +5,63 @@
bind dcc - lastfm dcc:lastfm
proc dcc:lastfm {handle idx arg} {
- switch [set command [lindex $arg 0]] {
- "" {
- return [*dcc:help $handle $idx lastfm]
- }
+ switch [set command [lindex $arg 0]] {
+ "" {
+ return [*dcc:help $handle $idx lastfm]
+ }
- "count" {
+ "count" {
- }
+ }
- "top5" {
- set username [lindex $arg 1]
- if {$username == ""} { set username $handle }
- set i 0
- foreach track [lastfm::library_getTracks $username 5] {
- putdcc $idx "[incr i]. [dg $track artist.name] - [dg $track name] ([dg $track playcount])"
- }
- }
+ "top5" {
+ set username [lindex $arg 1]
+ if {$username == ""} { set username $handle }
+ set i 0
+ foreach track [lastfm::library_getTracks $username 5] {
+ putdcc $idx "[incr i]. [dg $track artist.name] - [dg $track name] ([dg $track playcount])"
+ }
+ }
- default {
- putdcc $idx "Unknown command: $command"
- return 0
- }
- }
+ default {
+ putdcc $idx "Unknown command: $command"
+ return 0
+ }
+ }
}
namespace eval ::lastfm {
- proc library_getTracks {username {tracks 50} {artist ""}} {
- set url "?method=library.gettracks&&user=[url::encode $username]&limit=$tracks"
- if {$artist != ""} {
- append url &artist=[url::encode $artist]
- }
- set result [get_json $url]
- dg $result tracks.track
- }
+ proc library_getTracks {username {tracks 50} {artist ""}} {
+ set url "?method=library.gettracks&&user=[url::encode $username]&limit=$tracks"
+ if {$artist != ""} {
+ append url &artist=[url::encode $artist]
+ }
+ set result [get_json $url]
+ dg $result tracks.track
+ }
- proc getTrackPlayCount {username artist track} {
- foreach artistTrack [library_getTracks $username 500 $artist] {
- if {[string tolower [dg $artistTrack name]] == [string tolower $track]} {
- return [dg $artistTrack playcount]
- }
- }
- return 0
- }
+ proc getTrackPlayCount {username artist track} {
+ foreach artistTrack [library_getTracks $username 500 $artist] {
+ if {[string tolower [dg $artistTrack name]] == [string tolower $track]} {
+ return [dg $artistTrack playcount]
+ }
+ }
+ return 0
+ }
- proc get_json {url} {
- set url [url]${url}&api_key=[key]&format=json
- set token [http::geturl $url]
- set data [http::data $token]
- http::cleanup $token
- json::json2dict $data
- }
+ proc get_json {url} {
+ set url [url]${url}&api_key=[key]&format=json
+ set token [http::geturl $url]
+ set data [http::data $token]
+ http::cleanup $token
+ json::json2dict $data
+ }
- proc key {} {
- registry get lastfm.api.key
- }
+ proc key {} {
+ registry get lastfm.api.key
+ }
- proc url {} {
- registry get lastfm.api.url
- }
+ proc url {} {
+ registry get lastfm.api.url
+ }
}
diff --git a/Daeghrefn/MediaWiki.tcl b/Daeghrefn/MediaWiki.tcl
--- a/Daeghrefn/MediaWiki.tcl
+++ b/Daeghrefn/MediaWiki.tcl
@@ -1,11 +1,11 @@
# .tcl source scripts/Daeghrefn/MediaWiki.tcl
#
-# MediaWiki RC
+# MediaWiki RC
#
#
# Configuration
-#
+#
set MediaWikiRC(source) 127.0.0.1
set MediaWikiRC(port) 8676
set MediaWikiRC(channel) #wolfplex
@@ -18,17 +18,17 @@
#Gets editor
proc get_editor {message} {
- set message [stripcodes abcgru $message]
- regexp "\\* (.*?) \\*" $message match0 match1
- if {![info exists match1]} {
- return ""
- }
- return $match1
+ set message [stripcodes abcgru $message]
+ regexp "\\* (.*?) \\*" $message match0 match1
+ if {![info exists match1]} {
+ return ""
+ }
+ return $match1
}
#Checks if editor is known
proc is_known_editor {editor} {
- expr {$editor == "Dereckson" || $editor == "Spike"}
+ expr {$editor == "Dereckson" || $editor == "Spike"}
}
#Handles UDP event from $sock
@@ -39,14 +39,14 @@
#Check if peer is source IP to avoid flood
if {[string range $peer 0 [string length $MediaWikiRC(source)]-1] == $MediaWikiRC(source)} {
#putdebug "Received on udp: $pkt"
- #putdebug "Editor: [get_editor $pkt]"
+ #putdebug "Editor: [get_editor $pkt]"
if {$MediaWikiRC(warnKnownEditorsChanges) || ![is_known_editor [get_editor $pkt]]} {
if $MediaWikiRC(color) {
puthelp "PRIVMSG $MediaWikiRC(channel) :$pkt"
} {
puthelp "PRIVMSG $MediaWikiRC(channel) :[stripcodes abcgru $pkt]"
}
- }
+ }
} {
putdebug "$peer: [string length $pkt] {$pkt}"
}
diff --git a/Daeghrefn/Server.tcl b/Daeghrefn/Server.tcl
--- a/Daeghrefn/Server.tcl
+++ b/Daeghrefn/Server.tcl
@@ -26,37 +26,37 @@
# Binds
#
-bind bot - tc2 bot:tc2
+bind bot - tc2 bot:tc2
#Commands aliases only, main commands are handled by tc2:initialize
- bind dcc W php-fpm dcc:phpfpm
- bind pub W .php-fpm pub:phpfpm
- bind pub - .df pub:df
+ bind dcc W php-fpm dcc:phpfpm
+ bind pub W .php-fpm pub:phpfpm
+ bind pub - .df pub:df
#
# Initializes bind and creates procedures for every tc2 commands
#
proc tc2:addcommand {command} {
- set proc_tc2_command_dcc {
- tc2 dcc $idx $handle %COMMAND% $arg
- return 1
- }
- set proc_tc2_command_pub {
- tc2 pub "$chan $nick" $handle %COMMAND% $text
- return 1
- }
- bind dcc W $command dcc:$command
- bind pub W ".$command" pub:$command
- proc dcc:$command {handle idx arg} [string map "%COMMAND% $command" $proc_tc2_command_dcc]
- proc pub:$command {nick uhost handle chan text} [string map "%COMMAND% $command" $proc_tc2_command_pub]
+ set proc_tc2_command_dcc {
+ tc2 dcc $idx $handle %COMMAND% $arg
+ return 1
+ }
+ set proc_tc2_command_pub {
+ tc2 pub "$chan $nick" $handle %COMMAND% $text
+ return 1
+ }
+ bind dcc W $command dcc:$command
+ bind pub W ".$command" pub:$command
+ proc dcc:$command {handle idx arg} [string map "%COMMAND% $command" $proc_tc2_command_dcc]
+ proc pub:$command {nick uhost handle chan text} [string map "%COMMAND% $command" $proc_tc2_command_pub]
}
proc tc2:initialize {} {
- foreach command [registry get tc2.commands] {
- tc2:addcommand $command
- }
+ foreach command [registry get tc2.commands] {
+ tc2:addcommand $command
+ }
}
tc2:initialize
@@ -66,33 +66,33 @@
#
proc bot:tc2 {sourcebot command text} {
- if [catch {
- set success [dict get $text success]
- set reply [dict get $text reply]
- set bind [dict get $text bind]
- set who [dict get $text who]
- tc2:reply $bind $who $reply
- }] {
- putdebug $text
- }
+ if [catch {
+ set success [dict get $text success]
+ set reply [dict get $text reply]
+ set bind [dict get $text bind]
+ set who [dict get $text who]
+ tc2:reply $bind $who $reply
+ }] {
+ putdebug $text
+ }
}
proc tc2 {bind who handle command arg} {
- set bot [registry get tc2.bot]
- if ![islinked $bot] {
- tc2:reply $bind $who "$bot isn't linked"
- return
- }
- putbot $bot "tc2 [dict create requester $handle command $command arg $arg bind $bind who $who]"
+ set bot [registry get tc2.bot]
+ if ![islinked $bot] {
+ tc2:reply $bind $who "$bot isn't linked"
+ return
+ }
+ putbot $bot "tc2 [dict create requester $handle command $command arg $arg bind $bind who $who]"
}
proc tc2:reply {bind who message} {
- if {$bind == "dcc"} {
- putdcc $who $message
- } elseif {$bind == "pub"} {
- foreach "chan nick" $who {}
- putserv "PRIVMSG $chan :$nick, $message"
- } {
- error "Unknown bind in tc2:reply: $bind (expected: dcc or pub)"
- }
+ if {$bind == "dcc"} {
+ putdcc $who $message
+ } elseif {$bind == "pub"} {
+ foreach "chan nick" $who {}
+ putserv "PRIVMSG $chan :$nick, $message"
+ } {
+ error "Unknown bind in tc2:reply: $bind (expected: dcc or pub)"
+ }
}
diff --git a/Daeghrefn/Time.tcl b/Daeghrefn/Time.tcl
--- a/Daeghrefn/Time.tcl
+++ b/Daeghrefn/Time.tcl
@@ -13,7 +13,7 @@
#Every 5 minutes
proc cron:often {minute hour day month weekday} {
- sqlrehash
+ sqlrehash
}
#Every hour
diff --git a/Daeghrefn/Tools.tcl b/Daeghrefn/Tools.tcl
--- a/Daeghrefn/Tools.tcl
+++ b/Daeghrefn/Tools.tcl
@@ -11,17 +11,17 @@
#
proc genpass {main domain} {
- string range [md5 "$main:$domain"] 0 7
+ string range [md5 "$main:$domain"] 0 7
}
proc dcc:genpass {handle idx arg} {
- if {[llength $arg] != 2} {
- putdcc $idx "Usage: .genpass <main password> <domain name>"
- } {
- putcmdlog "#$handle# genpass ..."
- putdcc $idx [genpass [lindex $arg 0] [lindex $arg 1]]
- }
- return 0
+ if {[llength $arg] != 2} {
+ putdcc $idx "Usage: .genpass <main password> <domain name>"
+ } {
+ putcmdlog "#$handle# genpass ..."
+ putdcc $idx [genpass [lindex $arg 0] [lindex $arg 1]]
+ }
+ return 0
}
#
@@ -30,9 +30,9 @@
#
proc dcc:strlen {handle idx arg} {
- putdcc $idx [string length $arg]
- putcmdlog "#$handle# strlen ..."
- return 0
+ putdcc $idx [string length $arg]
+ putcmdlog "#$handle# strlen ..."
+ return 0
}
#
@@ -41,13 +41,13 @@
#
proc dcc:unixtime {handle idx arg} {
- if {$arg == ""} {
- putdcc $idx [unixtime]
- } elseif [isnumber $arg] {
- putdcc $idx [clock format $arg -format "%Y-%m-%d %H:%M:%S"]
- } {
- if [catch {putdcc $idx [clock scan $arg]} err] {
- putdcc $idx $err
- }
- }
+ if {$arg == ""} {
+ putdcc $idx [unixtime]
+ } elseif [isnumber $arg] {
+ putdcc $idx [clock format $arg -format "%Y-%m-%d %H:%M:%S"]
+ } {
+ if [catch {putdcc $idx [clock scan $arg]} err] {
+ putdcc $idx $err
+ }
+ }
}
diff --git a/Daeghrefn/Wikimedia.tcl b/Daeghrefn/Wikimedia.tcl
--- a/Daeghrefn/Wikimedia.tcl
+++ b/Daeghrefn/Wikimedia.tcl
@@ -1,5 +1,5 @@
-bind pub - .config pub:config
-bind dcc - config dcc:config
+bind pub - .config pub:config
+bind dcc - config dcc:config
bind pub - .+surname pub:surname
bind dcc D +surname dcc:surname
bind pub - .+nom pub:surname
@@ -18,142 +18,142 @@
# Determines if the Wikidata channel is Wikidata specific
# Wikidata channels allow commands for everyone, not only for D users.
proc isWikidataChannel {chan} {
- expr [lsearch [registry get wikidata.channels] $chan] != -1
+ expr [lsearch [registry get wikidata.channels] $chan] != -1
}
# Determines if the specified handle on the specified channel
# is allowed to run a Wikidata comamnd.
proc areWikidataCommandsAllowed {chan handle} {
- if {[matchattr $handle D]} {
- return 1
- }
+ if {[matchattr $handle D]} {
+ return 1
+ }
- isWikidataChannel $chan
+ isWikidataChannel $chan
}
# Handles .+surname command
proc pub:surname {nick uhost handle chan arg} {
- if {![areWikidataCommandsAllowed $chan $handle]} {
- return 0
- }
-
- if {[isAcceptableItemTitle $arg]} {
- create_surname $arg "serv $chan"
- return 1
- } {
- putserv "PRIVMSG $chan :$nick : ne sont gérés comme que les caractères alphanumériques, le tiret, l'apostrophe droite, de même que tout ce qui n'est pas ASCII standard."
- }
- return 0
+ if {![areWikidataCommandsAllowed $chan $handle]} {
+ return 0
+ }
+
+ if {[isAcceptableItemTitle $arg]} {
+ create_surname $arg "serv $chan"
+ return 1
+ } {
+ putserv "PRIVMSG $chan :$nick : ne sont gérés comme que les caractères alphanumériques, le tiret, l'apostrophe droite, de même que tout ce qui n'est pas ASCII standard."
+ }
+ return 0
}
# Handles .+surname command
proc dcc:surname {handle idx arg} {
- if {[isAcceptableItemTitle $arg]} {
- create_surname $arg "dcc $idx"
- return 1
- } {
- putdcc $idx "crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
- }
- return 0
+ if {[isAcceptableItemTitle $arg]} {
+ create_surname $arg "dcc $idx"
+ return 1
+ } {
+ putdcc $idx "crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
+ }
+ return 0
}
# Creates a surname
# @param $title the item title
# @param $state the state to pass to the create command callback (here with a mode and a target to print result)
proc create_surname {title state} {
- run_command "[get_external_script create_surname] [posix_escape $title]" print_command_callback print_python_error_callback $state
+ run_command "[get_external_script create_surname] [posix_escape $title]" print_command_callback print_python_error_callback $state
}
# Handles .+givenname command
proc pub:givenname {nick uhost handle chan arg} {
- if {![areWikidataCommandsAllowed $chan $handle]} {
- return 0
- }
-
- set params [split $arg]
- if {[llength $params] == 0} {
- putdcc $idx "Quel prénom ajouter ? e.g. .+prenom Aude F"
- return 0
- } elseif {[llength $params] > 1} {
- set title [lindex $params 0]
- set genre [string toupper [lindex $params 1]]
- switch -- $genre {
- M {}
- F {}
- D {}
- U {}
- E {set genre U}
- default {
- puthelp "PRIVMSG $chan :Attendu : F (féminin), M (masculin), U (épicène) — e.g. .+prenom Aude F"
- return 0
- }
- }
- } {
- set title $arg
- set genre D
- }
- if {[isAcceptableItemTitle $title]} {
- create_givenname $title $genre "serv $chan"
- return 1
- } {
- puthelp "PRIVMSG $chan :$nick : crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
- }
+ if {![areWikidataCommandsAllowed $chan $handle]} {
+ return 0
+ }
+
+ set params [split $arg]
+ if {[llength $params] == 0} {
+ putdcc $idx "Quel prénom ajouter ? e.g. .+prenom Aude F"
+ return 0
+ } elseif {[llength $params] > 1} {
+ set title [lindex $params 0]
+ set genre [string toupper [lindex $params 1]]
+ switch -- $genre {
+ M {}
+ F {}
+ D {}
+ U {}
+ E {set genre U}
+ default {
+ puthelp "PRIVMSG $chan :Attendu : F (féminin), M (masculin), U (épicène) — e.g. .+prenom Aude F"
+ return 0
+ }
+ }
+ } {
+ set title $arg
+ set genre D
+ }
+ if {[isAcceptableItemTitle $title]} {
+ create_givenname $title $genre "serv $chan"
+ return 1
+ } {
+ puthelp "PRIVMSG $chan :$nick : crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
+ }
}
# Handles .+givenname command
proc dcc:givenname {handle idx arg} {
- set params [split $arg]
- if {[llength $params] == 0} {
- putdcc $idx "Quel prénom ajouter ? e.g. .+prenom Aude F"
- return 0
- } elseif {[llength $params] > 1} {
- set title [lindex $params 0]
- set genre [string toupper [lindex $params 1]]
- switch -- $genre {
- M {}
- F {}
- D {}
- U {}
- E {set genre U}
- default {
- putdcc $idx "Attendu : F (féminin), M (masculin), U (épicène) — e.g. .+prenom Aude F"
- return 0
- }
- }
- } {
- set title $arg
- set genre D
- }
- if {[isAcceptableItemTitle $title]} {
- create_givenname $title $genre "dcc $idx"
- return 1
- } {
- putdcc $idx "crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
- }
+ set params [split $arg]
+ if {[llength $params] == 0} {
+ putdcc $idx "Quel prénom ajouter ? e.g. .+prenom Aude F"
+ return 0
+ } elseif {[llength $params] > 1} {
+ set title [lindex $params 0]
+ set genre [string toupper [lindex $params 1]]
+ switch -- $genre {
+ M {}
+ F {}
+ D {}
+ U {}
+ E {set genre U}
+ default {
+ putdcc $idx "Attendu : F (féminin), M (masculin), U (épicène) — e.g. .+prenom Aude F"
+ return 0
+ }
+ }
+ } {
+ set title $arg
+ set genre D
+ }
+ if {[isAcceptableItemTitle $title]} {
+ create_givenname $title $genre "dcc $idx"
+ return 1
+ } {
+ putdcc $idx "crée cet item manuellement, je ne suis pas conçu pour gérer ces caractères dans le titre."
+ }
}
# Creates a given name
# @param $title the item title
# @param $state the state to pass to the create command callback (here with a mode and a target to print result)
proc create_givenname {title genre state} {
- run_command "[get_external_script create_given_name] [posix_escape $title] $genre" print_command_callback print_python_error_callback $state
+ run_command "[get_external_script create_given_name] [posix_escape $title] $genre" print_command_callback print_python_error_callback $state
}
# Determines if the specified title is suitable to pass as shell argument
# @param $title The title to check
# @return 0 is the title is acceptable; otherwise, false.
proc isAcceptableItemTitle {title} {
- set re {[A-Za-z \-']}
- foreach char [split $title {}] {
- set value [scan $char %c]
- if {$value < 128} {
- #ASCII
- if {![regexp $re $char]} { return 0 }
- }
- #UTF-8 ok
- }
- return 1
+ set re {[A-Za-z \-']}
+ foreach char [split $title {}] {
+ set value [scan $char %c]
+ if {$value < 128} {
+ #ASCII
+ if {![regexp $re $char]} { return 0 }
+ }
+ #UTF-8 ok
+ }
+ return 1
}
@@ -163,85 +163,85 @@
# Handles .config pub command
proc pub:config {nick uhost handle chan arg} {
- if {[llength $arg] < 2} {
- puthelp "NOTICE $nick :Usage: .config <setting> <project>"
- return 0
- }
- putserv "PRIVMSG $chan :[wikimedia::get_config_variable [lindex $arg 0] [lindex $arg 1] [lrange $arg 2 end]]"
- return 1
+ if {[llength $arg] < 2} {
+ puthelp "NOTICE $nick :Usage: .config <setting> <project>"
+ return 0
+ }
+ putserv "PRIVMSG $chan :[wikimedia::get_config_variable [lindex $arg 0] [lindex $arg 1] [lrange $arg 2 end]]"
+ return 1
}
# Handles .config dcc command
proc dcc:config {handle idx arg} {
- if {[llength $arg] < 2} {
- putdcc $idx "Usage: .config <setting> <project>"
- return 0
- }
- putdcc $idx [wikimedia::get_config_variable [lindex $arg 0] [lindex $arg 1] [lrange $arg 2 end]]
- return 1
+ if {[llength $arg] < 2} {
+ putdcc $idx "Usage: .config <setting> <project>"
+ return 0
+ }
+ putdcc $idx [wikimedia::get_config_variable [lindex $arg 0] [lindex $arg 1] [lrange $arg 2 end]]
+ return 1
}
namespace eval ::wikimedia {
- # Script to get a configuration variable
- set get_config_script {
+ # Script to get a configuration variable
+ set get_config_script {
<?php
- error_reporting(0);
- require_once('%%dir%%/wmf-config/InitialiseSettings.php');
- $value = $wgConf->settings%%key%%;
- if (is_array($value)) {
- $values = array();
- if (array_keys($value) !== range(0, count($value) - 1)) {
- //Associative arary
- foreach ($value as $k => $v) {
- $values[] = "$k => $v";
- }
- echo implode(' / ', $values);
- } else {
- //Numeric array
- echo implode(', ', $value);
- }
- } else if (is_bool($value)) {
- echo $value ? 'true' : 'false';
- } else {
- echo $value;
- }
+ error_reporting(0);
+ require_once('%%dir%%/wmf-config/InitialiseSettings.php');
+ $value = $wgConf->settings%%key%%;
+ if (is_array($value)) {
+ $values = array();
+ if (array_keys($value) !== range(0, count($value) - 1)) {
+ //Associative arary
+ foreach ($value as $k => $v) {
+ $values[] = "$k => $v";
+ }
+ echo implode(' / ', $values);
+ } else {
+ //Numeric array
+ echo implode(', ', $value);
+ }
+ } else if (is_bool($value)) {
+ echo $value ? 'true' : 'false';
+ } else {
+ echo $value;
+ }
?>
- }
-
- # Gets a configuration variable, defined in $wgConf aray
- #
- # @param $setting the config variable's name
- # @param $project the project
- # @param $args If the config variable is an array, the keys to get (facultative, specify how many you want)
- # @return the config value
- proc get_config_variable {setting project args} {
- if {[string index $setting 0] == "\$"} {
- set setting [string rang $setting 1 end]
- }
- if {![regexp "^\[a-z]\[A-Za-z0-9]*$" $setting]} {
- return "Not a valid setting: $setting"
- }
-
- if {![regexp "^\[a-z]\[a-z0-9_]*$" $project]} {
- return "Not a valid project: $project"
- }
- set key "\['$setting']\['$project']"
- foreach arg $args {
- if {$arg == ""} break
- if {![regexp "^\[A-Za-z0-9]*$" $arg]} {
- return "Not a valid setting: $arg"
- }
- append key "\['$arg']"
- }
- set code [string map [list %%key%% $key %%dir%% [registry get repositories.operations.mediawiki-config]] $wikimedia::get_config_script]
- exec_php $code
- }
-
- # Executes inline PHP code
- #
- # @param code The PHP code to execute
- # @return the script stdout
- proc exec_php {code} {
- string trim [exec -- echo $code | php]
- }
+ }
+
+ # Gets a configuration variable, defined in $wgConf aray
+ #
+ # @param $setting the config variable's name
+ # @param $project the project
+ # @param $args If the config variable is an array, the keys to get (facultative, specify how many you want)
+ # @return the config value
+ proc get_config_variable {setting project args} {
+ if {[string index $setting 0] == "\$"} {
+ set setting [string rang $setting 1 end]
+ }
+ if {![regexp "^\[a-z]\[A-Za-z0-9]*$" $setting]} {
+ return "Not a valid setting: $setting"
+ }
+
+ if {![regexp "^\[a-z]\[a-z0-9_]*$" $project]} {
+ return "Not a valid project: $project"
+ }
+ set key "\['$setting']\['$project']"
+ foreach arg $args {
+ if {$arg == ""} break
+ if {![regexp "^\[A-Za-z0-9]*$" $arg]} {
+ return "Not a valid setting: $arg"
+ }
+ append key "\['$arg']"
+ }
+ set code [string map [list %%key%% $key %%dir%% [registry get repositories.operations.mediawiki-config]] $wikimedia::get_config_script]
+ exec_php $code
+ }
+
+ # Executes inline PHP code
+ #
+ # @param code The PHP code to execute
+ # @return the script stdout
+ proc exec_php {code} {
+ string trim [exec -- echo $code | php]
+ }
}
diff --git a/Daeghrefn/Wolfplex.tcl b/Daeghrefn/Wolfplex.tcl
--- a/Daeghrefn/Wolfplex.tcl
+++ b/Daeghrefn/Wolfplex.tcl
@@ -1,27 +1,27 @@
-bind pub - !open pub:open
-bind pub - !ouvert pub:open
-bind pub - !close pub:close
-bind pub - !closed pub:close
-bind pub - !ferme pub:close
-bind pub - !fermé pub:close
+bind pub - !open pub:open
+bind pub - !ouvert pub:open
+bind pub - !close pub:close
+bind pub - !closed pub:close
+bind pub - !ferme pub:close
+bind pub - !fermé pub:close
proc pub:open {nick uhost handle chan text} {
- setisopen yes
+ setisopen yes
}
proc pub:close {nick uhost handle chan text} {
- setisopen no
+ setisopen no
}
proc setisopen {status} {
- set query [::http::formatQuery oldid 0 wpTextbox1 $status wpSave Publier]
- set url "http://www.wolfplex.org/w/index.php?title=Mod%C3%A8le:IsOpen/status&action=edit"
- set tok [::http::geturl $url -query $query]
- set result [::http::data $tok]
- ::http::cleanup $tok
+ set query [::http::formatQuery oldid 0 wpTextbox1 $status wpSave Publier]
+ set url "http://www.wolfplex.org/w/index.php?title=Mod%C3%A8le:IsOpen/status&action=edit"
+ set tok [::http::geturl $url -query $query]
+ set result [::http::data $tok]
+ ::http::cleanup $tok
- set fd [open debug.log w]
- puts $fd $result
- flush $fd
- close $fd
+ set fd [open debug.log w]
+ puts $fd $result
+ flush $fd
+ close $fd
}
diff --git a/ForUsers/DANYAL/LogJoins.tcl b/ForUsers/DANYAL/LogJoins.tcl
--- a/ForUsers/DANYAL/LogJoins.tcl
+++ b/ForUsers/DANYAL/LogJoins.tcl
@@ -15,13 +15,13 @@
#Handles server notices
proc raw:logjoin {from keyword text} {
- global LogJoins
- if {$from == $LogJoins(server) && $keyword == "NOTICE"} {
- set pos [string first "Client connecting" $text]
- if {$pos > -1} {
- log_entry $LogJoins(file) [string range $text $pos end]
- }
- }
+ global LogJoins
+ if {$from == $LogJoins(server) && $keyword == "NOTICE"} {
+ set pos [string first "Client connecting" $text]
+ if {$pos > -1} {
+ log_entry $LogJoins(file) [string range $text $pos end]
+ }
+ }
}
#
@@ -30,12 +30,12 @@
#Returns a log message, prepended by current time
proc log_message {message} {
- return "[clock format [unixtime] -format "%x %X"] $message"
+ return "[clock format [unixtime] -format "%x %X"] $message"
}
#Logs a message in the specified file
proc log_entry {file message} {
- set fd [open $file a]
- puts $fd [log_message $message]
- close $fd
+ set fd [open $file a]
+ puts $fd [log_message $message]
+ close $fd
}
diff --git a/ForUsers/DANYAL/SMS.tcl b/ForUsers/DANYAL/SMS.tcl
--- a/ForUsers/DANYAL/SMS.tcl
+++ b/ForUsers/DANYAL/SMS.tcl
@@ -15,69 +15,69 @@
#Sends a SMS to $to with $message as text and $from as source
#Returns "" if SMS were sent, the error message otherwise
proc sendsms {from to message} {
- #Gets params
- global sms
- if [info exists sms($to)] {
- foreach "url pass" $sms($to) {}
- } {
- return "$to doesn't have enabled SMS feature."
- }
+ #Gets params
+ global sms
+ if [info exists sms($to)] {
+ foreach "url pass" $sms($to) {}
+ } {
+ return "$to doesn't have enabled SMS feature."
+ }
- #Check length
- set len [string length $from$message]
- if {$len > 113} {
- return "Message too long, drop [expr $len-113] chars]."
- }
+ #Check length
+ set len [string length $from$message]
+ if {$len > 113} {
+ return "Message too long, drop [expr $len-113] chars]."
+ }
- #Posts form
- package require http
- set query [::http::formatQuery m $from p $message v $pass envoi Envoyer]
- set tok [::http::geturl $url -query $query]
- set result [::http::data $tok]
- ::http::cleanup $tok
+ #Posts form
+ package require http
+ set query [::http::formatQuery m $from p $message v $pass envoi Envoyer]
+ set tok [::http::geturl $url -query $query]
+ set result [::http::data $tok]
+ ::http::cleanup $tok
- #Parses reply
- if {[string first "Impossible d'envoyer" $result] != -1 || [string first "There is an error" $result] != -1} {
- return "Can't send a SMS, according the web form."
- } elseif {[string first "Tu as subtilement" $result] != -1 || [string first "forget to write" $result] != -1} {
- return "Incorrect pass: $pass, check on $url if the antispam question haven't been modified."
- } elseif {[string first "envoi \[ Ok \]" $result] != -1 || [string first "our message have been sent with success" $result] != -1} {
- return ""
- } {
- return "I can't determine from the SMS web form reply if the message have been sent or not."
- }
+ #Parses reply
+ if {[string first "Impossible d'envoyer" $result] != -1 || [string first "There is an error" $result] != -1} {
+ return "Can't send a SMS, according the web form."
+ } elseif {[string first "Tu as subtilement" $result] != -1 || [string first "forget to write" $result] != -1} {
+ return "Incorrect pass: $pass, check on $url if the antispam question haven't been modified."
+ } elseif {[string first "envoi \[ Ok \]" $result] != -1 || [string first "our message have been sent with success" $result] != -1} {
+ return ""
+ } {
+ return "I can't determine from the SMS web form reply if the message have been sent or not."
+ }
}
proc dcc:sms {handle idx arg} {
- #Sends a SMS
- set to [lindex $arg 0]
- #TODO: use a proc to remove the first word instead and keep $arg as string
- set message [lrange $arg 1 end]
- if {[set result [sendsms $handle $to $message]] == ""} {
- putdcc $idx "SMS sent."
- putcmdlog "#$handle# sms ..."
- } {
- putdcc $idx $result
- }
- return 0
+ #Sends a SMS
+ set to [lindex $arg 0]
+ #TODO: use a proc to remove the first word instead and keep $arg as string
+ set message [lrange $arg 1 end]
+ if {[set result [sendsms $handle $to $message]] == ""} {
+ putdcc $idx "SMS sent."
+ putcmdlog "#$handle# sms ..."
+ } {
+ putdcc $idx $result
+ }
+ return 0
}
#!sms
proc pub:sms {nick uhost handle chan text} {
- #Sends a SMS
- if {$handle == "" || $handle == "*"} {
- set from $nick
- } {
- set from $handle
- }
- set to [lindex $text 0]
- #TODO: use a proc to remove the first word instead and keep $arg as string
- set message [lrange $text 1 end]
- if {[set result [sendsms $from $to $message]] == ""} {
- putquick "PRIVMSG $chan :$nick, SMS sent."
- putcmdlog "!$nick! sms ..."
- } {
- putquick "PRIVMSG $chan :$nick, $result."
- }
- return 0
+ #Sends a SMS
+ if {$handle == "" || $handle == "*"} {
+ set from $nick
+ } {
+ set from $handle
+ }
+ set to [lindex $text 0]
+ #TODO: use a proc to remove the first word instead and keep $arg as string
+ set message [lrange $text 1 end]
+ if {[set result [sendsms $from $to $message]] == ""} {
+ putquick "PRIVMSG $chan :$nick, SMS sent."
+ putcmdlog "!$nick! sms ..."
+ } {
+ putquick "PRIVMSG $chan :$nick, $result."
+ }
+ return 0
}
diff --git a/ForUsers/DANYAL/chanlist2html.tcl b/ForUsers/DANYAL/chanlist2html.tcl
--- a/ForUsers/DANYAL/chanlist2html.tcl
+++ b/ForUsers/DANYAL/chanlist2html.tcl
@@ -4,7 +4,7 @@
#
# Configuration
-# Paths are relative to eggdrop
+# Paths are relative to eggdrop
#
#The channel to save
@@ -26,39 +26,39 @@
#Generates a <ul><li>...<li><li>...<li></ul> HTML code from a list
proc list2ul {list {lineprefix ""}} {
- set html "${lineprefix}<ul>\n"
- foreach item $list {
- append html "${lineprefix}\t<li>${item}</li>\n"
- }
- append html "${lineprefix}</ul>"
+ set html "${lineprefix}<ul>\n"
+ foreach item $list {
+ append html "${lineprefix}\t<li>${item}</li>\n"
+ }
+ append html "${lineprefix}</ul>"
}
#Writes $target with the $channel users list from $template
proc chanlist2html_write {channel template target} {
- if [file exists $template] {
- set fd [open $template r]
- while {![eof $fd]} {
- append buffer [gets $fd]
- }
- close $fd
- } {
- set buffer "%%chanlist%%"
- }
- set fd [open $target w]
- set chanlist [list2ul [chanlist $channel]]
- puts $fd [string map [list %%chanlist%% $chanlist] $buffer]
- flush $fd
- close $fd
+ if [file exists $template] {
+ set fd [open $template r]
+ while {![eof $fd]} {
+ append buffer [gets $fd]
+ }
+ close $fd
+ } {
+ set buffer "%%chanlist%%"
+ }
+ set fd [open $target w]
+ set chanlist [list2ul [chanlist $channel]]
+ puts $fd [string map [list %%chanlist%% $chanlist] $buffer]
+ flush $fd
+ close $fd
}
#
# Timer
-#
+#
proc chanlist2html {} {
- global chanlist2html
- chanlist2html_write $chanlist2html(channel) $chanlist2html(tmpl) $chanlist2html(file)
- timer $chanlist2html(time) chanlist2html
+ global chanlist2html
+ chanlist2html_write $chanlist2html(channel) $chanlist2html(tmpl) $chanlist2html(file)
+ timer $chanlist2html(time) chanlist2html
}
chanlist2html
diff --git a/ForUsers/TOMJERRX/Download.tcl b/ForUsers/TOMJERRX/Download.tcl
--- a/ForUsers/TOMJERRX/Download.tcl
+++ b/ForUsers/TOMJERRX/Download.tcl
@@ -18,25 +18,25 @@
# Handles download public channel commands
proc pub:download {nick uhost handle chan text} {
- set url [string trim $text]
+ set url [string trim $text]
- if {$url == ""} {
- puthelp "PRIVMSG $chan :$nick, what URL do you want to download?"
- return 0
- }
+ if {$url == ""} {
+ puthelp "PRIVMSG $chan :$nick, what URL do you want to download?"
+ return 0
+ }
- if {![isvalidurl $url]} {
- puthelp "PRIVMSG $chan :$nick, $url isn't a valid URL"
- return 0
- }
+ if {![isvalidurl $url]} {
+ puthelp "PRIVMSG $chan :$nick, $url isn't a valid URL"
+ return 0
+ }
- if {![download $url]} {
- puthelp "PRIVMSG $chan :$nick, I can't download that."
- return 0
- }
+ if {![download $url]} {
+ puthelp "PRIVMSG $chan :$nick, I can't download that."
+ return 0
+ }
- puthelp "PRIVMSG $chan :$nick, downloaded."
- return 1
+ puthelp "PRIVMSG $chan :$nick, downloaded."
+ return 1
}
#
@@ -44,56 +44,56 @@
#
proc isvalidurl {url} {
- return 1
+ return 1
}
proc getfilename {url fd} {
- # Files to download should have a Content-Disposition header.
- set headers [::http::meta $fd]
- if {[dict exists $headers Content-Disposition]} {
- set re "filename=\"(.*)\""
- if {[regexp $re [dict get $headers Content-Disposition] match filename]} {
- return $filename
- }
- }
-
- # As a fallback, we use URL tail
- file tail $url
+ # Files to download should have a Content-Disposition header.
+ set headers [::http::meta $fd]
+ if {[dict exists $headers Content-Disposition]} {
+ set re "filename=\"(.*)\""
+ if {[regexp $re [dict get $headers Content-Disposition] match filename]} {
+ return $filename
+ }
+ }
+
+ # As a fallback, we use URL tail
+ file tail $url
}
proc getlocalfilename {filename} {
- global Download
- set base [file join $Download(path) $filename]
-
- # Not existing filename, we can use it
- if {![file exists $base]} {
- return $base
- }
-
- # If it already exists, we append .1 .2 .3
- set i 1
- while {[file exists $base.$i]} {
- incr i
- }
- return $base.$i
+ global Download
+ set base [file join $Download(path) $filename]
+
+ # Not existing filename, we can use it
+ if {![file exists $base]} {
+ return $base
+ }
+
+ # If it already exists, we append .1 .2 .3
+ set i 1
+ while {[file exists $base.$i]} {
+ incr i
+ }
+ return $base.$i
}
proc download {url} {
- # Code from http://wiki.tcl.tk/12871 by Venkat Iyer and Martin Lemburg.
- set fd_remote [::http::geturl $url -binary 1]
- set filename [getfilename $url $fd_remote]
- set localpath [getlocalfilename $filename]
-
- if {[::http::ncode $fd_remote] != 200} {
- # TODO: follow redirections or invoke curl instead of doing it in native TCL
- return 0
- }
-
- set fd_local [open $localpath w]
- fconfigure $fd_local -translation binary
- puts -nonewline $fd_local [::http::data $fd_remote]
- close $fd_local
-
- ::http::cleanup $fd_remote
- return 1
+ # Code from http://wiki.tcl.tk/12871 by Venkat Iyer and Martin Lemburg.
+ set fd_remote [::http::geturl $url -binary 1]
+ set filename [getfilename $url $fd_remote]
+ set localpath [getlocalfilename $filename]
+
+ if {[::http::ncode $fd_remote] != 200} {
+ # TODO: follow redirections or invoke curl instead of doing it in native TCL
+ return 0
+ }
+
+ set fd_local [open $localpath w]
+ fconfigure $fd_local -translation binary
+ puts -nonewline $fd_local [::http::data $fd_remote]
+ close $fd_local
+
+ ::http::cleanup $fd_remote
+ return 1
}
diff --git a/Maintenance/MigrateBlog.tcl b/Maintenance/MigrateBlog.tcl
--- a/Maintenance/MigrateBlog.tcl
+++ b/Maintenance/MigrateBlog.tcl
@@ -6,89 +6,89 @@
#
namespace eval ::blog:: {
- set lang(fr) 31
- set lang(en) 32
+ set lang(fr) 31
+ set lang(en) 32
- #sqladd -> sqladd7
- proc sqladd7 [info args sqladd] [string map {"sql \$sql" "sql7 \$sql"} [info body sqladd]]
+ #sqladd -> sqladd7
+ proc sqladd7 [info args sqladd] [string map {"sql \$sql" "sql7 \$sql"} [info body sqladd]]
- proc launch_migration {} {
- #Migration counters
- set counter_fail 0
- set counter_pass 0
+ proc launch_migration {} {
+ #Migration counters
+ set counter_fail 0
+ set counter_pass 0
- foreach row [sql7 "SELECT post_titre_url, post_lang FROM Blog.dc_post"] {
- foreach "title lang" $row {}
- set post_id [sql7 "SELECT ID FROM Dereckson_Blog.wp_posts WHERE post_name = '[sqlescape $title]'"]
- if {$post_id == ""} {
- putdebug "Can't find post: $title"
- incr counter_fail
- continue
- }
- if {$lang == "efr"} {
- putdebug "Bilingual post: $title - http://www.dereckson.be/blog/wp-admin/post.php?post=$post_id&action=edit"
- incr counter_fail
- } {
- #putdebug "$post_id -> _translations: [get_metadata $post_id $lang]"
- sqladd7 Dereckson_Blog.wp_postmeta "post_id meta_key meta_value" "$post_id _translations [get_translation_metadata $post_id $lang]"
- incr counter_pass
- }
- }
- putdebug "$counter_fail post[s $counter_fail] to manually take care of, $counter_pass post[s $counter_pass] updated."
- }
+ foreach row [sql7 "SELECT post_titre_url, post_lang FROM Blog.dc_post"] {
+ foreach "title lang" $row {}
+ set post_id [sql7 "SELECT ID FROM Dereckson_Blog.wp_posts WHERE post_name = '[sqlescape $title]'"]
+ if {$post_id == ""} {
+ putdebug "Can't find post: $title"
+ incr counter_fail
+ continue
+ }
+ if {$lang == "efr"} {
+ putdebug "Bilingual post: $title - http://www.dereckson.be/blog/wp-admin/post.php?post=$post_id&action=edit"
+ incr counter_fail
+ } {
+ #putdebug "$post_id -> _translations: [get_metadata $post_id $lang]"
+ sqladd7 Dereckson_Blog.wp_postmeta "post_id meta_key meta_value" "$post_id _translations [get_translation_metadata $post_id $lang]"
+ incr counter_pass
+ }
+ }
+ putdebug "$counter_fail post[s $counter_fail] to manually take care of, $counter_pass post[s $counter_pass] updated."
+ }
- proc get_translation_metadata {post_id lang} {
- # We need a PHP serialized array [ '$lang' => $post_id, '$altlang' => 0 ]
- if {$lang == "en"} { set altlang fr } { set altlang en }
- return "a:2:{s:2:\"$lang\";i:$post_id;s:2:\"$altlang\";i:0;}"
- }
+ proc get_translation_metadata {post_id lang} {
+ # We need a PHP serialized array [ '$lang' => $post_id, '$altlang' => 0 ]
+ if {$lang == "en"} { set altlang fr } { set altlang en }
+ return "a:2:{s:2:\"$lang\";i:$post_id;s:2:\"$altlang\";i:0;}"
+ }
- ## Fixes translation, when every post is in English, setting the correct one in French
- proc fix_translation {} {
- # Finds posts in French (from DotCler post_lang info)
- set posts {}
- foreach row [sql7 "SELECT post_titre_url, post_lang FROM Blog.dc_post"] {
- foreach "title lang" $row {}
- set post_id [sql7 "SELECT ID FROM Dereckson_Blog.wp_posts WHERE post_name = '[sqlescape $title]'"]
- if {$post_id == ""} {
- putdebug "Can't find post: $title"
- } elseif {$lang == "fr"} {
- lappend posts $post_id
- }
- }
+ ## Fixes translation, when every post is in English, setting the correct one in French
+ proc fix_translation {} {
+ # Finds posts in French (from DotCler post_lang info)
+ set posts {}
+ foreach row [sql7 "SELECT post_titre_url, post_lang FROM Blog.dc_post"] {
+ foreach "title lang" $row {}
+ set post_id [sql7 "SELECT ID FROM Dereckson_Blog.wp_posts WHERE post_name = '[sqlescape $title]'"]
+ if {$post_id == ""} {
+ putdebug "Can't find post: $title"
+ } elseif {$lang == "fr"} {
+ lappend posts $post_id
+ }
+ }
- # Sets metadata French in Wordpress
- batch_en2fr $posts
- }
+ # Sets metadata French in Wordpress
+ batch_en2fr $posts
+ }
- proc batch_en2fr {posts_id} {
- set postsUpdated 0
- foreach post_id $posts_id {
- incr postsUpdated [change_post_language $post_id $blog::lang(en) $blog::lang(fr)]
- }
- if {$postsUpdated > 0} {
- sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` - $postsUpdated WHERE term_taxonomy_id = $blog::lang(en)"
- sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` + $postsUpdated WHERE term_taxonomy_id = $blog::lang(fr)"
- }
- }
+ proc batch_en2fr {posts_id} {
+ set postsUpdated 0
+ foreach post_id $posts_id {
+ incr postsUpdated [change_post_language $post_id $blog::lang(en) $blog::lang(fr)]
+ }
+ if {$postsUpdated > 0} {
+ sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` - $postsUpdated WHERE term_taxonomy_id = $blog::lang(en)"
+ sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` + $postsUpdated WHERE term_taxonomy_id = $blog::lang(fr)"
+ }
+ }
- proc en2fr {post_id} {
- change_post_language $post_id $blog::lang(en) $blog::lang(fr)
- }
+ proc en2fr {post_id} {
+ change_post_language $post_id $blog::lang(en) $blog::lang(fr)
+ }
- proc change_post_language {post_id oldlang newlang {updateTaxonomy 1}} {
- set isNewLang [sql7 "SELECT count(*) FROM Dereckson_Blog.wp_term_relationships WHERE object_id = $post_id AND term_taxonomy_id IN ('$newlang')"]
- if $isNewLang {
- putdebug "Post $post_id is already in this language."
- return 0
- } {
- sql7 "DELETE FROM Dereckson_Blog.wp_term_relationships WHERE object_id = $post_id AND term_taxonomy_id = $oldlang"
- sql7 "INSERT INTO Dereckson_Blog.wp_term_relationships (object_id, term_taxonomy_id) VALUES ($post_id, $newlang)"
- if {$updateTaxonomy} {
- sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` - 1 WHERE term_taxonomy_id = $blog::lang(en)"
- sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` + 1 WHERE term_taxonomy_id = $blog::lang(fr)"
- }
- return 1
- }
- }
+ proc change_post_language {post_id oldlang newlang {updateTaxonomy 1}} {
+ set isNewLang [sql7 "SELECT count(*) FROM Dereckson_Blog.wp_term_relationships WHERE object_id = $post_id AND term_taxonomy_id IN ('$newlang')"]
+ if $isNewLang {
+ putdebug "Post $post_id is already in this language."
+ return 0
+ } {
+ sql7 "DELETE FROM Dereckson_Blog.wp_term_relationships WHERE object_id = $post_id AND term_taxonomy_id = $oldlang"
+ sql7 "INSERT INTO Dereckson_Blog.wp_term_relationships (object_id, term_taxonomy_id) VALUES ($post_id, $newlang)"
+ if {$updateTaxonomy} {
+ sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` - 1 WHERE term_taxonomy_id = $blog::lang(en)"
+ sql7 "UPDATE Dereckson_Blog.wp_term_taxonomy SET `count` = `count` + 1 WHERE term_taxonomy_id = $blog::lang(fr)"
+ }
+ return 1
+ }
+ }
}
diff --git a/TC2/Server.tcl b/TC2/Server.tcl
--- a/TC2/Server.tcl
+++ b/TC2/Server.tcl
@@ -1,21 +1,21 @@
# ===============================================
-# ========= ==== ====== ============
-# ============ ====== === === = ==========
-# ============ ===== ======== === =========
-# ============ ===== ============= ==========
-# ============ ===== ============ ===========
-# == DcK ===== ===== =========== ============
-# ============ ===== ========== =============
-# ============ ====== === === ==============
-# ============ ======= === ==========
+# ========= ==== ====== ============
+# ============ ====== === === = ==========
+# ============ ===== ======== === =========
+# ============ ===== ============= ==========
+# ============ ===== ============ ===========
+# == DcK ===== ===== =========== ============
+# ============ ===== ========== =============
+# ============ ====== === === ==============
+# ============ ======= === ==========
# ===============================================
# ===============================================
# == Tau Ceti Central == Server administration ==
# == This is a very dangerous product to use ==
# == Don't deploy it in stable environment ==
-# == Or say goodbye to the serv security ==
-# == This warning will not be repeated ==
-# == All your base are belong to us! ==
+# == Or say goodbye to the serv security ==
+# == This warning will not be repeated ==
+# == All your base are belong to us! ==
# ===============================================
# ===============================================
#
@@ -30,29 +30,29 @@
#Handles tc2 requests from linked bots
proc bot:tc2 {sourcebot command text} {
- #Sourcebot: Nasqueron
- #Command: tc2
- #Text: requester Dereckson command phpfpm arg status
- set requester [dict get $text requester]
- set cmd [dict get $text command]
- set arg [dict get $text arg]
- set bind [dict get $text bind]
- set who [dict get $text who]
-
- #Logs entry
- log tc2 "$requester@$sourcebot" "$cmd $arg"
-
- #Executes command
- if [proc_exists tc2:command:$cmd] {
- putcmdlog "(tc2) <$requester@$sourcebot> $cmd $arg"
- set reply [tc2:command:$cmd $requester $arg]
- } {
- set reply "0 {Unknown command: $cmd}"
- }
-
- #Reports result
- putbot $sourcebot "tc2 [dict create success [lindex $reply 0] reply [lindex $reply 1] bind $bind who $who]"
- return 1
+ #Sourcebot: Nasqueron
+ #Command: tc2
+ #Text: requester Dereckson command phpfpm arg status
+ set requester [dict get $text requester]
+ set cmd [dict get $text command]
+ set arg [dict get $text arg]
+ set bind [dict get $text bind]
+ set who [dict get $text who]
+
+ #Logs entry
+ log tc2 "$requester@$sourcebot" "$cmd $arg"
+
+ #Executes command
+ if [proc_exists tc2:command:$cmd] {
+ putcmdlog "(tc2) <$requester@$sourcebot> $cmd $arg"
+ set reply [tc2:command:$cmd $requester $arg]
+ } {
+ set reply "0 {Unknown command: $cmd}"
+ }
+
+ #Reports result
+ putbot $sourcebot "tc2 [dict create success [lindex $reply 0] reply [lindex $reply 1] bind $bind who $who]"
+ return 1
}
#
@@ -61,7 +61,7 @@
#Checks if $username begins by a letter and contains only letters, digits, -, _ or .
proc tc2:username_isvalid {username} {
- regexp {^[A-Za-z][A-Za-z0-9_\-\.]*$} $username
+ regexp {^[A-Za-z][A-Za-z0-9_\-\.]*$} $username
}
#Determines if $username exists on the system
@@ -69,157 +69,157 @@
proc tc2:username_exists {username} {
#TODO: Windows and other OSes (this line has been tested under FreeBSD)
if {[exec -- logins -oxl $username] == ""} {
- return 0
+ return 0
} {
- return 1
+ return 1
}
}
#Gets server hostname
proc tc2:hostname {} {
- exec hostname -s
+ exec hostname -s
}
#Determines if $username is root
proc tc2:isroot {username} {
- #Validates input data
- set username [string tolower $username]
- if ![tc2:username_isvalid $username] {
- return 0
- }
-
- #Check 1 - User has local accreditation
- if ![sql "SELECT count(*) FROM tc2_roots WHERE account_username = '$username' AND server_name = '[sqlescape [tc2:hostname]]'"] {
- return 0
- }
-
- #Check 2 - User is in the group wheel on the server
- if {[lsearch [exec -- id -Gn $username] wheel] == "-1"} {
- return 0
- } {
- return 1
- }
+ #Validates input data
+ set username [string tolower $username]
+ if ![tc2:username_isvalid $username] {
+ return 0
+ }
+
+ #Check 1 - User has local accreditation
+ if ![sql "SELECT count(*) FROM tc2_roots WHERE account_username = '$username' AND server_name = '[sqlescape [tc2:hostname]]'"] {
+ return 0
+ }
+
+ #Check 2 - User is in the group wheel on the server
+ if {[lsearch [exec -- id -Gn $username] wheel] == "-1"} {
+ return 0
+ } {
+ return 1
+ }
}
#Determines if $requester is *EXPLICITELY* allowed to allowed to manage the account $user
#When you invoke this proc, you should also check if the user is root.
# e.g. if {[tc2:isroot $requester] || [tc2:userallow $requester $user]} { ... }
proc tc2:userallow {requester user} {
- set sql "SELECT count(*) FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '[sqlescape $user]' AND user_id = [getuserid $user]"
- putdebug $sql
- sql $sql
+ set sql "SELECT count(*) FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '[sqlescape $user]' AND user_id = [getuserid $user]"
+ putdebug $sql
+ sql $sql
}
#tc2:getpermissions on $username: Gets permissions on the $username account
#tc2:getpermissions from $username: Gets permissions $username have on server accounts
proc tc2:getpermissions {keyword username} {
- switch $keyword {
- "from" {
- set sql "SELECT account_username FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND user_id = '[getuserid $username]'"
- }
- "on" {
- set sql "SELECT u.username FROM tc2_users_permissions p, users u WHERE p.server_name = '[sqlescape [tc2:hostname]]' AND p.account_username = '$username' AND u.user_id = p.user_id"
- }
- default {
- error "from or on expected"
- }
- }
- set accounts ""
- foreach row [sql $sql] {
- lappend accounts [lindex $row 0]
- }
+ switch $keyword {
+ "from" {
+ set sql "SELECT account_username FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND user_id = '[getuserid $username]'"
+ }
+ "on" {
+ set sql "SELECT u.username FROM tc2_users_permissions p, users u WHERE p.server_name = '[sqlescape [tc2:hostname]]' AND p.account_username = '$username' AND u.user_id = p.user_id"
+ }
+ default {
+ error "from or on expected"
+ }
+ }
+ set accounts ""
+ foreach row [sql $sql] {
+ lappend accounts [lindex $row 0]
+ }
}
#Creates an account $username from the $specified group
proc tc2:createaccount {username group} {
- if {$group == "web"} {
- set key "tc2.[tc2:hostname].wwwroot"
- if {[set wwwroot [registry get $key]] == ""} {
- error "You must define the registry key $key"
- }
- set homedir $wwwroot/$username
- if [catch {
- set reply [exec -- pw user add $username -g $group -b $wwwroot -w random]
- exec -- mkdir -p -m 0711 $homedir
- exec -- chown -R $username:web $homedir
- } err] {
- append reply " / "
- append reply $err
- }
- return $reply
- } {
- exec -- pw user add $username -g $group -m -w random
- }
+ if {$group == "web"} {
+ set key "tc2.[tc2:hostname].wwwroot"
+ if {[set wwwroot [registry get $key]] == ""} {
+ error "You must define the registry key $key"
+ }
+ set homedir $wwwroot/$username
+ if [catch {
+ set reply [exec -- pw user add $username -g $group -b $wwwroot -w random]
+ exec -- mkdir -p -m 0711 $homedir
+ exec -- chown -R $username:web $homedir
+ } err] {
+ append reply " / "
+ append reply $err
+ }
+ return $reply
+ } {
+ exec -- pw user add $username -g $group -m -w random
+ }
}
#Checks if $username begins by a letter and contains only letters, digits, -, _ or .
proc tc2:isdomain {domain} {
- regexp "^\[a-z0-9A-Z\]\[a-z0-9A-Z\\-.\]*\[a-z0-9A-Z\]$" $domain
+ regexp "^\[a-z0-9A-Z\]\[a-z0-9A-Z\\-.\]*\[a-z0-9A-Z\]$" $domain
}
proc tc2:cutdomain {domain} {
- #a.b.hostname a.b hostname
- #a.tld a.tld
- #a.b.tld a b.tld
- set items [split $domain .]
- if {[llength $items] < 3} {
- list "" $domain
- } elseif {[llength $items] == 3} {
- list [lindex $items 0] [join [lrange $items 1 end] .]
- } {
- set hostname [exec hostname -f]
- set k [expr [llength $hostname] + 1]
- if {[lrange $items end-$k end] == [split $hostname .]} {
- list [join [lrange $items 0 $k] .] $hostname
- } {
- list [join [lrange $items 0 end-2] .] [join [lrange $items end-1 end] .]
- }
- }
+ #a.b.hostname a.b hostname
+ #a.tld a.tld
+ #a.b.tld a b.tld
+ set items [split $domain .]
+ if {[llength $items] < 3} {
+ list "" $domain
+ } elseif {[llength $items] == 3} {
+ list [lindex $items 0] [join [lrange $items 1 end] .]
+ } {
+ set hostname [exec hostname -f]
+ set k [expr [llength $hostname] + 1]
+ if {[lrange $items end-$k end] == [split $hostname .]} {
+ list [join [lrange $items 0 $k] .] $hostname
+ } {
+ list [join [lrange $items 0 end-2] .] [join [lrange $items end-1 end] .]
+ }
+ }
}
#Determines if $username is a valid MySQL user
proc tc2:mysql_user_exists {username} {
- sql7 "SELECT count(*) FROM mysql.user WHERE user = '[sqlescape $username]'"
+ sql7 "SELECT count(*) FROM mysql.user WHERE user = '[sqlescape $username]'"
}
#Gets the host matching the first $username MySQL user
proc tc2:mysql_get_host {username} {
- sql7 "SELECT host FROM mysql.user WHERE user = '[sqlescape $username]' LIMIT 1"
+ sql7 "SELECT host FROM mysql.user WHERE user = '[sqlescape $username]' LIMIT 1"
}
#Gets a temporary password
proc tc2:randpass {} {
- encrypt [rand 99999999] [rand 99999999]
+ encrypt [rand 99999999] [rand 99999999]
}
#Adds the SSH key $key to the $username account
proc tc2:sshaddkey {username key} {
- set sshdir "/home/$username/.ssh"
- set keysfile "$sshdir/authorized_keys"
- if ![file exists $sshdir] {
- exec -- mkdir -p -m 0700 $sshdir
- exec chown $username $sshdir
- }
- if ![file isdirectory $sshdir] {
- return 0
- }
- set fd [open $keysfile a]
- puts $fd $key
- close $fd
- exec chmod 600 $keysfile
- exec chown $username $keysfile
- return 1
+ set sshdir "/home/$username/.ssh"
+ set keysfile "$sshdir/authorized_keys"
+ if ![file exists $sshdir] {
+ exec -- mkdir -p -m 0700 $sshdir
+ exec chown $username $sshdir
+ }
+ if ![file isdirectory $sshdir] {
+ return 0
+ }
+ set fd [open $keysfile a]
+ puts $fd $key
+ close $fd
+ exec chmod 600 $keysfile
+ exec chown $username $keysfile
+ return 1
}
#Guesses web user from requester or domain
proc tc2:guesswebuser {requester domain} {
- set alphanumdomain [regsub -all {([^[:alnum:]])} [string range $domain 0 [string last . $domain]-1] ""]
- foreach candidate [list $domain [string tolower $domain] $alphanumdomain $requester [string tolower $requester]] {
- if {[tc2:username_isvalid $candidate] && [tc2:username_exists $candidate]} {
- return $candidate
- }
- }
- registry get tc2.[tc2:hostname].nginx.defaultuser
+ set alphanumdomain [regsub -all {([^[:alnum:]])} [string range $domain 0 [string last . $domain]-1] ""]
+ foreach candidate [list $domain [string tolower $domain] $alphanumdomain $requester [string tolower $requester]] {
+ if {[tc2:username_isvalid $candidate] && [tc2:username_exists $candidate]} {
+ return $candidate
+ }
+ }
+ registry get tc2.[tc2:hostname].nginx.defaultuser
}
#
@@ -231,262 +231,262 @@
#account exists
#account create <username> <group> [SSH public key url]
proc tc2:command:account {requester arg} {
- set command [lindex $arg 0]
- switch -- $command {
- "exists" {
- set username [lindex $arg 1]
- if ![tc2:username_isvalid $username] {
- return {0 "this is not a valid username"}
- }
- if [tc2:username_exists $username] {
- list 1 "$username is a valid account on [tc2:hostname]."
- } {
- list 1 "$username isn't a valid account on [tc2:hostname]."
- }
- }
-
- "isroot" {
- set username [lindex $arg 1]
- if ![tc2:username_isvalid $username] {
- return {0 "this is not a valid username"}
- }
- if [tc2:isroot $username] {
- list 1 "$username has got root accreditation on [tc2:hostname]."
- } {
- list 1 "$username doesn't seem to have any root accreditation [tc2:hostname]."
- }
- }
-
- "permission" {
- set username [lindex $arg 1]
- if ![tc2:username_isvalid $username] {
- return {0 "this is not a valid username"}
- }
-
- switch -- [lindex $arg 2] {
- "" {
- set sentences {}
- set accounts_from [tc2:getpermissions from $username]
- set accounts_on [tc2:getpermissions on $username]
- if {$accounts_on != ""} {
- lappend sentences "has authority upon [join $accounts_on ", "]"
- }
- if {$accounts_from != ""} {
- lappend sentences "account can be managed from IRC by [join $accounts_from ", "]"
- }
- if {[tc2:isroot $username]} {
- lappend sentences "has root access"
- }
- if {$sentences == ""} {
- list 1 nada
- } {
- list 1 "$username [join $sentences " / "]."
- }
- }
-
- "add" {
- #e.g. .account permission espacewin add dereckson
- # will give access to the espacewin account to dereckson
- if {![tc2:isroot $requester] && ![tc2:userallow $requester $username]} {
- return "0 {you don't have the authority to give access to $username account.}"
- }
-
- #Asserts mandataire has an account
- set mandataire [lindex $arg 3]
- if {[set mandataire_user_id [getuserid $mandataire]] == ""} {
- return "0 {please create first a bot account for $mandataire.}"
- }
-
- #Adds the permission
- sqlreplace tc2_users_permissions "server_name account_username user_id" [list [tc2:hostname] $username $mandataire_user_id]
-
- return "1 {$mandataire has now access to $username account.}"
- }
-
- "del" {
- #e.g. .account permission espacewin del dereckson
- # will remove access to the espacewin account to dereckson
- if {![tc2:isroot $requester] && ![tc2:userallow $requester $username]} {
- return "0 {you don't have the authority to manage the $username account.}"
- }
-
- #Asserts mandataire is a valid bot account
- set mandataire [lindex $arg 3]
- if {[set mandataire_user_id [getuserid $mandataire]] == ""} {
- return "0 {$mandataire doesn't have a bot account, and so, no such permission.}"
- }
-
- #Checks if the permission exists
- if ![tc2:userallow $requester $mandataire] {
- return "0 {$mandataire haven't had an access to $username account.}"
- }
-
- #Removess the permission
- sql "DELETE FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '$username' AND user_id = '$mandataire_user_id'"
-
- return "1 {$mandataire doesn't have access to $username account anymore.}"
- }
-
- "+root" {
- #Checks right and need
- if ![tc2:isroot $requester] {
- return "0 {you don't have root authority yourself.}"
- }
- if [tc2:isroot $username] {
- return "0 {$username have already root authority.}"
- }
-
- #Declares him as root
- sqlreplace tc2_roots "server_name account_username user_id" [list [tc2:hostname] $username [getuserid $username]]
-
- #Checks if our intervention is enough
- if [tc2:isroot $username] {
- list 1 "$username have now root authority."
- } {
- list 1 "$username have been added as root and will have root authority once in the wheel group."
- }
- }
-
- "-root" {
- if ![tc2:isroot $requester] {
- return {0 "you don't have root authority yourself."}
- }
- if ![tc2:isroot $username] {
- list 0 "$username doesn't have root authority."
- } {
- #Removes entry from db
- sql "DELETE FROM tc2_roots WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '[sqlescape $username]'"
-
- #Checks if our intervention is enough
- list 1 "$username doesn't have root authority on IRC anymore. Check also the wheel group."
- }
- }
-
- default {
- list 0 "expected: add <username>, del <username>, +root, -root, or nothing"
- }
- }
- }
-
- "groups" {
- set username [lindex $arg 1]
- if ![tc2:username_isvalid $username] {
- return {0 "this is not a valid username"}
- }
- if [tc2:username_exists $username] {
- list 1 [exec -- id -Gn $username]
- } {
- list 0 "$username isn't a valid account on [tc2:hostname]."
- }
- }
-
- "create" {
- #Checks access and need
- set username [lindex $arg 1]
- if ![tc2:username_isvalid $username] {
- return {0 "this is not a valid username"}
- }
- if [tc2:username_exists $username] {
- return "0 {there is already a $username account}"
- }
- if ![tc2:isroot $requester] {
- return "0 {you don't have root authority, which is required to create an account.}"
- }
-
- #Checks group
- set group [lindex $arg 2]
- set validgroups [registry get tc2.[tc2:hostname].usergroups]
- if {$group == ""} {
- return "0 {In which group? Must be amongst $validgroups.}"
- }
- if {[lsearch $validgroups $group] == -1} {
- return "0 {$group isn't a valid group, must be among $validgroups}"
- }
-
- #Checks public key URL. If so, creates user with SSH key and random password.
- if {[set url [geturls [lindex $arg 3]]] != ""} {
- set password [tc2:createaccount $username $group]
- set keyAdded 0
- if {[catch {
- set key [geturltext $url]
- if {$key != ""} {
- set keyAdded [tc2:sshaddkey $username $key]
- }
- }]} {
- putdebug "An error occured adding the SSH key."
- set keyAdded 0
- }
- if {$keyAdded} {
- return [list 1 "account created"]
- } {
- return [list 1 "account created but can't install SSH key ; you can use the password $password"]
- }
- }
-
- #Creates user without SSH key.
- list 1 [tc2:createaccount $username $group]
- }
-
- "" {
- return {0 "permission, isroot, exists or groups expected"}
- }
-
- default {
- set reply 0
- lappend reply "unknown command: $command"
- }
- }
+ set command [lindex $arg 0]
+ switch -- $command {
+ "exists" {
+ set username [lindex $arg 1]
+ if ![tc2:username_isvalid $username] {
+ return {0 "this is not a valid username"}
+ }
+ if [tc2:username_exists $username] {
+ list 1 "$username is a valid account on [tc2:hostname]."
+ } {
+ list 1 "$username isn't a valid account on [tc2:hostname]."
+ }
+ }
+
+ "isroot" {
+ set username [lindex $arg 1]
+ if ![tc2:username_isvalid $username] {
+ return {0 "this is not a valid username"}
+ }
+ if [tc2:isroot $username] {
+ list 1 "$username has got root accreditation on [tc2:hostname]."
+ } {
+ list 1 "$username doesn't seem to have any root accreditation [tc2:hostname]."
+ }
+ }
+
+ "permission" {
+ set username [lindex $arg 1]
+ if ![tc2:username_isvalid $username] {
+ return {0 "this is not a valid username"}
+ }
+
+ switch -- [lindex $arg 2] {
+ "" {
+ set sentences {}
+ set accounts_from [tc2:getpermissions from $username]
+ set accounts_on [tc2:getpermissions on $username]
+ if {$accounts_on != ""} {
+ lappend sentences "has authority upon [join $accounts_on ", "]"
+ }
+ if {$accounts_from != ""} {
+ lappend sentences "account can be managed from IRC by [join $accounts_from ", "]"
+ }
+ if {[tc2:isroot $username]} {
+ lappend sentences "has root access"
+ }
+ if {$sentences == ""} {
+ list 1 nada
+ } {
+ list 1 "$username [join $sentences " / "]."
+ }
+ }
+
+ "add" {
+ #e.g. .account permission espacewin add dereckson
+ # will give access to the espacewin account to dereckson
+ if {![tc2:isroot $requester] && ![tc2:userallow $requester $username]} {
+ return "0 {you don't have the authority to give access to $username account.}"
+ }
+
+ #Asserts mandataire has an account
+ set mandataire [lindex $arg 3]
+ if {[set mandataire_user_id [getuserid $mandataire]] == ""} {
+ return "0 {please create first a bot account for $mandataire.}"
+ }
+
+ #Adds the permission
+ sqlreplace tc2_users_permissions "server_name account_username user_id" [list [tc2:hostname] $username $mandataire_user_id]
+
+ return "1 {$mandataire has now access to $username account.}"
+ }
+
+ "del" {
+ #e.g. .account permission espacewin del dereckson
+ # will remove access to the espacewin account to dereckson
+ if {![tc2:isroot $requester] && ![tc2:userallow $requester $username]} {
+ return "0 {you don't have the authority to manage the $username account.}"
+ }
+
+ #Asserts mandataire is a valid bot account
+ set mandataire [lindex $arg 3]
+ if {[set mandataire_user_id [getuserid $mandataire]] == ""} {
+ return "0 {$mandataire doesn't have a bot account, and so, no such permission.}"
+ }
+
+ #Checks if the permission exists
+ if ![tc2:userallow $requester $mandataire] {
+ return "0 {$mandataire haven't had an access to $username account.}"
+ }
+
+ #Removess the permission
+ sql "DELETE FROM tc2_users_permissions WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '$username' AND user_id = '$mandataire_user_id'"
+
+ return "1 {$mandataire doesn't have access to $username account anymore.}"
+ }
+
+ "+root" {
+ #Checks right and need
+ if ![tc2:isroot $requester] {
+ return "0 {you don't have root authority yourself.}"
+ }
+ if [tc2:isroot $username] {
+ return "0 {$username have already root authority.}"
+ }
+
+ #Declares him as root
+ sqlreplace tc2_roots "server_name account_username user_id" [list [tc2:hostname] $username [getuserid $username]]
+
+ #Checks if our intervention is enough
+ if [tc2:isroot $username] {
+ list 1 "$username have now root authority."
+ } {
+ list 1 "$username have been added as root and will have root authority once in the wheel group."
+ }
+ }
+
+ "-root" {
+ if ![tc2:isroot $requester] {
+ return {0 "you don't have root authority yourself."}
+ }
+ if ![tc2:isroot $username] {
+ list 0 "$username doesn't have root authority."
+ } {
+ #Removes entry from db
+ sql "DELETE FROM tc2_roots WHERE server_name = '[sqlescape [tc2:hostname]]' AND account_username = '[sqlescape $username]'"
+
+ #Checks if our intervention is enough
+ list 1 "$username doesn't have root authority on IRC anymore. Check also the wheel group."
+ }
+ }
+
+ default {
+ list 0 "expected: add <username>, del <username>, +root, -root, or nothing"
+ }
+ }
+ }
+
+ "groups" {
+ set username [lindex $arg 1]
+ if ![tc2:username_isvalid $username] {
+ return {0 "this is not a valid username"}
+ }
+ if [tc2:username_exists $username] {
+ list 1 [exec -- id -Gn $username]
+ } {
+ list 0 "$username isn't a valid account on [tc2:hostname]."
+ }
+ }
+
+ "create" {
+ #Checks access and need
+ set username [lindex $arg 1]
+ if ![tc2:username_isvalid $username] {
+ return {0 "this is not a valid username"}
+ }
+ if [tc2:username_exists $username] {
+ return "0 {there is already a $username account}"
+ }
+ if ![tc2:isroot $requester] {
+ return "0 {you don't have root authority, which is required to create an account.}"
+ }
+
+ #Checks group
+ set group [lindex $arg 2]
+ set validgroups [registry get tc2.[tc2:hostname].usergroups]
+ if {$group == ""} {
+ return "0 {In which group? Must be amongst $validgroups.}"
+ }
+ if {[lsearch $validgroups $group] == -1} {
+ return "0 {$group isn't a valid group, must be among $validgroups}"
+ }
+
+ #Checks public key URL. If so, creates user with SSH key and random password.
+ if {[set url [geturls [lindex $arg 3]]] != ""} {
+ set password [tc2:createaccount $username $group]
+ set keyAdded 0
+ if {[catch {
+ set key [geturltext $url]
+ if {$key != ""} {
+ set keyAdded [tc2:sshaddkey $username $key]
+ }
+ }]} {
+ putdebug "An error occured adding the SSH key."
+ set keyAdded 0
+ }
+ if {$keyAdded} {
+ return [list 1 "account created"]
+ } {
+ return [list 1 "account created but can't install SSH key ; you can use the password $password"]
+ }
+ }
+
+ #Creates user without SSH key.
+ list 1 [tc2:createaccount $username $group]
+ }
+
+ "" {
+ return {0 "permission, isroot, exists or groups expected"}
+ }
+
+ default {
+ set reply 0
+ lappend reply "unknown command: $command"
+ }
+ }
}
#.mysql create database [username]
proc tc2:command:mysql {requester arg} {
- switch -- [set command [lindex $arg 0]] {
- "create" {
- set database [lindex $arg 1]
- set username [lindex $arg 2]
- if ![tc2:username_isvalid $database] {
- list 0 "Invalid database name: $database"
- } elseif [file exists [registry get tc2.[tc2:hostname].mysql.datadir]/$database] {
- list 1 "database $database already exists"
- } elseif {$username == ""} {
- if {[tc2:mysql_user_exists $database]} {
- tc2:command:mysql $requester [list create $database $database]
- } {
- #Ok, create the database and a new user with same login than db and random password
- set password [tc2:randpass]
- if [catch {
- sql7 "CREATE DATABASE $database"
- sql7 "GRANT ALL PRIVILEGES ON $database.* TO '$database'@'localhost' IDENTIFIED BY '$password'"
- } err] {
- list 0 $err
- } {
- list 1 "database created, with rights granted to user $database, with $password as temporary password"
- }
- }
- } {
- if {![tc2:username_isvalid $username]} {
- list 0 "Invalid username: $username"
- }
- if {[tc2:isroot $requester] || [tc2:userallow $requester $username]} {
- if [catch {
- set host [tc2:mysql_get_host $username]
- sql7 "CREATE DATABASE $database"
- sql7 "GRANT ALL PRIVILEGES ON $database.* TO '$username'@'$host'"
- } err] {
- list 0 $err
- } {
- list 1 "database $database created, with rights granted to $username@$host"
- }
- } {
- [list 0 "You aren't root nor have authority on $username"
- }
- }
- }
-
- default {
- list 0 "try .mysql create <database> \[username\]"
- }
- }
+ switch -- [set command [lindex $arg 0]] {
+ "create" {
+ set database [lindex $arg 1]
+ set username [lindex $arg 2]
+ if ![tc2:username_isvalid $database] {
+ list 0 "Invalid database name: $database"
+ } elseif [file exists [registry get tc2.[tc2:hostname].mysql.datadir]/$database] {
+ list 1 "database $database already exists"
+ } elseif {$username == ""} {
+ if {[tc2:mysql_user_exists $database]} {
+ tc2:command:mysql $requester [list create $database $database]
+ } {
+ #Ok, create the database and a new user with same login than db and random password
+ set password [tc2:randpass]
+ if [catch {
+ sql7 "CREATE DATABASE $database"
+ sql7 "GRANT ALL PRIVILEGES ON $database.* TO '$database'@'localhost' IDENTIFIED BY '$password'"
+ } err] {
+ list 0 $err
+ } {
+ list 1 "database created, with rights granted to user $database, with $password as temporary password"
+ }
+ }
+ } {
+ if {![tc2:username_isvalid $username]} {
+ list 0 "Invalid username: $username"
+ }
+ if {[tc2:isroot $requester] || [tc2:userallow $requester $username]} {
+ if [catch {
+ set host [tc2:mysql_get_host $username]
+ sql7 "CREATE DATABASE $database"
+ sql7 "GRANT ALL PRIVILEGES ON $database.* TO '$username'@'$host'"
+ } err] {
+ list 0 $err
+ } {
+ list 1 "database $database created, with rights granted to $username@$host"
+ }
+ } {
+ [list 0 "You aren't root nor have authority on $username"
+ }
+ }
+ }
+
+ default {
+ list 0 "try .mysql create <database> \[username\]"
+ }
+ }
}
#.nginx reload
@@ -496,162 +496,162 @@
#TODO .nginx server edit <domain> <-php|+php>
#TODO .nginx server edit <domain> <-ssl|+ssl>
proc tc2:command:nginx {requester arg} {
- switch -- [set command [lindex $arg 0]] {
- "reload" {
- if [catch {exec /usr/local/etc/rc.d/nginx reload} output] {
- if {[string first "is successful" $output] == -1} {
- return [list 0 $output]
- } {
- return {1 "ok, nginx reloaded"}
- }
- } {
- return {1 "ok, nginx reloaded"}
- }
- }
-
- "status" {
- set conn [exec sockstat | grep nginx | grep -c tcp]
- if {$conn == 0} {
- return {1 "nginx not running"}
- } {
- return "1 {$conn connection[s $conn]}"
- }
- return $reply
- }
-
- "create" {
- tc2:command:nginx $requester [list server add {*}[lrange $arg 1 end]]
- }
-
- "server" {
- #.nginx server add <domain> [directory] [+php] [+upstream <url>] [+ssl]
- #.nginx server edit <domain> <+php|-php>
- set subcommand [lindex $arg 1]
- set domain [lindex $arg 2]
-
- if {$subcommand != "" && $domain != "" && [tc2:isdomain $domain]} {
- set fulldomain $domain
- foreach "subdomain domain" [tc2:cutdomain $fulldomain] {}
- set tpldir [registry get tc2.[tc2:hostname].nginx.tpldir]
- set config [registry get tc2.[tc2:hostname].nginx.etcdir]/$domain.conf
- switch $subcommand {
- add {
- #Default options
- global username
- set wwwdir [registry get tc2.[tc2:hostname].wwwroot]/$domain/$subdomain
- set logdir [registry get tc2.[tc2:hostname].nginx.logdir]/$domain
- set ssldir [registry get tc2.[tc2:hostname].nginx.ssldir]/$domain
- set user [tc2:guesswebuser $requester $domain]
- set tpl vhost.tpl
- set php 0
- set ssl 0
- set upstream 0
- set upstream_keyword ""
- set upstream_url ""
- set index "index.html index.htm default.html default.htm"
- set phpfpmport ""
-
- #Parses options
- for {set i 3} {$i < [llength $arg]} {incr i} {
- set option [lindex $arg $i]
- if {$option == "+php"} {
- set php 1
- set index "index.html index.php index.htm"
-
- #Determines php-fpm port
- set phpfpmport [sqlscalar "SELECT pool_port FROM tc2_phpfpm_pools WHERE pool_user = '[sqlescape $user]'"]
- if {$phpfpmport == ""} {
- #Fallbacks to default www pool
- set port [registry get tc2.[tc2:hostname].phpfpm.defaultport]
- if {$phpfpmport == ""} {
- return "0 {no pool for $user, and tc2.[tc2:hostname].phpfpm.defaultport registry key isn't defined to fallback to www pool}"
- }
- }
- } elseif {$option == "+upstream"} {
- set upstream 1
- set upstream_keyword [lindex $arg [incr i]]
- set upstream_url [lindex $arg [incr i]]
- } elseif {$option == "+ssl"} {
- set ssl 1
- } elseif {[string index $option 0] == "/"} {
- set wwwdir $option
- } else {
- return [list 0 "Unknown option: $option"]
- }
- }
-
- #TODO: check if $user is legitimate
- if {$user != "www" && ![tc2:isroot $requester] && ![tc2:userallow $requester $user]} {
- return "0 {you don't have the authority to create a website linked to $user account.}"
- }
-
- #Creates needed directories
- if ![file exists $wwwdir] {
- exec -- mkdir -m 0711 -p $wwwdir
- exec -- chown $user $wwwdir
- }
- if ![file exists $logdir] {
- exec -- mkdir -m 0711 -p $wwwdir
- exec -- chown $user $wwwdir
- }
-
- #Prepares new config block
- set fd [open $tpldir/$tpl r]
- set template [read $fd]
- close $fd
- set xtra ""
- foreach option "ssl php upstream" {
- if $$option {
- set xtrafile $tpldir/extra-$option.tpl
- if ![file exists $xtrafile] {
- return [list 0 "Template file not found: $xtrafile"]
- }
- set fd [open $xtrafile]
- append xtra "\n\n"
- append xtra [read $fd]
- close $fd
- }
- }
- set configblock [string map [list %EXTRACONFIG% $xtra] $template]
- set configblock [string map [list %REQUESTER% $requester %TIME% [unixtime] %COMMENT% "Autogenerated by $username" %FULLDOMAIN% $fulldomain %LOGDIR% $logdir %SSLDIR% $ssldir %SUBDOMAIN% $subdomain %WWWDIR% $wwwdir %PHPFPMPORT% $phpfpmport %CUSTOM-PREPHP% "" %CUSTOM-PHP% "" %CUSTOM% "" %UPSTREAMKEYWORD% $upstream_keyword %UPSTREAMURL% $upstream_url %INDEX% $index %EXTRACONFIG% $xtra] $configblock]
-
- #Opens or creates domain config file
- if [file exists $config] {
- set fd [open $config a]
- } {
- #We use a also template for ou config file header
- set fd [open $tpldir/vhost-header.tpl r]
- set template [read $fd]
- close $fd
- set fd [open $config w]
- puts $fd [string map "%DOMAIN% $domain" $template]
- flush $fd
- }
-
- #Writes new config block
- puts $fd ""
- puts $fd $configblock
- close $fd
- return [list 1 "done, $fulldomain server block added to $config ; use .nginx reload to save"]
- }
-
- edit {
- return [list 1 "not yet implemented, edit the file $config"]
- }
- }
- }
- return {0 "usage: .nginx server add/edit domain \[options\]"}
- }
-
- "" {
- return {0 "server add, server edit, status or reload expected"}
- }
-
- default {
- set reply 0
- lappend reply "unknown command: $command"
- }
- }
+ switch -- [set command [lindex $arg 0]] {
+ "reload" {
+ if [catch {exec /usr/local/etc/rc.d/nginx reload} output] {
+ if {[string first "is successful" $output] == -1} {
+ return [list 0 $output]
+ } {
+ return {1 "ok, nginx reloaded"}
+ }
+ } {
+ return {1 "ok, nginx reloaded"}
+ }
+ }
+
+ "status" {
+ set conn [exec sockstat | grep nginx | grep -c tcp]
+ if {$conn == 0} {
+ return {1 "nginx not running"}
+ } {
+ return "1 {$conn connection[s $conn]}"
+ }
+ return $reply
+ }
+
+ "create" {
+ tc2:command:nginx $requester [list server add {*}[lrange $arg 1 end]]
+ }
+
+ "server" {
+ #.nginx server add <domain> [directory] [+php] [+upstream <url>] [+ssl]
+ #.nginx server edit <domain> <+php|-php>
+ set subcommand [lindex $arg 1]
+ set domain [lindex $arg 2]
+
+ if {$subcommand != "" && $domain != "" && [tc2:isdomain $domain]} {
+ set fulldomain $domain
+ foreach "subdomain domain" [tc2:cutdomain $fulldomain] {}
+ set tpldir [registry get tc2.[tc2:hostname].nginx.tpldir]
+ set config [registry get tc2.[tc2:hostname].nginx.etcdir]/$domain.conf
+ switch $subcommand {
+ add {
+ #Default options
+ global username
+ set wwwdir [registry get tc2.[tc2:hostname].wwwroot]/$domain/$subdomain
+ set logdir [registry get tc2.[tc2:hostname].nginx.logdir]/$domain
+ set ssldir [registry get tc2.[tc2:hostname].nginx.ssldir]/$domain
+ set user [tc2:guesswebuser $requester $domain]
+ set tpl vhost.tpl
+ set php 0
+ set ssl 0
+ set upstream 0
+ set upstream_keyword ""
+ set upstream_url ""
+ set index "index.html index.htm default.html default.htm"
+ set phpfpmport ""
+
+ #Parses options
+ for {set i 3} {$i < [llength $arg]} {incr i} {
+ set option [lindex $arg $i]
+ if {$option == "+php"} {
+ set php 1
+ set index "index.html index.php index.htm"
+
+ #Determines php-fpm port
+ set phpfpmport [sqlscalar "SELECT pool_port FROM tc2_phpfpm_pools WHERE pool_user = '[sqlescape $user]'"]
+ if {$phpfpmport == ""} {
+ #Fallbacks to default www pool
+ set port [registry get tc2.[tc2:hostname].phpfpm.defaultport]
+ if {$phpfpmport == ""} {
+ return "0 {no pool for $user, and tc2.[tc2:hostname].phpfpm.defaultport registry key isn't defined to fallback to www pool}"
+ }
+ }
+ } elseif {$option == "+upstream"} {
+ set upstream 1
+ set upstream_keyword [lindex $arg [incr i]]
+ set upstream_url [lindex $arg [incr i]]
+ } elseif {$option == "+ssl"} {
+ set ssl 1
+ } elseif {[string index $option 0] == "/"} {
+ set wwwdir $option
+ } else {
+ return [list 0 "Unknown option: $option"]
+ }
+ }
+
+ #TODO: check if $user is legitimate
+ if {$user != "www" && ![tc2:isroot $requester] && ![tc2:userallow $requester $user]} {
+ return "0 {you don't have the authority to create a website linked to $user account.}"
+ }
+
+ #Creates needed directories
+ if ![file exists $wwwdir] {
+ exec -- mkdir -m 0711 -p $wwwdir
+ exec -- chown $user $wwwdir
+ }
+ if ![file exists $logdir] {
+ exec -- mkdir -m 0711 -p $wwwdir
+ exec -- chown $user $wwwdir
+ }
+
+ #Prepares new config block
+ set fd [open $tpldir/$tpl r]
+ set template [read $fd]
+ close $fd
+ set xtra ""
+ foreach option "ssl php upstream" {
+ if $$option {
+ set xtrafile $tpldir/extra-$option.tpl
+ if ![file exists $xtrafile] {
+ return [list 0 "Template file not found: $xtrafile"]
+ }
+ set fd [open $xtrafile]
+ append xtra "\n\n"
+ append xtra [read $fd]
+ close $fd
+ }
+ }
+ set configblock [string map [list %EXTRACONFIG% $xtra] $template]
+ set configblock [string map [list %REQUESTER% $requester %TIME% [unixtime] %COMMENT% "Autogenerated by $username" %FULLDOMAIN% $fulldomain %LOGDIR% $logdir %SSLDIR% $ssldir %SUBDOMAIN% $subdomain %WWWDIR% $wwwdir %PHPFPMPORT% $phpfpmport %CUSTOM-PREPHP% "" %CUSTOM-PHP% "" %CUSTOM% "" %UPSTREAMKEYWORD% $upstream_keyword %UPSTREAMURL% $upstream_url %INDEX% $index %EXTRACONFIG% $xtra] $configblock]
+
+ #Opens or creates domain config file
+ if [file exists $config] {
+ set fd [open $config a]
+ } {
+ #We use a also template for ou config file header
+ set fd [open $tpldir/vhost-header.tpl r]
+ set template [read $fd]
+ close $fd
+ set fd [open $config w]
+ puts $fd [string map "%DOMAIN% $domain" $template]
+ flush $fd
+ }
+
+ #Writes new config block
+ puts $fd ""
+ puts $fd $configblock
+ close $fd
+ return [list 1 "done, $fulldomain server block added to $config ; use .nginx reload to save"]
+ }
+
+ edit {
+ return [list 1 "not yet implemented, edit the file $config"]
+ }
+ }
+ }
+ return {0 "usage: .nginx server add/edit domain \[options\]"}
+ }
+
+ "" {
+ return {0 "server add, server edit, status or reload expected"}
+ }
+
+ default {
+ set reply 0
+ lappend reply "unknown command: $command"
+ }
+ }
}
@@ -659,152 +659,152 @@
#phpfpm status
#phpfpm create <user>
proc tc2:command:phpfpm {requester arg} {
- set command [lindex $arg 0]
-
- switch $command {
- "reload" {
- if [catch {exec /usr/local/etc/rc.d/php-fpm reload} output] {
- list 0 [string map {"\n" " "} $output]
- } {
- return {1 "ok, php-fpm reloaded"}
- }
- }
-
- "restart" {
- if [catch {exec /usr/local/etc/rc.d/php-fpm restart} output] {
- list 0 [string map {"\n" " "} $output]
- } {
- return {1 "ok, php-fpm reloaded"}
- }
- }
-
- "status" {
- catch {exec /usr/local/etc/rc.d/php-fpm status} output
- list 1 [string map {"\n" " "} $output]
- }
-
- "create" {
- set user [lindex $arg 1]
- if {$user == ""} {
- return {0 "syntax: phpfpm create <user>"}
- }
- if ![tc2:username_isvalid $user] {
- return {0 "not a valid username"}
- }
- if ![tc2:username_exists $user] {
- return "0 {$user isn't a valid [tc2:hostname] user}"
- }
- if [file exists [set file "/usr/local/etc/php-fpm/pool-prod/$user.conf"]] {
- return "0 {there is already a $user pool}"
- }
- if {![tc2:isroot $requester] && ![tc2:userallow $requester $user]} {
- return "0 {you don't have the authority to create a pool under $user user}"
- }
- set port [sql "SELECT MAX(pool_port) FROM tc2_phpfpm_pools"]
- if {$port == ""} {
- set port 9000
- } {
- incr port
- }
-
- #Adds it in MySQL table
- set time [unixtime]
- sqladd tc2_phpfpm_pools {pool_user pool_port pool_requester pool_time} [list $user $port $requester $time]
-
- #Write config gile
- global username
- set fd [open /usr/local/etc/php-fpm/pool.tpl r]
- set template [read $fd]
- close $fd
- set fd [open $file w]
- puts $fd [string map "%REQUESTER% $requester %TIME% $time %PORT% $port %USER% $user %GROUP% [exec -- id -gn $user] %COMMENT% {Autogenerated by $username}" $template]
- close $fd
- exec -- chown root:config $file
- exec -- chmod 644 $file
- return {1 "pool created, use '.phpfpm reload' to enable it"}
- }
-
- "" {
- return {0 "create, status or reload expected"}
- }
-
- default {
- set reply 0
- lappend reply "unknown command: $command"
- }
- }
+ set command [lindex $arg 0]
+
+ switch $command {
+ "reload" {
+ if [catch {exec /usr/local/etc/rc.d/php-fpm reload} output] {
+ list 0 [string map {"\n" " "} $output]
+ } {
+ return {1 "ok, php-fpm reloaded"}
+ }
+ }
+
+ "restart" {
+ if [catch {exec /usr/local/etc/rc.d/php-fpm restart} output] {
+ list 0 [string map {"\n" " "} $output]
+ } {
+ return {1 "ok, php-fpm reloaded"}
+ }
+ }
+
+ "status" {
+ catch {exec /usr/local/etc/rc.d/php-fpm status} output
+ list 1 [string map {"\n" " "} $output]
+ }
+
+ "create" {
+ set user [lindex $arg 1]
+ if {$user == ""} {
+ return {0 "syntax: phpfpm create <user>"}
+ }
+ if ![tc2:username_isvalid $user] {
+ return {0 "not a valid username"}
+ }
+ if ![tc2:username_exists $user] {
+ return "0 {$user isn't a valid [tc2:hostname] user}"
+ }
+ if [file exists [set file "/usr/local/etc/php-fpm/pool-prod/$user.conf"]] {
+ return "0 {there is already a $user pool}"
+ }
+ if {![tc2:isroot $requester] && ![tc2:userallow $requester $user]} {
+ return "0 {you don't have the authority to create a pool under $user user}"
+ }
+ set port [sql "SELECT MAX(pool_port) FROM tc2_phpfpm_pools"]
+ if {$port == ""} {
+ set port 9000
+ } {
+ incr port
+ }
+
+ #Adds it in MySQL table
+ set time [unixtime]
+ sqladd tc2_phpfpm_pools {pool_user pool_port pool_requester pool_time} [list $user $port $requester $time]
+
+ #Write config gile
+ global username
+ set fd [open /usr/local/etc/php-fpm/pool.tpl r]
+ set template [read $fd]
+ close $fd
+ set fd [open $file w]
+ puts $fd [string map "%REQUESTER% $requester %TIME% $time %PORT% $port %USER% $user %GROUP% [exec -- id -gn $user] %COMMENT% {Autogenerated by $username}" $template]
+ close $fd
+ exec -- chown root:config $file
+ exec -- chmod 644 $file
+ return {1 "pool created, use '.phpfpm reload' to enable it"}
+ }
+
+ "" {
+ return {0 "create, status or reload expected"}
+ }
+
+ default {
+ set reply 0
+ lappend reply "unknown command: $command"
+ }
+ }
}
#.df
#.df pull [extension]
proc tc2:command:df {requester arg} {
- set command [lindex $arg 0]
-
- switch $command {
- "pull" {
- set what [lindex $arg 1]
- if {$what == ""} {
- set what core
- } {
- if {![file exists [registry get df.paths.extensions]/$what]} {
- return [list 0 "Invalid extension: $what"]
- }
- }
-
- catch {exec -- su -m [registry get df.who] -c "[registry get df.paths.bin]/dfpull $what"} status
- if { $status == "Already up-to-date." } {
- return { 1 "Repository already up-to-date." }
- } elseif { [string first "Can't currently pull code" $status] > -1 } {
- list 0 $status
- } else {
- putdebug $status
- return { 1 "repository updated" }
- }
- }
-
- "" {
- return {0 "pull expected"}
- }
-
- default {
- set reply 0
- lappend reply "unknown command: $command"
- }
-
- }
+ set command [lindex $arg 0]
+
+ switch $command {
+ "pull" {
+ set what [lindex $arg 1]
+ if {$what == ""} {
+ set what core
+ } {
+ if {![file exists [registry get df.paths.extensions]/$what]} {
+ return [list 0 "Invalid extension: $what"]
+ }
+ }
+
+ catch {exec -- su -m [registry get df.who] -c "[registry get df.paths.bin]/dfpull $what"} status
+ if { $status == "Already up-to-date." } {
+ return { 1 "Repository already up-to-date." }
+ } elseif { [string first "Can't currently pull code" $status] > -1 } {
+ list 0 $status
+ } else {
+ putdebug $status
+ return { 1 "repository updated" }
+ }
+ }
+
+ "" {
+ return {0 "pull expected"}
+ }
+
+ default {
+ set reply 0
+ lappend reply "unknown command: $command"
+ }
+
+ }
}
#ci status
#ci stop
proc tc2:command:ci {requester arg} {
- set command [lindex $arg 0]
-
- switch $command {
- "start" {
- list 0 [string range "use /usr/local/etc/rc.d/jenkins onestart" 0 end]
- }
-
- "status" {
- catch {exec /usr/local/etc/rc.d/jenkins onestatus} status
- list 1 [string range $status 0 [string first . $status]]
- }
-
- "stop" {
- #Jenkins doesn't reply to stop signal on the server, so we kill it.
- if [catch {exec -- kill -9 [exec cat /var/run/jenkins/jenkins.pid]} output] {
- list 0 [string map {"\n" " "} $output]
- } {
- return {1 "ok, Jenkins stopped"}
- }
- }
-
- "" {
- return {0 "status or stop expected"}
- }
-
- default {
- set reply 0
- lappend reply "unknown command: $command"
- }
- }
+ set command [lindex $arg 0]
+
+ switch $command {
+ "start" {
+ list 0 [string range "use /usr/local/etc/rc.d/jenkins onestart" 0 end]
+ }
+
+ "status" {
+ catch {exec /usr/local/etc/rc.d/jenkins onestatus} status
+ list 1 [string range $status 0 [string first . $status]]
+ }
+
+ "stop" {
+ #Jenkins doesn't reply to stop signal on the server, so we kill it.
+ if [catch {exec -- kill -9 [exec cat /var/run/jenkins/jenkins.pid]} output] {
+ list 0 [string map {"\n" " "} $output]
+ } {
+ return {1 "ok, Jenkins stopped"}
+ }
+ }
+
+ "" {
+ return {0 "status or stop expected"}
+ }
+
+ default {
+ set reply 0
+ lappend reply "unknown command: $command"
+ }
+ }
}
diff --git a/TC2/Time.tcl b/TC2/Time.tcl
--- a/TC2/Time.tcl
+++ b/TC2/Time.tcl
@@ -5,22 +5,22 @@
bind cron - "0 4 * * *" cron:daily
proc onload {} {
- sqlconnect sql7
+ sqlconnect sql7
}
proc launch {} {
- #This proc, called on startup, causes the eggdrop
- #to die on "unloadmodule server"
- #.tcl launch manually will work
-
- #Drops IRC support
- unloadmodule irc
- unloadmodule ctcp
- unloadmodule channels
- unloadmodule server
-
- #Links to primary bot
- link Daeghrefn
+ #This proc, called on startup, causes the eggdrop
+ #to die on "unloadmodule server"
+ #.tcl launch manually will work
+
+ #Drops IRC support
+ unloadmodule irc
+ unloadmodule ctcp
+ unloadmodule channels
+ unloadmodule server
+
+ #Links to primary bot
+ link Daeghrefn
}
#Every minute
@@ -29,15 +29,15 @@
#Every 5 minutes
proc cron:often {minute hour day month weekday} {
- #Reconnects to sql, sql2
- sqlrehash
-
- #Sends a no-op command to keep sql7 alive
- if [catch {
- sql7 "SELECT 666"
- }] {
- putcmdlog "Warning: not connected to sql7 - mysql won't work."
- }
+ #Reconnects to sql, sql2
+ sqlrehash
+
+ #Sends a no-op command to keep sql7 alive
+ if [catch {
+ sql7 "SELECT 666"
+ }] {
+ putcmdlog "Warning: not connected to sql7 - mysql won't work."
+ }
}
#Every hour
diff --git a/Wearg/Broker.tcl b/Wearg/Broker.tcl
--- a/Wearg/Broker.tcl
+++ b/Wearg/Broker.tcl
@@ -1,136 +1,136 @@
namespace eval broker {
- proc init {} {
- # Loads our librabbitmq wrapper extension
- if {![is_package_present rabbitmq]} {
- load lib/rabbitmq.so
- }
-
- # Connects to the broker
- if {![mq connected]} {
- connect
- }
-
- # Starts timer
- if {![is_timer_started]} {
- start_timer
- }
- }
-
- proc connect {} {
- mq connect [registry get broker.host] [vault_get broker username] [vault_get broker password] [registry get broker.vhost]
- }
-
- proc is_timer_started {} {
- expr [string first ::broker::on_tick [utimers]] > -1
- }
-
- proc start_timer {} {
- utimer 4 [namespace current]::on_tick
- }
-
- # Determines if we're in a risk to receive a SIGCHLD while the broker intercepts signals
- #
- # @param time The specified unixtime, or the current one if omitted
- # @return 1 if the risk is there, 0 if it shouldn't be risky
- proc near_SIGCHLD_arrival {{time ""}} {
- if {$time == ""} {
- set time [clock seconds]
- }
- set timePosition [expr $time % 300]
- expr $timePosition == 0 || $timePosition == 299
- }
-
- proc on_tick {} {
- if {![near_SIGCHLD_arrival]} {
- # We generally want to get messages, but not
- # when the SIGCHLD signal is sent to the bot
- # which seems to be every five minutes.
-
- get_messages
- }
- utimer 1 [namespace current]::on_tick
- }
-
- proc get_messages {} {
- foreach queue [registry get broker.queues] {
- while 1 {
- if {[catch {set message [mq get $queue -noack]} brokerError]} {
- if {[recover_from_broker_error $brokerError]} {
- continue
- } {
- error $brokerError
- }
- }
- if {$message == ""} {
- break
- } {
- on_message $queue $message
- }
- }
- }
- }
-
- # Tries to recover from broker error and determines if we could continue
- #
- # @param error The error message.
- # @return 1 if we can continue to process messages, 0 if we should throw an error
- proc recover_from_broker_error {error} {
- if {$error == "Child process signal received."} {
- putdebug "Ignoring SIGCHLD"
- } elseif {[string match "*server connection error 320*CONNECTION_FORCED*" $error]} {
- # If the session doesn't allow the bot to process
- # messages, we can ask the server to disconnect it.
- # Log the error message, as management plugin
- # allows to send a custom reason.
- putdebug "$error / Trying to reconnect..."
- connect
- } elseif {$error == "Not connected."} {
- connect
- } else {
- return 0
- }
-
- return 1
- }
-
- proc bind {queue callback} {
- global brokerbinds
- set entry [list $queue $callback]
-
- if {[info exists brokerbinds]} {
- foreach bind $brokerbinds {
- if {$bind == $entry} {
- # Bind is already here
- return
- }
- }
- }
-
- lappend brokerbinds $entry
- }
-
- proc binds {} {
- global brokerbinds
-
- if {[info exists brokerbinds]} {
- return $brokerbinds
- }
-
- return ""
- }
-
- # Triggered when a message comes to the broker to dispatch it to bound procs
- proc on_message {queue message} {
- set propagated 0
- foreach bind [binds] {
- foreach "bindQueue callback" $bind {}
- if {[string match $bindQueue $queue]} {
- $callback $queue $message
- incr propagated
- }
- }
- if {$propagated == 0} {
- putdebug "\[Broker\] Not propagated: <$queue> [string range $message 0 64]..."
- }
- }
+ proc init {} {
+ # Loads our librabbitmq wrapper extension
+ if {![is_package_present rabbitmq]} {
+ load lib/rabbitmq.so
+ }
+
+ # Connects to the broker
+ if {![mq connected]} {
+ connect
+ }
+
+ # Starts timer
+ if {![is_timer_started]} {
+ start_timer
+ }
+ }
+
+ proc connect {} {
+ mq connect [registry get broker.host] [vault_get broker username] [vault_get broker password] [registry get broker.vhost]
+ }
+
+ proc is_timer_started {} {
+ expr [string first ::broker::on_tick [utimers]] > -1
+ }
+
+ proc start_timer {} {
+ utimer 4 [namespace current]::on_tick
+ }
+
+ # Determines if we're in a risk to receive a SIGCHLD while the broker intercepts signals
+ #
+ # @param time The specified unixtime, or the current one if omitted
+ # @return 1 if the risk is there, 0 if it shouldn't be risky
+ proc near_SIGCHLD_arrival {{time ""}} {
+ if {$time == ""} {
+ set time [clock seconds]
+ }
+ set timePosition [expr $time % 300]
+ expr $timePosition == 0 || $timePosition == 299
+ }
+
+ proc on_tick {} {
+ if {![near_SIGCHLD_arrival]} {
+ # We generally want to get messages, but not
+ # when the SIGCHLD signal is sent to the bot
+ # which seems to be every five minutes.
+
+ get_messages
+ }
+ utimer 1 [namespace current]::on_tick
+ }
+
+ proc get_messages {} {
+ foreach queue [registry get broker.queues] {
+ while 1 {
+ if {[catch {set message [mq get $queue -noack]} brokerError]} {
+ if {[recover_from_broker_error $brokerError]} {
+ continue
+ } {
+ error $brokerError
+ }
+ }
+ if {$message == ""} {
+ break
+ } {
+ on_message $queue $message
+ }
+ }
+ }
+ }
+
+ # Tries to recover from broker error and determines if we could continue
+ #
+ # @param error The error message.
+ # @return 1 if we can continue to process messages, 0 if we should throw an error
+ proc recover_from_broker_error {error} {
+ if {$error == "Child process signal received."} {
+ putdebug "Ignoring SIGCHLD"
+ } elseif {[string match "*server connection error 320*CONNECTION_FORCED*" $error]} {
+ # If the session doesn't allow the bot to process
+ # messages, we can ask the server to disconnect it.
+ # Log the error message, as management plugin
+ # allows to send a custom reason.
+ putdebug "$error / Trying to reconnect..."
+ connect
+ } elseif {$error == "Not connected."} {
+ connect
+ } else {
+ return 0
+ }
+
+ return 1
+ }
+
+ proc bind {queue callback} {
+ global brokerbinds
+ set entry [list $queue $callback]
+
+ if {[info exists brokerbinds]} {
+ foreach bind $brokerbinds {
+ if {$bind == $entry} {
+ # Bind is already here
+ return
+ }
+ }
+ }
+
+ lappend brokerbinds $entry
+ }
+
+ proc binds {} {
+ global brokerbinds
+
+ if {[info exists brokerbinds]} {
+ return $brokerbinds
+ }
+
+ return ""
+ }
+
+ # Triggered when a message comes to the broker to dispatch it to bound procs
+ proc on_message {queue message} {
+ set propagated 0
+ foreach bind [binds] {
+ foreach "bindQueue callback" $bind {}
+ if {[string match $bindQueue $queue]} {
+ $callback $queue $message
+ incr propagated
+ }
+ }
+ if {$propagated == 0} {
+ putdebug "\[Broker\] Not propagated: <$queue> [string range $message 0 64]..."
+ }
+ }
}
diff --git a/Wearg/Notifications.tcl b/Wearg/Notifications.tcl
--- a/Wearg/Notifications.tcl
+++ b/Wearg/Notifications.tcl
@@ -3,176 +3,176 @@
bind time - "30 *" ::notifications::channel_notify_periodics
namespace eval notifications {
- proc init {} {
- ::broker::bind [registry get broker.queue.notifications] ::notifications::on_broker_message
-
- bind * * * * ::notifications::channel_notify
- bind "DockerHub" * * * ::notifications::docker_build_summary
- }
-
- proc bind {service project group type callback} {
- global notificationsbinds
- set entry [list $service $project $group $type $callback]
-
- if {[info exists notificationsbinds]} {
- foreach bind $notificationsbinds {
- if {$bind == $entry} {
- # Bind is already here
- return
- }
- }
- }
-
- lappend notificationsbinds $entry
- }
-
- proc binds {} {
- global notificationsbinds
-
- if {[info exists notificationsbinds]} {
- return $notificationsbinds
- }
-
- return ""
- }
-
- proc is_matching_notification_bind {bind notification} {
- set bindFields "service project group type callback"
-
- # We want to ensure the first four bind fields match the values of the notification dictionary
- foreach $bindFields $bind {}
- set fields [lrange $bindFields 0 end-1]
- foreach field $fields {
- if {![string match [set $field] [dict get $notification $field]]} {
- return 0
- }
- }
-
- return 1
- }
-
- proc on_broker_message {queue message} {
- set notification [json::json2dict $message]
- set message [dict get $notification text]
-
- foreach field "service project group rawContent type text link" {
- lappend params [dict get $notification $field]
- }
-
- set matchingBinds 0
- foreach bind [binds] {
- if {[is_matching_notification_bind $bind $notification]} {
- set callback [lindex $bind 4]
- $callback {*}$params
- incr matchingBinds
- }
- }
- if {$matchingBinds == 0} {
- putdebug "No bind for queue $queue message $message"
- }
- }
-
- proc get_projects {} {
- registry get notifications.projects
- }
-
- proc get_notification_channel {project group} {
- if {$project == "Wolfplex"} {
- return "#wolfplex"
- }
- if {$project == "TrustSpace"} {
- return "#wolfplex"
- }
- if {$project == "Keruald"} {
- return "#nasqueron-logs"
- }
- if {$project == "Nasqueron"} {
- switch $group {
- eglide { return "#eglide" }
- tasacora { return "#tasacora" }
- trustspace { return "#wolfplex" }
- docker { return "#nasqueron-ops" }
- ops { return "#nasqueron-ops" }
- orgz { return "#nasqueron-ops" }
- devtools { return "#nasqueron-logs" }
- nasqueron { return "#nasqueron-logs" }
- default {
- putdebug "Message for unknown group: $project $group"
- return "#nasqueron-logs"
- }
- }
- }
- return ""
- }
-
- proc get_image_from_docker_payload {payload} {
- set repository [dict get $payload repository]
- dict get $repository repo_name
- }
-
- proc docker_build_summary {service project group rawContent type text link} {
- if {$service != "DockerHub" || $type != "push"} {
- return
- }
-
- set image [get_image_from_docker_payload $rawContent]
- set key notifications.periodics.docker.$project
-
- set periodicsNotifications [registry get $key]
- dict incr periodicsNotifications $image
- registry set $key $periodicsNotifications
- }
-
- proc channel_notify_periodics {minutes hours day month year} {
- foreach project [get_projects] {
- channel_notify_periodics_for_project $project
- }
- }
-
- proc docker_format_builds {builds} {
- set first 1
- foreach "image count" $builds {
- lappend list "$image (${count}x)"
- }
- join $list ", "
- }
-
- proc channel_notify_periodics_for_project {project} {
- set key notifications.periodics.docker.$project
- set builds [registry get $key]
- if {$builds == ""} {
- return
- }
-
- set channel [get_notification_channel $project docker]
- putquick "PRIVMSG $channel :New images pushed to Docker Hub: [docker_format_builds $builds]"
- registry delete $key
- }
-
- proc channel_notify {service project group rawContent type text link} {
- # T790 - Ignores Docker Hub notification in real time to offer a summary instead
- if {$service == "DockerHub"} {
- return
- }
-
- # T1253 - Some events produce "null text"
- if {$text == "null"} {
- set routingKey "$project.$group.$service.$type"
- putdebug "Message 'null' received for $routingKey notification:"
- putdebug $rawContent
- return
- }
-
- set channel [get_notification_channel $project $group]
- if {$channel == ""} {
- return
- }
-
- set message $text
- if {$link != ""} {
- append message " — $link"
- }
-
- putquick "PRIVMSG $channel :$message"
- }
+ proc init {} {
+ ::broker::bind [registry get broker.queue.notifications] ::notifications::on_broker_message
+
+ bind * * * * ::notifications::channel_notify
+ bind "DockerHub" * * * ::notifications::docker_build_summary
+ }
+
+ proc bind {service project group type callback} {
+ global notificationsbinds
+ set entry [list $service $project $group $type $callback]
+
+ if {[info exists notificationsbinds]} {
+ foreach bind $notificationsbinds {
+ if {$bind == $entry} {
+ # Bind is already here
+ return
+ }
+ }
+ }
+
+ lappend notificationsbinds $entry
+ }
+
+ proc binds {} {
+ global notificationsbinds
+
+ if {[info exists notificationsbinds]} {
+ return $notificationsbinds
+ }
+
+ return ""
+ }
+
+ proc is_matching_notification_bind {bind notification} {
+ set bindFields "service project group type callback"
+
+ # We want to ensure the first four bind fields match the values of the notification dictionary
+ foreach $bindFields $bind {}
+ set fields [lrange $bindFields 0 end-1]
+ foreach field $fields {
+ if {![string match [set $field] [dict get $notification $field]]} {
+ return 0
+ }
+ }
+
+ return 1
+ }
+
+ proc on_broker_message {queue message} {
+ set notification [json::json2dict $message]
+ set message [dict get $notification text]
+
+ foreach field "service project group rawContent type text link" {
+ lappend params [dict get $notification $field]
+ }
+
+ set matchingBinds 0
+ foreach bind [binds] {
+ if {[is_matching_notification_bind $bind $notification]} {
+ set callback [lindex $bind 4]
+ $callback {*}$params
+ incr matchingBinds
+ }
+ }
+ if {$matchingBinds == 0} {
+ putdebug "No bind for queue $queue message $message"
+ }
+ }
+
+ proc get_projects {} {
+ registry get notifications.projects
+ }
+
+ proc get_notification_channel {project group} {
+ if {$project == "Wolfplex"} {
+ return "#wolfplex"
+ }
+ if {$project == "TrustSpace"} {
+ return "#wolfplex"
+ }
+ if {$project == "Keruald"} {
+ return "#nasqueron-logs"
+ }
+ if {$project == "Nasqueron"} {
+ switch $group {
+ eglide { return "#eglide" }
+ tasacora { return "#tasacora" }
+ trustspace { return "#wolfplex" }
+ docker { return "#nasqueron-ops" }
+ ops { return "#nasqueron-ops" }
+ orgz { return "#nasqueron-ops" }
+ devtools { return "#nasqueron-logs" }
+ nasqueron { return "#nasqueron-logs" }
+ default {
+ putdebug "Message for unknown group: $project $group"
+ return "#nasqueron-logs"
+ }
+ }
+ }
+ return ""
+ }
+
+ proc get_image_from_docker_payload {payload} {
+ set repository [dict get $payload repository]
+ dict get $repository repo_name
+ }
+
+ proc docker_build_summary {service project group rawContent type text link} {
+ if {$service != "DockerHub" || $type != "push"} {
+ return
+ }
+
+ set image [get_image_from_docker_payload $rawContent]
+ set key notifications.periodics.docker.$project
+
+ set periodicsNotifications [registry get $key]
+ dict incr periodicsNotifications $image
+ registry set $key $periodicsNotifications
+ }
+
+ proc channel_notify_periodics {minutes hours day month year} {
+ foreach project [get_projects] {
+ channel_notify_periodics_for_project $project
+ }
+ }
+
+ proc docker_format_builds {builds} {
+ set first 1
+ foreach "image count" $builds {
+ lappend list "$image (${count}x)"
+ }
+ join $list ", "
+ }
+
+ proc channel_notify_periodics_for_project {project} {
+ set key notifications.periodics.docker.$project
+ set builds [registry get $key]
+ if {$builds == ""} {
+ return
+ }
+
+ set channel [get_notification_channel $project docker]
+ putquick "PRIVMSG $channel :New images pushed to Docker Hub: [docker_format_builds $builds]"
+ registry delete $key
+ }
+
+ proc channel_notify {service project group rawContent type text link} {
+ # T790 - Ignores Docker Hub notification in real time to offer a summary instead
+ if {$service == "DockerHub"} {
+ return
+ }
+
+ # T1253 - Some events produce "null text"
+ if {$text == "null"} {
+ set routingKey "$project.$group.$service.$type"
+ putdebug "Message 'null' received for $routingKey notification:"
+ putdebug $rawContent
+ return
+ }
+
+ set channel [get_notification_channel $project $group]
+ if {$channel == ""} {
+ return
+ }
+
+ set message $text
+ if {$link != ""} {
+ append message " — $link"
+ }
+
+ putquick "PRIVMSG $channel :$message"
+ }
}
diff --git a/Wearg/Time.tcl b/Wearg/Time.tcl
--- a/Wearg/Time.tcl
+++ b/Wearg/Time.tcl
@@ -6,16 +6,16 @@
#bind cron - "0 4 * * *" cron:daily
proc onload {} {
- ::broker::init
- ::notifications::init
+ ::broker::init
+ ::notifications::init
}
#Every 5 minutes
proc cron:often {minute hour day month weekday} {
- #Reconnects to broker
- if {[mq connected]} {
- mq disconnect
- }
+ #Reconnects to broker
+ if {[mq connected]} {
+ mq disconnect
+ }
}
#Every hour
diff --git a/tests/Core.test b/tests/Core.test
--- a/tests/Core.test
+++ b/tests/Core.test
@@ -12,73 +12,73 @@
###
test strlen_regular_string {} -body {
- strlen "quux"
+ strlen "quux"
} -result 4
test strlen_empty_string {} -body {
- strlen ""
+ strlen ""
} -result 0
test strlenmax {} -body {
- strlenmax "a aa alpha beta gamma delta omega"
+ strlenmax "a aa alpha beta gamma delta omega"
} -result 5
test strlenmax_empty_words {} -body {
- strlenmax [list "" "" "" ""]
+ strlenmax [list "" "" "" ""]
} -result 0
test strlenmax_empty_list_one_empty_word {} -body {
- strlenmax {""}
+ strlenmax {""}
} -result 0
test strlenmax_empty_list {} -body {
- strlenmax {}
+ strlenmax {}
} -result 0
test strlenmap {} -body {
- strlenmap "a aa aaa aa a"
+ strlenmap "a aa aaa aa a"
} -result "1 2 3 2 1"
test lmax {} -body {
- lmax "7 10 1 20 11 4 3"
+ lmax "7 10 1 20 11 4 3"
} -result 20
test lmin {} -body {
- lmin "7 10 1 20 11 4 3"
+ lmin "7 10 1 20 11 4 3"
} -result 1
test lmax_from_an_empty_list {
- When there is no numeric value, nothing should be returned
+ When there is no numeric value, nothing should be returned
} -body {
- lmax ""
+ lmax ""
} -result ""
test lmax_from_an_words_list {
- When there is no numeric value, nothing should be returned
+ When there is no numeric value, nothing should be returned
} -body {
- lmax "alpha beta gamma"
+ lmax "alpha beta gamma"
} -result ""
test lmax_from_a_mixed_list {
- Non numeric numbers should be ignored
+ Non numeric numbers should be ignored
} -body {
- lmax "7 10 1 20 notanumber 11 4 3"
+ lmax "7 10 1 20 notanumber 11 4 3"
} -result 20
test zeroornumber_from_integer {} -body {
- zeroornumber 4
+ zeroornumber 4
} -result 4
test zeroornumber_from_non_numeric_string {} -body {
- zeroornumber "alpha"
+ zeroornumber "alpha"
} -result 0
test zeroornumber_from_zero {} -body {
- zeroornumber 0
+ zeroornumber 0
} -result 0
test zeroornumber_from_empty_list {} -body {
- zeroornumber ""
+ zeroornumber ""
} -result 0
###
diff --git a/tests/ServersLog.test b/tests/ServersLog.test
--- a/tests/ServersLog.test
+++ b/tests/ServersLog.test
@@ -14,15 +14,15 @@
###
proc registry {command key {value ""}} {
- if {$command == "get" && $key == "serverslog.knowncomponents"} {
- return "Alpha Beta"
- }
+ if {$command == "get" && $key == "serverslog.knowncomponents"} {
+ return "Alpha Beta"
+ }
- if {$command == "get" && $key == "serverslog.knownnotcomponents"} {
- return "{GSoC Mentors}"
- }
+ if {$command == "get" && $key == "serverslog.knownnotcomponents"} {
+ return "{GSoC Mentors}"
+ }
- error "Unexpected registry call: $command $key $value"
+ error "Unexpected registry call: $command $key $value"
}
###
@@ -30,39 +30,39 @@
###
test is_known_component_when_known {} -body {
- is_known_component Alpha
+ is_known_component Alpha
} -result 1
test is_known_component_when_known_parent {} -body {
- is_known_component Beta/Delta
+ is_known_component Beta/Delta
} -result 1
test is_known_component_with_trailing_slash {} -body {
- is_known_component Beta/
+ is_known_component Beta/
} -result 0
test is_known_component_when_unknown {} -body {
- is_known_component Gamma
+ is_known_component Gamma
} -result 0
test could_be_a_component_with_date {} -body {
- could_be_a_component "15-Apr-2018 21:37:42 UTC"
+ could_be_a_component "15-Apr-2018 21:37:42 UTC"
} -result 0
test could_be_a_component_with_time {} -body {
- could_be_a_component "1905495.738522"
+ could_be_a_component "1905495.738522"
} -result 0
test could_be_a_component_with_time_in_log {} -body {
- could_be_a_component " 0.528573"
+ could_be_a_component " 0.528573"
} -result 0
test could_be_a_component_with_server_name {} -body {
- could_be_a_component "Ysul"
+ could_be_a_component "Ysul"
} -result 1
test could_be_a_component_with_mailing_list_prefix {} -body {
- could_be_a_component "GSoC Mentors"
+ could_be_a_component "GSoC Mentors"
} -result 0
###
diff --git a/tests/Tech.test b/tests/Tech.test
--- a/tests/Tech.test
+++ b/tests/Tech.test
@@ -14,19 +14,19 @@
###
test should_log_tcl_command_for_legit_command {} -body {
- should_log_tcl_command "quux"
+ should_log_tcl_command "quux"
} -result 1
test should_log_tcl_command_for_empty_command {} -body {
- should_log_tcl_command ""
+ should_log_tcl_command ""
} -result 1
test should_log_tcl_command_for_sql_connect {} -body {
- should_log_tcl_command "sql connect localhost root somepassword"
+ should_log_tcl_command "sql connect localhost root somepassword"
} -result 0
test should_log_tcl_command_for_genpass {} -body {
- should_log_tcl_command "genpass somepassword somedomain.tld"
+ should_log_tcl_command "genpass somepassword somedomain.tld"
} -result 0
###
diff --git a/tests/init.tcl b/tests/init.tcl
--- a/tests/init.tcl
+++ b/tests/init.tcl
@@ -5,10 +5,10 @@
# Tests config
set dir [info script]
if {$dir == ""} {
- set dir [pwd]
- append dir "/scripts"
+ set dir [pwd]
+ append dir "/scripts"
} {
- set dir [file dirname [file dirname [file normalize $dir]]]
+ set dir [file dirname [file dirname [file normalize $dir]]]
}
# Standard procedures

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 22, 14:32 (20 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3550410
Default Alt Text
D4012.diff (179 KB)

Event Timeline