1 /**
2 	Copyright: © 2014 rejectedsoftware e.K.
3 	License: Subject to the terms of the GNU GPLv3 license, as written in the included LICENSE.txt file.
4 	Authors: Sönke Ludwig
5 */
6 module dubregistry.notificationcenter;
7 
8 import dubregistry.scheduler;
9 
10 import std.array : appender;
11 import std.datetime;
12 import std.encoding : sanitize;
13 import std.string : format;
14 import userman.db.controller;
15 import vibe.core.log;
16 import vibe.mail.smtp;
17 import vibe.stream.memory;
18 import diet.html;
19 
20 
21 class NotificationCenter {
22 	private {
23 		UserManController m_users;
24 		PersistentScheduler m_scheduler;
25 		string[][string][User.ID] m_deprecations;
26 
27 		enum weeklyDeprecationEventName = "deprecation-warnings";
28 	}
29 
30 	this(UserManController users)
31 	{
32 		m_users = users;
33 		m_scheduler = new PersistentScheduler(Path("notification-schedule.json"));
34 		if (!m_scheduler.existsEvent(weeklyDeprecationEventName))
35 			m_scheduler.scheduleWeeklyEvent(weeklyDeprecationEventName, SysTime(DateTime(2014, 01, 05, 12, 0, 0), UTC()));
36 	}
37 
38 	void startRegularNotifications()
39 	{
40 		m_scheduler.setEventHandler(weeklyDeprecationEventName, &onSendDeprecationWarnings);
41 	}
42 
43 	void notifyNewErrors(User.ID user_id, string package_name, string branch_or_version, string[] errors)
44 	{
45 		auto user = m_users.getUser(user_id);
46 		if (user.email != "sludwig@rejectedsoftware.com") return;
47 
48 		auto settings = m_users.settings;
49 
50 		auto mail = new Mail;
51 		mail.headers["From"] = format("%s <%s>", settings.serviceName, settings.serviceEmail);
52 		mail.headers["To"] = format("%s <%s>", user.fullName, user.email); // FIXME: sanitize/escape user.fullName
53 		mail.headers["Subject"] = format("[%s] Errors in new version %s", package_name, branch_or_version);
54 
55 		auto dst = appender!string();
56 		dst.compileHTMLDietFile!("dubregistry.mail.package-version-errors.dt", user, settings, package_name, branch_or_version, errors);
57 		mail.bodyText = dst.data;
58 
59 		sendMail(settings.mailSettings, mail);
60 	}
61 
62 	void setDeprecationWarnings(User.ID user_id, string package_name, string[] warnings)
63 	{
64 		auto pd = user_id in m_deprecations;
65 		if (!pd) {
66 			m_deprecations[user_id] = null;
67 			pd = user_id in m_deprecations;
68 		}
69 		if (warnings.length) (*pd)[package_name] = warnings;
70 		else if (package_name in *pd) (*pd).remove(package_name);
71 	}
72 
73 	private void onSendDeprecationWarnings()
74 	{
75 		foreach (uid, deprecations; m_deprecations) {
76 			User user;
77 			try {
78 				user = m_users.getUser(uid);
79 				if (user.email != "sludwig@rejectedsoftware.com") continue;
80 
81 				auto settings = m_users.settings;
82 
83 				auto mail = new Mail;
84 				mail.headers["From"] = format("%s <%s>", settings.serviceName, settings.serviceEmail);
85 				mail.headers["To"] = format("%s <%s>", user.fullName, user.email); // FIXME: sanitize/escape user.fullName
86 				mail.headers["Subject"] = format("Weekly deprecation warnings reminder");
87 
88 				auto dst = appender!string();
89 				dst.compileHTMLDietFile!("dubregistry.mail.package-deprecation-warnings.dt", user, settings, deprecations);
90 				mail.bodyText = cast(string)dst.data;
91 
92 				sendMail(settings.mailSettings, mail);
93 			} catch (Exception e) {
94 				logDiagnostic("Failed to send deprecation mail to %s <%s>: %s", user.fullName, user.email, e.msg);
95 				logDebug("Full error: %s", e.toString().sanitize);
96 			}
97 		}
98 	}
99 }