1 | #! /usr/bin/env php |
||
2 | |||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
3 | <?php |
||
0 ignored issues
–
show
|
|||
4 | // This file is part of BOINC. |
||
5 | // http://boinc.berkeley.edu |
||
6 | // Copyright (C) 2008 University of California |
||
7 | // |
||
8 | // BOINC is free software; you can redistribute it and/or modify it |
||
9 | // under the terms of the GNU Lesser General Public License |
||
10 | // as published by the Free Software Foundation, |
||
11 | // either version 3 of the License, or (at your option) any later version. |
||
12 | // |
||
13 | // BOINC is distributed in the hope that it will be useful, |
||
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
16 | // See the GNU Lesser General Public License for more details. |
||
17 | // |
||
18 | // You should have received a copy of the GNU Lesser General Public License |
||
19 | // along with BOINC. If not, see <http://www.gnu.org/licenses/>. |
||
20 | |||
21 | // remind.php [--lapsed | --failed] [--show_email] [--userid ID] |
||
22 | // |
||
23 | // --lapsed |
||
24 | // Send emails to lapsed user (see below) |
||
25 | // --failed |
||
26 | // Send emails to failed user (see below) |
||
27 | // --userid |
||
28 | // Send both "lapsed" and "failed" emails to the given user, |
||
29 | // regardless of whether they are due to be sent. |
||
30 | // The --lapsed and --failed options are ignored. |
||
31 | // (for testing) |
||
32 | // --show_email |
||
33 | // Show the text that would be mailed |
||
34 | // --explain |
||
35 | // Show which users would be sent email and why |
||
36 | // --send |
||
37 | // Actually send emails (this is an option to encourage |
||
38 | // you to do thorough testing before using it) |
||
39 | // --count N |
||
40 | // By default send to all users that qualify, but if count is |
||
41 | // set, only send to N users at a time |
||
42 | // |
||
43 | // This program sends "reminder" emails to |
||
44 | // - failed users: those who |
||
45 | // 1) were created at least $start_interval seconds ago, |
||
46 | // 2) have zero total credit |
||
47 | // 3) haven't been sent an email in at least $email_interval seconds. |
||
48 | // These people typically either had a technical glitch, |
||
49 | // or their prefs didn't allow sending them work, |
||
50 | // or the app crashed on their host. |
||
51 | // The email should direct them to a web page that helps |
||
52 | // them fix the startup problem. |
||
53 | // |
||
54 | // Set $start_interval according to your project's delay bounds |
||
55 | // e.g. (1 or 2 weeks). |
||
56 | /// $email_interval should be roughly 1 month - |
||
57 | // we don't want to bother people too often. |
||
58 | // |
||
59 | // - lapsed users: those who |
||
60 | // 1) have positive total credit, |
||
61 | // 2) haven't done a scheduler RPC within the past |
||
62 | // $lapsed_interval seconds, and |
||
63 | // 3) haven't been sent an email in at least $email_interval seconds. |
||
64 | // The email should gently prod them to start running the project again. |
||
65 | // |
||
66 | |||
67 | $cli_only = true; |
||
68 | require_once("../inc/util_ops.inc"); |
||
69 | require_once("../inc/email.inc"); |
||
70 | |||
71 | db_init(); |
||
72 | set_time_limit(0); |
||
73 | |||
74 | $globals->start_interval = 14*86400; |
||
75 | $globals->email_interval = 200*86400; |
||
76 | $globals->lapsed_interval = 60*86400; |
||
77 | $globals->do_failed = false; |
||
78 | $globals->do_lapsed = false; |
||
79 | $globals->show_email = false; |
||
80 | $globals->send = false; |
||
81 | $globals->explain = false; |
||
82 | $globals->userid = 0; |
||
83 | $globals->count = -1; |
||
84 | |||
85 | for ($i=1; $i<$argc; $i++) { |
||
86 | if ($argv[$i] == "--failed") { |
||
87 | $globals->do_failed = true; |
||
88 | } elseif ($argv[$i] == "--lapsed") { |
||
89 | $globals->do_lapsed = true; |
||
90 | } elseif ($argv[$i] == "--show_email") { |
||
91 | $globals->show_email = true; |
||
92 | } elseif ($argv[$i] == "--explain") { |
||
93 | $globals->explain = true; |
||
94 | } elseif ($argv[$i] == "--send") { |
||
95 | $globals->send = true; |
||
96 | } elseif ($argv[$i] == "--userid") { |
||
97 | $i++; |
||
98 | $globals->userid = $argv[$i]; |
||
99 | } elseif ($argv[$i] == "--count") { |
||
100 | $i++; |
||
101 | $globals->count = $argv[$i]; |
||
102 | } else { |
||
103 | echo "unrecognized option $argv[$i]\n"; |
||
104 | echo "usage: remind.php [--failed ] [--lapsed] [--userid N] [--show_mail] [--explain] [--send] [--count N]\n"; |
||
105 | exit (1); |
||
106 | } |
||
107 | } |
||
108 | |||
109 | // File names for the various mail types. |
||
110 | // Change these here if needed. |
||
111 | // |
||
112 | $dir = "remind_email"; |
||
113 | $failed_html = "$dir/reminder_failed_html"; |
||
114 | $failed_text = "$dir/reminder_failed_text"; |
||
115 | $failed_subject = "$dir/reminder_failed_subject"; |
||
116 | $lapsed_html = "$dir/reminder_lapsed_html"; |
||
117 | $lapsed_text = "$dir/reminder_lapsed_text"; |
||
118 | $lapsed_subject = "$dir/reminder_lapsed_subject"; |
||
119 | |||
120 | // return time of last scheduler RPC from this user, |
||
121 | // or zero if they're never done one |
||
122 | // |
||
123 | function last_rpc_time($user) { |
||
124 | $x = 0; |
||
125 | $result = _mysql_query("select rpc_time from host where userid=$user->id"); |
||
126 | while ($host = _mysql_fetch_object($result)) { |
||
127 | if ($host->rpc_time > $x) $x = $host->rpc_time; |
||
128 | } |
||
129 | _mysql_free_result($result); |
||
130 | return $x; |
||
131 | } |
||
132 | |||
133 | function read_files(&$item) { |
||
134 | $item['html'] = @file_get_contents($item['html_file']); |
||
135 | if (!$item['html']) { |
||
0 ignored issues
–
show
This
if statement is empty and can be removed.
This check looks for the bodies of These if (rand(1, 6) > 3) {
//print "Check failed";
} else {
print "Check succeeded";
}
could be turned into if (rand(1, 6) <= 3) {
print "Check succeeded";
}
This is much more concise to read. ![]() |
|||
136 | //$x = $item['html_file']; |
||
137 | //echo "file missing: $x\n"; |
||
138 | //exit(); |
||
139 | } |
||
140 | $item['text'] = @file_get_contents($item['text_file']); |
||
141 | if (!$item['text']) { |
||
142 | $x = $item['text_file']; |
||
143 | echo "file missing: $x\n"; |
||
144 | exit(); |
||
0 ignored issues
–
show
|
|||
145 | } |
||
146 | $item['subject'] = @file_get_contents($item['subject']); |
||
147 | if (!$item['subject']) { |
||
148 | $x = $item['subject']; |
||
149 | echo "file missing: $x\n"; |
||
150 | exit(); |
||
0 ignored issues
–
show
|
|||
151 | } |
||
152 | } |
||
153 | |||
154 | function read_email_files() { |
||
155 | global $failed_html; |
||
156 | global $failed_text; |
||
157 | global $failed_subject; |
||
158 | global $lapsed_html; |
||
159 | global $lapsed_text; |
||
160 | global $lapsed_subject; |
||
161 | |||
162 | $failed['html_file'] = $failed_html; |
||
163 | $failed['text_file'] = $failed_text; |
||
164 | $failed['subject'] = $failed_subject; |
||
165 | $lapsed['html_file'] = $lapsed_html; |
||
166 | $lapsed['text_file'] = $lapsed_text; |
||
167 | $lapsed['subject'] = $lapsed_subject; |
||
168 | read_files($failed); |
||
169 | read_files($lapsed); |
||
170 | $email_files['failed'] = $failed; |
||
171 | $email_files['lapsed'] = $lapsed; |
||
172 | return $email_files; |
||
173 | } |
||
174 | |||
175 | function replace($user, $template) { |
||
176 | $pat = array( |
||
177 | '/<name\/>/', |
||
178 | '/<email\/>/', |
||
179 | '/<create_time\/>/', |
||
180 | '/<total_credit\/>/', |
||
181 | '/<opt_out_url\/>/', |
||
182 | '/<user_id\/>/', |
||
183 | '/<lapsed_interval\/>/', |
||
184 | ); |
||
185 | $rep = array( |
||
186 | $user->name, |
||
187 | $user->email_addr, |
||
188 | gmdate('d F Y', $user->create_time), |
||
189 | number_format($user->total_credit, 0), |
||
190 | opt_out_url($user), |
||
191 | $user->id, |
||
192 | floor ((time() - last_rpc_time($user)) / 86400), |
||
193 | ); |
||
194 | return preg_replace($pat, $rep, $template); |
||
195 | } |
||
196 | |||
197 | function mail_type($user, $type) { |
||
198 | global $globals; |
||
199 | global $email_files; |
||
200 | |||
201 | $email_file = $email_files[$type]; |
||
202 | if ($email_file['html']) { |
||
203 | $html = replace($user, $email_file['html']); |
||
204 | } else { |
||
205 | $html = null; |
||
206 | } |
||
207 | $text = replace($user, $email_file['text']); |
||
208 | if ($globals->show_email) { |
||
209 | echo "------- SUBJECT ----------\n"; |
||
210 | echo $email_file['subject']; |
||
211 | echo "\n------- HTML ----------\n"; |
||
212 | echo $html; |
||
213 | echo "\n------- TEXT ----------\n"; |
||
214 | echo $text; |
||
215 | } |
||
216 | if ($globals->send) { |
||
217 | echo "sending to $user->email_addr\n"; |
||
218 | echo send_email( |
||
219 | $user, |
||
220 | $email_file['subject'], |
||
221 | $text, |
||
222 | $html |
||
223 | ); |
||
224 | $now = time(); |
||
225 | $ntype = 0; |
||
226 | if ($type == 'lapsed') $ntype = 2; |
||
227 | if ($type == 'failed') $ntype = 3; |
||
228 | $query = "insert into sent_email values($user->id, $now, $ntype)"; |
||
229 | _mysql_query($query); |
||
230 | } |
||
231 | $globals->count--; |
||
232 | if ($globals->count == 0) { |
||
233 | echo "reached limit set by --count - exiting...\n"; |
||
234 | exit(); |
||
0 ignored issues
–
show
|
|||
235 | } |
||
236 | } |
||
237 | |||
238 | function last_reminder_time($user) { |
||
239 | $query = "select * from sent_email where userid=$user->id"; |
||
240 | $result = _mysql_query($query); |
||
241 | $t = 0; |
||
242 | while ($r = _mysql_fetch_object($result)) { |
||
243 | if ($r->email_type !=2 && $r->email_type != 3) continue; |
||
244 | if ($r->time_sent > $t) $t = $r->time_sent; |
||
245 | |||
246 | } |
||
247 | _mysql_free_result($result); |
||
248 | return $t; |
||
249 | } |
||
250 | |||
251 | function handle_user($user, $do_type) { |
||
252 | global $globals; |
||
253 | global $email_interval; |
||
254 | |||
255 | if ($user->send_email == 0) { |
||
256 | if ($globals->explain) { |
||
257 | echo "user: $user->id send_email = 0\n"; |
||
258 | } |
||
259 | return; |
||
260 | } |
||
261 | $max_email_time = time() - $globals->email_interval; |
||
262 | if (last_reminder_time($user) > $max_email_time) { |
||
263 | if ($globals->explain) { |
||
264 | echo "user: $user->id sent too recently\n"; |
||
265 | } |
||
266 | return; |
||
267 | } |
||
268 | if ($globals->explain) { |
||
269 | $x = (time() - $user->create_time)/86400; |
||
270 | $t = last_rpc_time($user); |
||
271 | $show_lapsed_interval = (time()-$t)/86400; |
||
272 | echo "user $user->id ($user->email_addr) was created $x days ago\n"; |
||
273 | echo " total_credit: $user->total_credit; last RPC $show_lapsed_interval days ago\n"; |
||
274 | echo " sending $do_type email\n"; |
||
275 | } |
||
276 | mail_type($user, $do_type); |
||
277 | } |
||
278 | |||
279 | function do_failed() { |
||
280 | global $globals; |
||
281 | |||
282 | $max_create_time = time() - $globals->start_interval; |
||
283 | $result = _mysql_query( |
||
284 | "select * from user where send_email<>0 and create_time<$max_create_time and total_credit = 0;" |
||
285 | ); |
||
286 | while ($user = _mysql_fetch_object($result)) { |
||
287 | handle_user($user, 'failed'); |
||
288 | } |
||
289 | _mysql_free_result($result); |
||
290 | } |
||
291 | |||
292 | function do_lapsed() { |
||
293 | global $globals; |
||
294 | $max_last_rpc_time = time() - $globals->lapsed_interval; |
||
295 | |||
296 | // the following is an efficient way of getting the list of |
||
297 | // users for which no host has done an RPC recently |
||
298 | // |
||
299 | $result = _mysql_query( |
||
300 | "select userid from host group by userid having max(rpc_time)<$max_last_rpc_time;" |
||
301 | ); |
||
302 | while ($host = _mysql_fetch_object($result)) { |
||
303 | $uresult = _mysql_query("select * from user where id = $host->userid;"); |
||
304 | $user = _mysql_fetch_object($uresult); |
||
305 | _mysql_free_result($uresult); |
||
306 | if (!$user) { |
||
307 | echo "Can't find user $host->userid\n"; |
||
308 | continue; |
||
309 | } |
||
310 | handle_user($user, 'lapsed'); |
||
311 | } |
||
312 | _mysql_free_result($result); |
||
313 | } |
||
314 | |||
315 | if (!function_exists('make_php_mailer')) { |
||
316 | echo "You must use PHPMailer (http://phpmailer.sourceforge.net)\n"; |
||
317 | exit(); |
||
318 | } |
||
319 | |||
320 | $email_files = read_email_files(); |
||
321 | |||
322 | if ($globals->userid) { |
||
323 | $user = BoincUser::lookup_id($globals->userid); |
||
324 | if (!$user) { |
||
325 | echo "No such user: $globals->userid\n"; |
||
326 | exit(); |
||
327 | } |
||
328 | $user->last_rpc_time = last_rpc_time($user); |
||
329 | mail_type($user, 'failed'); |
||
330 | mail_type($user, 'lapsed'); |
||
331 | } else { |
||
332 | if ($globals->do_failed) { |
||
333 | do_failed(); |
||
334 | } |
||
335 | if ($globals->do_lapsed) { |
||
336 | do_lapsed(); |
||
337 | } |
||
338 | } |
||
339 | |||
340 | ?> |
||
341 |