1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# models/track_mailer.rb:
# Emails which go to users who are tracking things.
#
# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
#
# $Id: track_mailer.rb,v 1.23 2009-10-03 02:50:11 francis Exp $
class TrackMailer < ApplicationMailer
def event_digest(user, email_about_things)
post_redirect = PostRedirect.new(
:uri => main_url(user_url(user)) + "#email_subscriptions",
:user_id => user.id)
post_redirect.save!
unsubscribe_url = confirm_url(:email_token => post_redirect.email_token)
@from = contact_from_name_and_email
headers 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834
'Precedence' => 'bulk' # http://www.vbulletin.com/forum/project.php?issueid=27687 (Exchange hack)
# 'Return-Path' => blackhole_email, 'Reply-To' => @from # we don't care about bounces for tracks
# (We let it return bounces for now, so we can manually kill the tracks that bounce so Yahoo
# etc. don't decide we are spammers.)
@recipients = user.name_and_email
@subject = "Your WhatDoTheyKnow.com email alert"
@body = { :user => user, :email_about_things => email_about_things, :unsubscribe_url => unsubscribe_url }
end
# Send email alerts for tracked things. Never more than one email
# a day, nor about events which are more than a week old, nor
# events about which emails have been sent within the last two
# weeks.
# Useful query to run by hand to see how many alerts are due:
# User.find(:all, :conditions => [ "last_daily_track_email < ?", Time.now - 1.day ]).size
def self.alert_tracks
now = Time.now()
users = User.find(:all, :conditions => [ "last_daily_track_email < ?", now - 1.day ])
if users.empty?
return false
end
for user in users
email_about_things = []
track_things = TrackThing.find(:all, :conditions => [ "tracking_user_id = ? and track_medium = ?", user.id, 'email_daily' ])
for track_thing in track_things
# What have we alerted on already?
#
# We only use track_things_sent_emails records which are less than 14 days old.
# In the search query loop below, we also only use items described in last 7 days.
# An item described that recently definitely can't appear in track_things_sent_emails
# earlier, so this is safe (with a week long margin of error). If the alerts break
# for a whole week, then they will miss some items. Tough.
done_info_request_events = {}
tt_sent = track_thing.track_things_sent_emails.find(:all, :conditions => ['created_at > ?', now - 14.days])
for t in tt_sent
if not t.info_request_event_id.nil?
done_info_request_events[t.info_request_event_id] = 1
end
end
# Query for things in this track. We use described_at for the
# ordering, so we catch anything new (before described), or
# anything whose new status has been described.
xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 100, 1)
# Go through looking for unalerted things
alert_results = []
for result in xapian_object.results
if result[:model].class.to_s != "InfoRequestEvent"
raise "need to add other types to TrackMailer.alert_tracks (unalerted)"
end
next if track_thing.created_at >= result[:model].described_at # made before the track was created
next if result[:model].described_at < now - 7.days # older than 1 week (see 14 days / 7 days in comment above)
next if done_info_request_events.include?(result[:model].id) # definitely already done
# OK alert this one
alert_results.push(result)
end
# If there were more alerts for this track, then store them
if alert_results.size > 0
email_about_things.push([track_thing, alert_results, xapian_object])
end
end
# If we have anything to send, then send everything for the user in one mail
if email_about_things.size > 0
# Send the email
TrackMailer.deliver_event_digest(user, email_about_things)
end
# Record that we've now sent those alerts to that user
for track_thing, alert_results in email_about_things
for result in alert_results
track_things_sent_email = TrackThingsSentEmail.new
track_things_sent_email.track_thing_id = track_thing.id
if result[:model].class.to_s == "InfoRequestEvent"
track_things_sent_email.info_request_event_id = result[:model].id
else
raise "need to add other types to TrackMailer.alert_tracks (mark alerted)"
end
track_things_sent_email.save!
end
end
user.last_daily_track_email = now
user.no_xapian_reindex = true
user.save!
end
return true
end
def self.alert_tracks_loop
# Run alert_tracks in an endless loop, sleeping when there is nothing to do
while true
sleep_seconds = 1
while !alert_tracks
sleep sleep_seconds
sleep_seconds *= 2
sleep_seconds = 300 if sleep_seconds > 300
end
end
end
end
|