Issues (1963)

html/ops/remind.php (6 issues)

1
#! /usr/bin/env php
2
0 ignored issues
show
PHP files must only contain PHP code
Loading history...
3
<?php
0 ignored issues
show
The opening PHP tag must be the first content in the file
Loading history...
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 if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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.

Loading history...
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
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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