-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bot-monitor: allow pausing email notifications
- Loading branch information
1 parent
19d325a
commit fa2d52a
Showing
9 changed files
with
167 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import { argv, bot, log, mailTransporter, Mwn } from "../botbase"; | ||
import {Rule, RuleError, Monitor, subtractFromNow, alertsDb} from "./index"; | ||
import * as crypto from "crypto"; | ||
|
||
export class Alert { | ||
rule: Rule | ||
|
@@ -60,17 +61,18 @@ export class Alert { | |
log(`[i] Sending email for "${this.name}" to ${this.rule.email}`); | ||
let subject = `[${this.rule.bot}] ${this.rule.task} failure`; | ||
|
||
const webKey = crypto.randomBytes(32).toString('hex'); | ||
if (this.rule.email.includes('@')) { | ||
await mailTransporter.sendMail({ | ||
from: '[email protected]', | ||
to: this.rule.email, | ||
subject: subject, | ||
html: this.getEmailBodyHtml(), | ||
html: this.getEmailBodyHtml(webKey), | ||
}); | ||
} else { | ||
await new bot.User(this.rule.email).email( | ||
subject, | ||
this.getEmailBodyPlain(), | ||
this.getEmailBodyPlain(webKey), | ||
{ccme: true} | ||
).catch(err => { | ||
if (err.code === 'notarget') { | ||
|
@@ -86,18 +88,26 @@ export class Alert { | |
}); | ||
} | ||
|
||
getEmailBodyHtml(): string { | ||
getEmailBodyHtml(webKey: string): string { | ||
const taskKey = `${this.rule.bot}: ${this.rule.task}`; | ||
return `${this.rule.bot}'s task <b>${this.rule.task}</b> failed to run per the configuration specified at <a href="https://en.wikipedia.org/wiki/Wikipedia:Bot_activity_monitor/Configurations">Wikipedia:Bot activity monitor/Configurations</a>. Detected only ${this.actions} ${this.rule.action === 'edit' ? 'edit' : `"${this.rule.action}" action`}s in the last ${this.rule.duration}, whereas at least ${this.rule.minEdits} were expected.` + | ||
`<br><br>` + | ||
`If your bot is behaving as expected, then you may want to <a href="https://en.wikipedia.org/wiki/Wikipedia:Bot_activity_monitor/Configurations?action=edit">modify the task configuration instead</a>. Or to unsubscribe from these email notifications, remove the |email= parameter from the {{/task}} template.` + | ||
`<br><br>` + | ||
`To temporarily pause these notifications, click here: https://sdzerobot.toolforge.org/bot-monitor/pause?task=${encodeURIComponent(taskKey)}&webKey=${webKey}` + | ||
`<br><br>` + | ||
`Thanks!`; | ||
} | ||
|
||
getEmailBodyPlain(): string { | ||
getEmailBodyPlain(webKey: string): string { | ||
const taskKey = `${this.rule.bot}: ${this.rule.task}`; | ||
return `${this.rule.bot}'s task "${this.rule.task}" failed to run per the configuration specified at Wikipedia:Bot activity monitor/Configurations (<https://en.wikipedia.org/wiki/Wikipedia:Bot_activity_monitor/Configurations>). Detected only ${this.actions} ${this.rule.action === 'edit' ? 'edit' : `"${this.rule.action}" action`}s in the last ${this.rule.duration}, whereas at least ${this.rule.minEdits} were expected.` + | ||
`\n\n` + | ||
`If your bot is behaving as expected, then you may want to modify the task configuration instead. Or to unsubscribe from these email notifications, remove the |email= parameter from the {{/task}} template. Thanks!`; | ||
`If your bot is behaving as expected, then you may want to modify the task configuration instead. Or to unsubscribe from these email notifications, remove the |email= parameter from the {{/task}} template.` + | ||
`\n\n` + | ||
`To temporarily pause these notifications, click here: https://sdzerobot.toolforge.org/bot-monitor/pause?task=${encodeURIComponent(taskKey)}&webKey=${webKey}` + | ||
`\n\n` + | ||
`Thanks!`; | ||
} | ||
|
||
// static pingpage = 'Wikipedia:Bot activity monitor/Pings' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
CREATE TABLE alerts( | ||
name VARCHAR(255) PRIMARY KEY, | ||
lastEmailed TIMESTAMP | ||
); | ||
|
||
ALTER TABLE alerts ADD webKey CHAR(128); | ||
ALTER TABLE alerts ADD paused timestamp null; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<h2>Pausing failure notifications for {{task}}</h2> | ||
{{#if current}} | ||
<form method="post"> | ||
<label>{{{current}}}</label> | ||
<input type="hidden" name="task" value="{{task}}"> | ||
<input type="hidden" name="webKey" value="{{webKey}}"> | ||
<input type="hidden" name="unpause" value="1"> | ||
<input type="submit" value="Unpause"> | ||
</form> | ||
{{/if}} | ||
<br> | ||
<form method="post"> | ||
<input type="hidden" name="task" value="{{task}}"> | ||
<input type="hidden" name="webKey" value="{{webKey}}"> | ||
<label for="till">Pause notifications till:</label> | ||
<input id="till" name="date" type="date" value="{{dateVal}}" required> | ||
<input type="submit" value="Pause"> | ||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import * as express from "express"; | ||
import {alertsDb} from "./AlertsDb"; | ||
import {bot} from "../botbase"; | ||
|
||
const router = express.Router(); | ||
|
||
alertsDb.connect(); | ||
|
||
router.all('/pause', async (req, res, next) => { | ||
try { | ||
const { task, webKey } = req.query as Record<string, string>; | ||
const { date, unpause } = req.body as Record<string, string>; | ||
if (!webKey || !task) { | ||
return next(new CustomError(400, "Missing one of required query params: task, webKey")); | ||
} | ||
|
||
let current = ''; | ||
let dateVal = ''; | ||
if (date) { // POST | ||
const tillDate = new bot.Date(date); | ||
const rowsUpdated = await alertsDb.setPausedTillTime(task, webKey, tillDate); | ||
if (!rowsUpdated) { | ||
return next(new CustomError(403, "Unauthorized")); | ||
} | ||
current = `<span style="color: green; font-weight: bold">Successfully paused notifications till ${tillDate.format('D MMMM YYYY')} (UTC).</span>`; | ||
dateVal = tillDate.format('YYYY-MM-DD'); | ||
} else if (unpause) { // POST | ||
const rowsUpdated = await alertsDb.setPausedTillTime(task, webKey); | ||
if (!rowsUpdated) { | ||
return next(new CustomError(403, "Unauthorized")); | ||
} | ||
current = `<span style="color: green; font-weight: bold">Successfully unpaused notifications.</span>`; | ||
} else { // GET | ||
let pausedTill = await alertsDb.getPausedTillTime(task, webKey); | ||
if (pausedTill) { | ||
current = `Notifications are currently paused till ${pausedTill.format('D MMMM YYYY')} (UTC).`; | ||
dateVal = pausedTill.format('YYYY-MM-DD'); | ||
} | ||
} | ||
|
||
return res.render('bot-monitor/web-endpoint', { | ||
task, | ||
webKey, | ||
current, | ||
dateVal | ||
}); | ||
} catch (e) { | ||
next(e); | ||
} | ||
}); | ||
|
||
export class CustomError extends Error { | ||
status: number; | ||
constructor(status: number, msg: string) { | ||
super(msg); | ||
this.status = status; | ||
} | ||
} | ||
|
||
|
||
export default router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters