| 1 | # ============================================= |
1 | # ============================================= |
| 2 | # !tell script for Eggdrop |
2 | # !tell script for Eggdrop |
| 3 | # Usage: !tell <nick> <message> |
3 | # Usage: !tell <nick> <message> |
| 4 | # Admin: /msg <bot> !cleartell (bot owners only) |
4 | # Admin: /msg <bot> !cleartell (bot owners only) |
| 5 | # ============================================= |
5 | # ============================================= |
| 6 | 6 | ||
| 7 | namespace eval tell { |
7 | namespace eval tell { |
| 8 | variable tellfile "scripts/tell.db" ;# storage file (relative to the eggdrop dir) |
8 | variable tellfile "scripts/tell.db" ;# storage file (relative to the eggdrop dir) |
| 9 | variable maxpending 10 ;# max queued messages per nick (0 = unlimited) |
9 | variable maxpending 10 ;# max queued messages per nick (0 = unlimited) |
| 10 | variable messages |
10 | variable messages |
| 11 | array set messages {} |
11 | array set messages {} |
| 12 | 12 | ||
| 13 | # Load queued messages from disk |
13 | # Load queued messages from disk |
| 14 | proc load {} { |
14 | proc load {} { |
| 15 | variable messages |
15 | variable messages |
| 16 | variable tellfile |
16 | variable tellfile |
| 17 | array unset messages |
17 | array unset messages |
| 18 | array set messages {} |
18 | array set messages {} |
| 19 | if {![file exists $tellfile]} { return } |
19 | if {![file exists $tellfile]} { return } |
| 20 | if {[catch {open $tellfile r} fd]} { |
20 | if {[catch {open $tellfile r} fd]} { |
| 21 | putlog "tell.tcl: cannot read $tellfile: $fd" |
21 | putlog "tell.tcl: cannot read $tellfile: $fd" |
| 22 | return |
22 | return |
| 23 | } |
23 | } |
| 24 | fconfigure $fd -encoding utf-8 |
24 | fconfigure $fd -encoding utf-8 |
| 25 | while {[gets $fd line] >= 0} { |
25 | while {[gets $fd line] >= 0} { |
| 26 | if {[string trim $line] eq ""} { continue } |
26 | if {[string trim $line] eq ""} { continue } |
| 27 | # each line is a clean Tcl list: target sender time message |
27 | # each line is a clean Tcl list: target sender time message |
| 28 | if {[catch {lassign $line target sender time message}]} { continue } |
28 | if {[catch {lassign $line target sender time message}]} { continue } |
| 29 | if {$target eq ""} { continue } |
29 | if {$target eq ""} { continue } |
| 30 | lappend messages([string tolower $target]) [list $sender $time $message] |
30 | lappend messages([string tolower $target]) [list $sender $time $message] |
| 31 | } |
31 | } |
| 32 | close $fd |
32 | close $fd |
| 33 | } |
33 | } |
| 34 | 34 | ||
| 35 | # Persist queued messages to disk |
35 | # Persist queued messages to disk |
| 36 | proc save {} { |
36 | proc save {} { |
| 37 | variable messages |
37 | variable messages |
| 38 | variable tellfile |
38 | variable tellfile |
| 39 | if {[catch {open $tellfile w} fd]} { |
39 | if {[catch {open $tellfile w} fd]} { |
| 40 | putlog "tell.tcl: cannot write $tellfile: $fd" |
40 | putlog "tell.tcl: cannot write $tellfile: $fd" |
| 41 | return |
41 | return |
| 42 | } |
42 | } |
| 43 | fconfigure $fd -encoding utf-8 |
43 | fconfigure $fd -encoding utf-8 |
| 44 | foreach target [array names messages] { |
44 | foreach target [array names messages] { |
| 45 | foreach m $messages($target) { |
45 | foreach m $messages($target) { |
| 46 | lassign $m sender time message |
46 | lassign $m sender time message |
| 47 | puts $fd [list $target $sender $time $message] |
47 | puts $fd [list $target $sender $time $message] |
| 48 | } |
48 | } |
| 49 | } |
49 | } |
| 50 | close $fd |
50 | close $fd |
| 51 | } |
51 | } |
| 52 | 52 | ||
| 53 | – # !tell <nick> <message> |
53 | + # !tell <nick> <message> |
| 54 | proc do_tell {nick uhost hand chan text} { |
54 | proc do_tell {nick uhost hand chan text} { |
| 55 | variable messages |
55 | variable messages |
| 56 | variable maxpending |
56 | variable maxpending |
| 57 | if {![regexp {^\s*(\S+)\s+(.+)$} $text -> target message]} { |
57 | if {![regexp {^\s*(\S+)\s+(.+)$} $text -> target message]} { |
| 58 | puthelp "PRIVMSG $chan :Usage: !tell <nick> <message>" |
58 | puthelp "PRIVMSG $chan :Usage: !tell <nick> <message>" |
| 59 | return |
59 | return |
| 60 | } |
60 | } |
| 61 | set message [string trim $message] |
61 | set message [string trim $message] |
| 62 | set ltarget [string tolower $target] |
62 | set ltarget [string tolower $target] |
| 63 | if {$maxpending > 0 && [info exists messages($ltarget)] \ |
63 | if {$maxpending > 0 && [info exists messages($ltarget)] \ |
| 64 | && [llength $messages($ltarget)] >= $maxpending} { |
64 | && [llength $messages($ltarget)] >= $maxpending} { |
| 65 | puthelp "PRIVMSG $chan :$nick: $target already has $maxpending messages waiting - try again later." |
65 | puthelp "PRIVMSG $chan :$nick: $target already has $maxpending messages waiting - try again later." |
| 66 | return |
66 | return |
| 67 | } |
67 | } |
| 68 | set timestamp [clock format [clock seconds] -gmt 1 -format "%d/%m %H:%M GMT"] |
68 | set timestamp [clock format [clock seconds] -gmt 1 -format "%d/%m %H:%M GMT"] |
| 69 | lappend messages($ltarget) [list $nick $timestamp $message] |
69 | lappend messages($ltarget) [list $nick $timestamp $message] |
| 70 | save |
70 | save |
| 71 | puthelp "PRIVMSG $chan :$nick: noted. $target will be told the next time they're around." |
71 | puthelp "PRIVMSG $chan :$nick: noted. $target will be told the next time they're around." |
| 72 | } |
72 | } |
| 73 | 73 | ||
| 74 | # Deliver queued messages (on join or when the user speaks) |
74 | # Deliver queued messages (on join or when the user speaks) |
| 75 | proc deliver {nick uhost hand chan {text ""}} { |
75 | proc deliver {nick uhost hand chan {text ""}} { |
| 76 | variable messages |
76 | variable messages |
| 77 | set lnick [string tolower $nick] |
77 | set lnick [string tolower $nick] |
| 78 | if {![info exists messages($lnick)] || [llength $messages($lnick)] == 0} { |
78 | if {![info exists messages($lnick)] || [llength $messages($lnick)] == 0} { |
| 79 | return |
79 | return |
| 80 | } |
80 | } |
| 81 | foreach m $messages($lnick) { |
81 | foreach m $messages($lnick) { |
| 82 | lassign $m sender time message |
82 | lassign $m sender time message |
| 83 | – puthelp "PRIVMSG $chan :$nick: $sender left you a message on $time - $message" |
83 | + puthelp "NOTICE $nick :$sender left you a message on $time - $message" |
| 84 | } |
84 | } |
| 85 | unset messages($lnick) |
85 | unset messages($lnick) |
| 86 | save |
86 | save |
| 87 | } |
87 | } |
| 88 | 88 | ||
| 89 | # !cleartell (owner only via private message) |
89 | # !cleartell (owner only via private message) |
| 90 | proc clear_tells {nick uhost hand text} { |
90 | proc clear_tells {nick uhost hand text} { |
| 91 | variable messages |
91 | variable messages |
| 92 | set n 0 |
92 | set n 0 |
| 93 | foreach t [array names messages] { incr n [llength $messages($t)] } |
93 | foreach t [array names messages] { incr n [llength $messages($t)] } |
| 94 | array unset messages |
94 | array unset messages |
| 95 | array set messages {} |
95 | array set messages {} |
| 96 | save |
96 | save |
| 97 | puthelp "PRIVMSG $nick :Cleared $n pending message(s)." |
97 | puthelp "PRIVMSG $nick :Cleared $n pending message(s)." |
| 98 | } |
98 | } |
| 99 | 99 | ||
| 100 | bind pub - "!tell" ::tell::do_tell |
100 | bind pub - "!tell" ::tell::do_tell |
| 101 | bind join - * ::tell::deliver |
101 | bind join - * ::tell::deliver |
| 102 | bind pubm - * ::tell::deliver ;# deliver when the user next speaks |
102 | bind pubm - * ::tell::deliver ;# deliver when the user next speaks |
| 103 | bind msg o "!cleartell" ::tell::clear_tells |
103 | bind msg o "!cleartell" ::tell::clear_tells |
| 104 | 104 | ||
| 105 | load |
105 | load |
| 106 | putlog "tell.tcl loaded - !tell system active" |
106 | putlog "tell.tcl loaded - !tell system active" |
| 107 | } |
107 | } |
| 108 | |||