#[Copyright 2025 ITwrx. This file is part of Forget-Me-Not. Forget-Me-Not is released under the GNU Affero General Public License 3.0. See COPYING or for details.]# import std/[times, osproc], smtp import ../models/reminder, ../models/user, datetime #TODO: use comnfig file for creds and other comms settings instead of hardcoding. proc setFutureSendDate(reminderId: int) = var reminder: Reminder reminder = getReminderById(reminderId) var newSendDate: DateTime case reminder.repeatFreq: of "day": newSendDate = now() + 1.days reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() of "week": newSendDate = nextWeekday(reminder.weeklyOn) reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() of "month": if reminder.monthlyOnDay > 0: #create DateTime with current month and year and reminder.monthlyOnDay newSendDate = dateTime(year(now()), month(now()), reminder.monthlyOnDay) newSendDate = newSendDate + 1.months reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() else: #monthly on week number and weekday. e.g. "third thursday of every month". newSendDate = nextMonthlyOnWeekdayOfWeek($reminder.monthlyOnWeekday, $reminder.monthlyOnWeek) reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() of "year": #yearly on month and day. #string zeros (db artifacts) have a length of 1... if reminder.yearlyOnMonth.len() > 1: newSendDate = nextYearlyDate(reminder.yearlyOnMonth, reminder.yearlyOnDay) reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() #yearly on weekday of week of month. e.g. third thursday of november of each year. else: newSendDate = nextYearlyOnWeekdayOfWeekOfMonth($reminder.yearlyOnWeekday, $reminder.yearlyOnWeek, $reminder.yearlyOnMonth2) reminder.sendDate = $format(newSendDate, "yyyy-MM-dd") updateReminderSendDate(reminder) clearAllReminders() else: echo "Invalid value for reminder.repeatFreq in setFutureSendDate()" proc sendEmail(reminderMsg: string) = ##Warning: hardcoded userId expects one user with id of 1. let userEmailAddress = getEmailByUserId("1") let headers = @[("From", "mymaileraccount@mydomain.org")] let msg = createMessage("Reminder from Forget-Me-Not", reminderMsg, @[userEmailAddress], mCc = @[""], otherHeaders = headers) {.cast(raises: []).}: let smtpConn = newSmtp(debug=false) smtpConn.connect("mail.mydomain.org", Port 587) smtpConn.startTls() smtpConn.auth("mymaileraccount@mydomain.org", "mymaileraccount-password-goes-here") #loop through email messages and send to reuse connection? smtpConn.sendmail("mymaileraccount@mydomain.org", @[userEmailAddress], $msg) #manually closing not necessary? smtpConn.close() proc sendXMPP(reminderMsg: string) = var output: string var status: int (output, status) = execCmdEx("xmppc -m message chat receiving-xmpp-user@myxmppserverdomain.org \"" & reminderMsg & "\"") if status != 0: #log this later instead. echo output echo "error sending XMPP msg" #send reminders that haven't been sent yet and set new sendDate (if repeating). proc sendReminders*() = let nowDT = now() let reminders = getAllReminders() for reminder in reminders: let sendDateDTString = $reminder.sendDate & " " & $reminder.sendTimeHr & ":" & $reminder.sendTimeMin & ":" & $reminder.sendTimeAmPm #single digits for minutes, as db send_time_min is integer and won't use "00", which results in runtime parse error. let sendDateDT = parse(sendDateDTString, "yyyy-M-d h:m:tt") #if sendDate is not in the future, it hasn't been sent yet (we are changing sendDate to future date during each send) and needs to be sent. if sendDateDT <= nowDT: #send reminder notification case reminder.notifyVia: of "email": sendEmail(reminder.message) of "xmpp": sendXMPP(reminder.message) else: sendXMPP(reminder.message) sendEmail(reminder.message) if reminder.repeats == 1: setFutureSendDate(reminder.id) else: deleteReminder(reminder.id) clearAllReminders()