bsw@1248: InitiativeForNotification = mondelefant.new_class() bsw@1248: InitiativeForNotification.table = 'initiative_for_notification' bsw@1248: bsw@1248: InitiativeForNotification:add_reference{ bsw@1248: mode = 'm1', bsw@1248: to = "Initiative", bsw@1248: this_key = 'initiative_id', bsw@1248: that_key = 'id', bsw@1248: ref = 'initiative', bsw@1248: } bsw@1248: bsw@1248: bsw@1248: function InitiativeForNotification:notify_member_id(member_id) bsw@1248: bsw@1248: db:query("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ") bsw@1248: bsw@1248: local member = Member:by_id(member_id) bsw@1248: locale.set{ lang = member.lang or config.default_lang } bsw@1248: bsw@1248: io.stderr:write("Sending digest #" .. member.notification_counter .. " to " .. member.notify_email .. "\n") bsw@1248: bsw@1248: if not member.notify_email then bsw@1248: return bsw@1248: end bsw@1248: bsw@1248: local selector = db:new_selector() bsw@1248: :add_field("*") bsw@1248: :from({ "get_initiatives_for_notification(?)", member_id }, "initiative_for_notification") bsw@1248: :join("initiative", nil, "initiative.id = initiative_for_notification.initiative_id") bsw@1248: :join("issue", nil, "issue.id = initiative.issue_id") bsw@1248: :join("member", nil, "member.id = initiative_for_notification.recipient_id") bsw@1248: :add_order_by("md5(initiative_for_notification.recipient_id || '-' || member.notification_counter || '-' || issue.area_id)") bsw@1248: :add_order_by("md5(initiative_for_notification.recipient_id || '-' || member.notification_counter || '-' || issue.id)") bsw@1248: selector._class = self bsw@1248: bsw@1248: local initiatives_for_notification = selector:exec() bsw@1248: bsw@1248: if #initiatives_for_notification < 1 then bsw@1248: return bsw@1248: end bsw@1248: bsw@1248: local initiatives = initiatives_for_notification:load("initiative") bsw@1248: local issues = initiatives:load("issue") bsw@1248: issues:load("area") bsw@1248: issues:load("policy") bsw@1248: bsw@1248: local last_area_id bsw@1248: local last_issue_id bsw@1248: bsw@1248: local draft_count = 0 bsw@1248: local suggestion_count = 0 bsw@1248: bsw@1248: local ms = {} bsw@1248: bsw@1248: for i, entry in ipairs(initiatives_for_notification) do bsw@1248: local initiative = entry.initiative bsw@1248: local issue = initiative.issue bsw@1248: local area = issue.area bsw@1248: local policy = issue.policy bsw@1248: bsw@1248: local m = {} bsw@1248: if last_area_id ~= area.id then bsw@1248: m[#m+1] = "*** " .. area.name .. " ***" bsw@1248: m[#m+1] = "" bsw@1248: last_area_id = area.id bsw@1248: end bsw@1248: if last_issue_id ~= issue.id then bsw@1248: local state_time_text bsw@1248: if string.sub(issue.state_time_left, 1, 1) == "-" then bsw@1248: state_time_text = _"Phase ends soon" bsw@1248: else bsw@1248: state_time_text = _( "#{interval} left", { bsw@1248: interval = format.interval_text(issue.state_time_left) bsw@1248: }) bsw@1248: end bsw@1248: m[#m+1] = "---" bsw@1248: m[#m+1] = policy.name .. " #" .. issue.id .. " - " .. issue.state_name .. " - " .. state_time_text bsw@1248: m[#m+1] = "" bsw@1248: last_issue_id = issue.id bsw@1248: end bsw@1248: m[#m+1] = initiative.display_name bsw@1248: local source bsw@1248: if entry.supported then bsw@1248: source = _"has my support" bsw@1248: local draft_info bsw@1248: if entry.new_draft then bsw@1248: draft_info = _"draft updated" bsw@1248: draft_count = draft_count + 1 bsw@1248: end bsw@1248: if draft_info then bsw@1248: source = source .. ", " .. draft_info bsw@1248: end bsw@1248: local info bsw@1248: if entry.new_suggestion_count then bsw@1248: if entry.new_suggestion_count == 1 then bsw@1248: info = _"new suggestion added" bsw@1248: elseif entry.new_suggestion_count > 1 then bsw@1248: info = _("#{count} suggestions added", { count = entry.new_suggestion_count }) bsw@1248: end bsw@1248: suggestion_count = suggestion_count + entry.new_suggestion_count bsw@1248: end bsw@1248: if info then bsw@1248: source = source .. ", " .. info bsw@1248: end bsw@1248: elseif entry.featured then bsw@1248: source = _"featured" bsw@1248: end bsw@1248: if entry.leading then bsw@1248: source = source and source .. ", " or "" bsw@1248: source = source .. "currently leading" bsw@1248: end bsw@1248: m[#m+1] = "(" .. source .. ")" bsw@1248: m[#m+1] = "" bsw@1248: if not initiatives_for_notification[i+1] or initiatives_for_notification[i+1].issue_id ~= issue.id then bsw@1248: m[#m+1] = _("more: #{url}", { url = request.get_absolute_baseurl() .. "issue/show/" .. issue.id .. ".html" }) bsw@1248: m[#m+1] = "" bsw@1248: end bsw@1248: ms[#ms+1] = table.concat(m, "\n") bsw@1248: end bsw@1248: bsw@1248: local info = {} bsw@1248: bsw@1248: if draft_count > 0 then bsw@1248: if draft_count == 1 then bsw@1248: info[#info+1] = _"draft updated for " .. initiatives_for_notification[1].initiative.display_name bsw@1248: else bsw@1248: info[#info+1] = _("drafts of #{draft_count} initiatives updated", { draft_count = draft_count }) bsw@1248: end bsw@1248: end bsw@1248: bsw@1248: if suggestion_count > 0 then bsw@1248: if suggestion_count == 1 then bsw@1248: info[#info+1] = _"new suggestion for " .. initiatives_for_notification[1].initiative.display_name bsw@1248: else bsw@1248: info[#info+1] = _("#{suggestion_count} suggestions added", { suggestion_count = suggestion_count }) bsw@1248: end bsw@1248: end bsw@1248: bsw@1248: if draft_count == 0 and suggestion_count == 0 then bsw@1248: info[#info+1] = _"featured initiatives" bsw@1248: end bsw@1248: bsw@1248: local subject = _("Digest #{id}: #{info}", { bsw@1248: id = member.notification_counter, info = table.concat(info, ", ") bsw@1248: }) bsw@1248: bsw@1248: bsw@1248: local template = config.notification_digest_template bsw@1248: bsw@1248: local message = _(template, { bsw@1248: name = member.name, bsw@1248: digest = table.concat(ms, "\n") bsw@1248: }) bsw@1248: bsw@1248: local success = net.send_mail{ bsw@1248: envelope_from = config.mail_envelope_from, bsw@1248: from = config.mail_from, bsw@1248: reply_to = config.mail_reply_to, bsw@1248: to = member.notify_email, bsw@1248: subject = subject, bsw@1248: content_type = "text/plain; charset=UTF-8", bsw@1248: content = message bsw@1248: } bsw@1248: bsw@1248: db:query("COMMIT") bsw@1248: bsw@1248: end bsw@1248: bsw@1248: function InitiativeForNotification:notify_next_member() bsw@1248: local scheduled_notification_to_send = ScheduledNotificationToSend:get_next() bsw@1248: if not scheduled_notification_to_send then bsw@1248: return false bsw@1248: end bsw@1248: InitiativeForNotification:notify_member_id(scheduled_notification_to_send.recipient_id) bsw@1248: return true bsw@1248: end bsw@1248: bsw@1248: ScheduledNotificationToSend:get_next()