1 <?php |
1 <?php |
2 |
2 |
3 // most of the code in here goes towards keeping track of the list of members currently in the various channels we're in. |
3 require('statsincludes/stats_core.php'); |
|
4 require('statsincludes/stats_logger.php'); |
|
5 require('statsincludes/stats_frontend.php'); |
4 |
6 |
5 $stats_memberlist = array(); |
|
6 $stats_prefixes = array( |
|
7 'o' => '@', |
|
8 'v' => '+' |
|
9 ); |
|
10 $stats_data = array('anonymous' => array(), 'messages' => array()); |
|
11 $stats_day = gmdate('Ymd'); |
|
12 @include("./stats/stats-data-$stats_day.php"); |
|
13 unset($stats_data['members']); |
|
14 $stats_data['members'] =& $stats_memberlist; |
|
15 |
|
16 eb_hook('event_self_join', 'stats_init_channel($this);'); |
|
17 eb_hook('event_raw_message', 'stats_process_message($chan, $message);'); |
|
18 eb_hook('snippet_dynamic', 'if ( $snippet === "memberlist" ) return stats_list_members($chan, $message); if ( $snippet === "deluser" ) return stats_del_user($chan, $message);'); |
|
19 eb_hook('event_other', 'stats_handle_other_event($message);'); |
|
20 eb_hook('event_privmsg', 'stats_handle_privmsg($message);'); |
|
21 |
|
22 function stats_init_channel(&$chan) |
|
23 { |
|
24 global $stats_memberlist, $stats_prefixes, $stats_data; |
|
25 |
|
26 $channel_name = $chan->get_channel_name(); |
|
27 $stats_memberlist[$channel_name] = array(); |
|
28 $prefixes_regexp = '/^([' . preg_quote(implode('', $stats_prefixes)) . '])+/'; |
|
29 $prefixes_flipped = array_flip($stats_prefixes); |
|
30 $prefixes_regexp_notlist = '/[^' . preg_quote(implode('', $prefixes_flipped)) . ']/'; |
|
31 |
|
32 if ( !isset($stats_data['messages'][$channel_name]) ) |
|
33 { |
|
34 $stats_data['messages'][$channel_name] = array(); |
|
35 } |
|
36 |
|
37 // read list of members from channel |
|
38 @stream_set_timeout($chan->parent->sock, 3); |
|
39 while ( $msg = $chan->parent->get() ) |
|
40 { |
|
41 if ( $ml = strstr($msg, ' 353 ') ) |
|
42 { |
|
43 $memberlist = trim(substr(strstr($ml, ':'), 1)); |
|
44 $stats_memberlist[$channel_name] = explode(' ', $memberlist); |
|
45 $stats_memberlist[$channel_name] = array_flip($stats_memberlist[$channel_name]); |
|
46 foreach ( $stats_memberlist[$channel_name] as $nick => $_ ) |
|
47 { |
|
48 $stats_memberlist[$channel_name][$nick] = ''; |
|
49 while ( preg_match($prefixes_regexp, $nick) ) |
|
50 { |
|
51 $prefix = substr($nick, 0, 1); |
|
52 $add = preg_replace($prefixes_regexp_notlist, '', strval($stats_memberlist[$channel_name][$nick])); |
|
53 unset($stats_memberlist[$channel_name][$nick]); |
|
54 $nick = substr($nick, 1); |
|
55 $stats_memberlist[$channel_name][$nick] = $prefixes_flipped[$prefix] . $add; |
|
56 } |
|
57 } |
|
58 break; |
|
59 } |
|
60 } |
|
61 } |
|
62 |
|
63 function stats_process_message(&$chan, $message) |
|
64 { |
|
65 global $stats_memberlist, $stats_data; |
|
66 $channel_name = $chan->get_channel_name(); |
|
67 if ( !isset($stats_memberlist[$channel_name]) ) |
|
68 { |
|
69 return false; |
|
70 } |
|
71 |
|
72 $ml =& $stats_memberlist[$channel_name]; |
|
73 |
|
74 // we need to change statistics accordingly depending on the event |
|
75 if ( $message['action'] == 'JOIN' ) |
|
76 { |
|
77 // member joined - init their flags and up the member count by one |
|
78 $ml[$message['nick']] = ''; |
|
79 } |
|
80 else if ( $message['action'] == 'PART' ) |
|
81 { |
|
82 // member left - clear flags and decrement the total member count |
|
83 unset($ml[$message['nick']]); |
|
84 $ml = array_values($ml); |
|
85 } |
|
86 else if ( $message['action'] == 'MODE' ) |
|
87 { |
|
88 // update member list (not sure why this would be useful, but export it anyway - display scripts might find it useful) |
|
89 list($mode, $target) = explode(' ', $message['message']); |
|
90 $action = substr($mode, 0, 1); |
|
91 |
|
92 global $stats_prefixes; |
|
93 $ml[$target] = str_replace(substr($mode, 1), '', $ml[$target]); |
|
94 if ( $action == '+' ) |
|
95 { |
|
96 $ml[$target] .= substr($mode, 1); |
|
97 } |
|
98 } |
|
99 else if ( $message['action'] == 'PRIVMSG' ) |
|
100 { |
|
101 // private message into $channel_name - mark the user active and log the message time |
|
102 if ( isset($stats_data['anonymous'][$message['nick']]) ) |
|
103 $message['nick'] = 'Anonymous'; |
|
104 |
|
105 $messages =& $stats_data['messages'][$channel_name]; |
|
106 |
|
107 $messages[] = array( |
|
108 'time' => time(), |
|
109 'nick' => $message['nick'] |
|
110 ); |
|
111 } |
|
112 |
|
113 stats_cron(); |
|
114 } |
|
115 |
|
116 function stats_list_members(&$chan, &$message) |
|
117 { |
|
118 global $stats_memberlist; |
|
119 $channel_name = $chan->get_channel_name(); |
|
120 if ( !isset($stats_memberlist[$channel_name]) ) |
|
121 { |
|
122 return false; |
|
123 } |
|
124 |
|
125 $ml =& $stats_memberlist[$channel_name]; |
|
126 |
|
127 $chan->parent->privmsg($message['nick'], "memberlist:\n" . str_replace("\n", ' ', print_r($ml, true))); |
|
128 |
|
129 return true; |
|
130 } |
|
131 |
|
132 function stats_del_user(&$chan, &$message) |
|
133 { |
|
134 global $stats_memberlist, $privileged_list, $irc, $stats_data; |
|
135 |
|
136 // remove a user from the DB |
|
137 $targetuser = trim(substr(strstr($message['message'], '|'), 1)); |
|
138 if ( empty($targetuser) ) |
|
139 $targetuser = $message['nick']; |
|
140 |
|
141 if ( $targetuser != $message['nick'] && !in_array($message['nick'], $privileged_list) ) |
|
142 { |
|
143 $irc->privmsg($message['nick'], "Sorry, you need to be a moderator to delete statistics for users other than yourself."); |
|
144 return true; |
|
145 } |
|
146 |
|
147 // we should be good - delete the user |
|
148 foreach ( $stats_data['messages'] as $channel => &$messages ) |
|
149 { |
|
150 foreach ( $messages as $i => &$currentmessage ) |
|
151 { |
|
152 if ( $currentmessage['nick'] == $targetuser ) |
|
153 { |
|
154 unset($messages[$i]); |
|
155 } |
|
156 } |
|
157 $messages = array_values($messages); |
|
158 } |
|
159 unset($users, $currentmessage, $messages); |
|
160 |
|
161 global $nick; |
|
162 $greeting = ( $targetuser == $message['nick'] ) ? "All of your statistics data" : "All of {$targetuser}'s statistic data"; |
|
163 $irc->privmsg($message['nick'], "$greeting has been removed from the database for all channels. The changes will show up in the next commit to disk, which is usually no more than once every two minutes."); |
|
164 $irc->privmsg($message['nick'], "Want your stats to be anonymized in the future? Type /msg $nick anonymize to make me keep all your stats anonymous in the future. This only applies to your current nick though - for example if you change your nick to \"{$message['nick']}|sleep\" or similar your information will not be anonymous."); |
|
165 $irc->privmsg($message['nick'], "You can't clear your logs if you're anonymous. Type /msg $nick denonymize to remove yourself from the anonymization list. Anonymized logs can't be converted back to their original nicks."); |
|
166 |
|
167 return true; |
|
168 } |
|
169 |
|
170 function stats_handle_privmsg(&$message) |
|
171 { |
|
172 global $irc, $stats_data, $nick; |
|
173 static $poll_list = array(); |
|
174 |
|
175 $message['message'] = strtolower($message['message']); |
|
176 |
|
177 if ( trim($message['message']) === 'anonymize' ) |
|
178 { |
|
179 $stats_data['anonymous'][$message['nick']] = true; |
|
180 $poll_list[$message['nick']] = true; |
|
181 $irc->privmsg($message['nick'], "Anonymization complete. Any further statistics recorded about you will be anonymous."); |
|
182 $irc->privmsg($message['nick'], "Do you want to also anonymize any past statistics about you? (type \"yes\" or \"no\")"); |
|
183 } |
|
184 else if ( trim($message['message']) === 'denonymize' ) |
|
185 { |
|
186 $stats_data['anonymous'][$message['nick']] = false; |
|
187 unset($stats_data['anonymous'][$message['nick']]); |
|
188 $irc->privmsg($message['nick'], "Denonymization complete. Any further statistics recorded about you will bear your nick. Remember that you can always change this with /msg $nick anonymize."); |
|
189 } |
|
190 else if ( trim($message['message']) === 'yes' && isset($poll_list[$message['nick']]) ) |
|
191 { |
|
192 // anonymize logs for this user |
|
193 // we should be good - delete the user |
|
194 $targetuser = $message['nick']; |
|
195 |
|
196 foreach ( $stats_data['messages'] as $channel => &$messages ) |
|
197 { |
|
198 foreach ( $messages as $i => &$currentmessage ) |
|
199 { |
|
200 if ( $currentmessage['nick'] == $targetuser ) |
|
201 { |
|
202 $currentmessage['nick'] = 'Anonymous'; |
|
203 } |
|
204 } |
|
205 $messages = array_values($messages); |
|
206 } |
|
207 unset($users, $currentmessage, $messages); |
|
208 $irc->privmsg($message['nick'], "Anonymization complete. All past statistics on your nick are now anonymous."); |
|
209 |
|
210 unset($poll_list[$message['nick']]); |
|
211 } |
|
212 stats_cron(); |
|
213 } |
|
214 |
|
215 function stats_handle_other_event(&$message) |
|
216 { |
|
217 global $stats_memberlist; |
|
218 |
|
219 if ( $message['action'] == 'NICK' ) |
|
220 { |
|
221 // we have a nick change; go through all channels and replace the old nick with the new |
|
222 foreach ( $stats_memberlist as &$ml ) |
|
223 { |
|
224 if ( isset($ml[$message['nick']]) ) |
|
225 { |
|
226 $ml[$message['message']] = $ml[$message['nick']]; |
|
227 unset($ml[$message['nick']]); |
|
228 } |
|
229 } |
|
230 } |
|
231 stats_cron(); |
|
232 } |
|
233 |
|
234 function stats_cron() |
|
235 { |
|
236 static $commit_time = 0; |
|
237 $now = time(); |
|
238 // commit to disk every 1 minute |
|
239 if ( $commit_time + 60 < $now ) |
|
240 { |
|
241 $commit_time = $now; |
|
242 stats_commit(); |
|
243 } |
|
244 } |
|
245 |
|
246 function stats_commit() |
|
247 { |
|
248 global $stats_data, $stats_day; |
|
249 |
|
250 ob_start(); |
|
251 var_export($stats_data); |
|
252 $stats_data_exported = ob_get_contents(); |
|
253 ob_end_clean(); |
|
254 |
|
255 $fp = @fopen("./stats/stats-data-$stats_day.php", 'w'); |
|
256 if ( !$fp ) |
|
257 return false; |
|
258 fwrite($fp, "<?php\n\$stats_data = $stats_data_exported;\n"); |
|
259 fclose($fp); |
|
260 |
|
261 if ( $stats_day != gmdate('Ymd') ) |
|
262 { |
|
263 // it's a new day! flush all our logs |
|
264 foreach ( $stats_data['messages'] as &$data ) |
|
265 { |
|
266 $data = array(); |
|
267 } |
|
268 } |
|
269 |
|
270 $stats_day = gmdate('Ymd'); |
|
271 } |
|
272 |
|