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