diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/incoming_message.rb | 54 | ||||
-rw-r--r-- | app/models/info_request.rb | 18 | ||||
-rw-r--r-- | app/models/info_request_event.rb | 32 | ||||
-rw-r--r-- | app/models/public_body.rb | 49 | ||||
-rw-r--r-- | app/models/request_mailer.rb | 24 | ||||
-rw-r--r-- | app/models/track_mailer.rb | 12 | ||||
-rw-r--r-- | app/models/track_thing.rb | 81 | ||||
-rw-r--r-- | app/models/user.rb | 39 | ||||
-rw-r--r-- | app/models/user_mailer.rb | 2 |
9 files changed, 194 insertions, 117 deletions
diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 16ae38b92..2b795ddf5 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -29,7 +29,6 @@ # general not specific to IncomingMessage. require 'alaveteli_file_types' -require 'external_command' require 'htmlentities' require 'rexml/document' require 'zip/zip' @@ -1121,38 +1120,38 @@ class IncomingMessage < ActiveRecord::Base tempfile.print body tempfile.flush if content_type == 'application/vnd.ms-word' - external_command("/usr/bin/wvText", tempfile.path, tempfile.path + ".txt") + AlaveteliExternalCommand.run("/usr/bin/wvText", tempfile.path, tempfile.path + ".txt") # Try catdoc if we get into trouble (e.g. for InfoRequestEvent 2701) if not File.exists?(tempfile.path + ".txt") - external_command("/usr/bin/catdoc", tempfile.path, :append_to => text) + AlaveteliExternalCommand.run("/usr/bin/catdoc", tempfile.path, :append_to => text) else text += File.read(tempfile.path + ".txt") + "\n\n" File.unlink(tempfile.path + ".txt") end elsif content_type == 'application/rtf' # catdoc on RTF prodcues less comments and extra bumf than --text option to unrtf - external_command("/usr/bin/catdoc", tempfile.path, :append_to => text) + AlaveteliExternalCommand.run("/usr/bin/catdoc", tempfile.path, :append_to => text) elsif content_type == 'text/html' # lynx wordwraps links in its output, which then don't get formatted properly # by Alaveteli. We use elinks instead, which doesn't do that. - external_command("/usr/bin/elinks", "-eval", "'set document.codepage.assume = \"utf-8\"'", "-dump-charset", "utf-8", "-force-html", "-dump", + AlaveteliExternalCommand.run("/usr/bin/elinks", "-eval", "'set document.codepage.assume = \"utf-8\"'", "-dump-charset", "utf-8", "-force-html", "-dump", tempfile.path, :append_to => text) elsif content_type == 'application/vnd.ms-excel' # Bit crazy using /usr/bin/strings - but xls2csv, xlhtml and # py_xls2txt only extract text from cells, not from floating # notes. catdoc may be fooled by weird character sets, but will # probably do for UK FOI requests. - external_command("/usr/bin/strings", tempfile.path, :append_to => text) + AlaveteliExternalCommand.run("/usr/bin/strings", tempfile.path, :append_to => text) elsif content_type == 'application/vnd.ms-powerpoint' # ppthtml seems to catch more text, but only outputs HTML when # we want text, so just use catppt for now - external_command("/usr/bin/catppt", tempfile.path, :append_to => text) + AlaveteliExternalCommand.run("/usr/bin/catppt", tempfile.path, :append_to => text) elsif content_type == 'application/pdf' - external_command("/usr/bin/pdftotext", tempfile.path, "-", :append_to => text) + AlaveteliExternalCommand.run("/usr/bin/pdftotext", tempfile.path, "-", :append_to => text) elsif content_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' # This is Microsoft's XML office document format. # Just pull out the main XML file, and strip it of text. - xml = external_command("/usr/bin/unzip", "-qq", "-c", tempfile.path, "word/document.xml") + xml = AlaveteliExternalCommand.run("/usr/bin/unzip", "-qq", "-c", tempfile.path, "word/document.xml") if !xml.nil? doc = REXML::Document.new(xml) text += doc.each_element( './/text()' ){}.join(" ") @@ -1305,10 +1304,15 @@ class IncomingMessage < ActiveRecord::Base prefix = email prefix =~ /^(.*)@/ prefix = $1 - if !prefix.nil? && prefix.downcase.match(/^(postmaster|mailer-daemon|auto_reply|donotreply|no.reply)$/) + if !prefix.nil? && prefix.downcase.match(/^(postmaster|mailer-daemon|auto_reply|do.?not.?reply|no.reply)$/) + return false + end + if !self.mail['return-path'].nil? && self.mail['return-path'].addr == "<>" + return false + end + if !self.mail['auto-submitted'].nil? && !self.mail['auto-submitted'].keys.empty? return false end - return true end @@ -1336,34 +1340,6 @@ class IncomingMessage < ActiveRecord::Base end private :normalise_content_type - def self.external_command(program_name, *args) - # Run an external program, and return its output. - # Standard error is suppressed unless the program - # fails (i.e. returns a non-zero exit status). - opts = {} - if !args.empty? && args[-1].is_a?(Hash) - opts = args.pop - end - - xc = ExternalCommand.new(program_name, *args) - if opts.has_key? :append_to - xc.out = opts[:append_to] - end - xc.run() - if xc.status != 0 - # Error - $stderr.puts("Error from #{program_name} #{args.join(' ')}:") - $stderr.print(xc.err) - return nil - else - if opts.has_key? :append_to - opts[:append_to] << "\n\n" - else - return xc.out - end - end - end - private_class_method :external_command end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 9b0f1047b..92322f74f 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -117,13 +117,13 @@ class InfoRequest < ActiveRecord::Base # only check on create, so existing models with mixed case are allowed def validate_on_create if !self.title.nil? && !MySociety::Validate.uses_mixed_capitals(self.title, 10) - errors.add(:title, N_('Please write the summary using a mixture of capital and lower case letters. This makes it easier for others to read.')) + errors.add(:title, _('Please write the summary using a mixture of capital and lower case letters. This makes it easier for others to read.')) end if !self.title.nil? && title.size > 200 - errors.add(:title, N_('Please keep the summary short, like in the subject of an email. You can use a phrase, rather than a full sentence.')) + errors.add(:title, _('Please keep the summary short, like in the subject of an email. You can use a phrase, rather than a full sentence.')) end if !self.title.nil? && self.title =~ /^(FOI|Freedom of Information)\s*requests?$/i - errors.add(:title, N_('Please describe more what the request is about in the subject. There is no need to say it is an FOI request, we add that on anyway.')) + errors.add(:title, _('Please describe more what the request is about in the subject. There is no need to say it is an FOI request, we add that on anyway.')) end end @@ -780,8 +780,7 @@ public # Display version of status - def display_status - status = self.calculate_status + def InfoRequest.get_status_description(status) if status == 'waiting_classification' _("Awaiting classification.") elsif status == 'waiting_response' @@ -819,6 +818,10 @@ public end end + def display_status + InfoRequest.get_status_description(self.calculate_status) + end + # Completely delete this request and all objects depending on it def fully_destroy self.track_things.each do |track_thing| @@ -919,10 +922,13 @@ public end # List of incoming messages to followup, by unique email - def who_can_followup_to + def who_can_followup_to(skip_message = nil) ret = [] done = {} for incoming_message in self.incoming_messages.reverse + if incoming_message == skip_message + next + end incoming_message.safe_mail_from email = OutgoingMailer.email_for_followup(self, incoming_message) diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 4003217b0..4ea89bf81 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -303,37 +303,7 @@ class InfoRequestEvent < ActiveRecord::Base def display_status if is_incoming_message? status = self.calculated_state - if !status.nil? - if status == 'waiting_response' - return _("Acknowledgement") - elsif status == 'waiting_clarification' - return _("Clarification required") - elsif status == 'gone_postal' - return _("Handled by post") - elsif status == 'deadline_extended' - return _("Deadline Extended") - elsif status == 'wrong_response' - return _("Wrong Response") - elsif status == 'not_held' - return _("Information not held") - elsif status == 'rejected' - return _("Refused") - elsif status == 'partially_successful' - return _("Some information sent") - elsif status == 'successful' - return _("All information sent") - elsif status == 'internal_review' - return _("Internal review acknowledgement") - elsif status == 'user_withdrawn' - return _("Withdrawn by requester") - elsif status == 'error_message' - return _("Delivery error") - elsif status == 'requires_admin' - return _("Unusual response") - end - raise "unknown status " + status - end - return "Response" + return status.nil? ? _("Response") : InfoRequest.get_status_description(status) end if is_outgoing_message? diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 81149e3c2..311e19001 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -112,16 +112,6 @@ class PublicBody < ActiveRecord::Base end end - # XXX this should be saner; probably implement categories as data - begin - load "public_body_categories_#{I18n.locale.to_s}.rb" - rescue MissingSourceFile - begin - load "public_body_categories_#{I18n.default_locale.to_s}.rb" - rescue MissingSourceFile - load "public_body_categories.rb" - end - end # Set the first letter, which is used for faster queries before_save(:set_first_letter) def set_first_letter @@ -255,8 +245,8 @@ class PublicBody < ActiveRecord::Base types = [] first = true for tag in self.tags - if PublicBodyCategories::CATEGORIES_BY_TAG.include?(tag.name) - desc = PublicBodyCategories::CATEGORY_SINGULAR_BY_TAG[tag.name] + if PublicBodyCategories::get().by_tag().include?(tag.name) + desc = PublicBodyCategories::get().singular_by_tag()[tag.name] if first # terrible that Ruby/Rails doesn't have an equivalent of ucfirst # (capitalize shockingly converts later characters to lowercase) @@ -344,7 +334,7 @@ class PublicBody < ActiveRecord::Base # Import from CSV. Just tests things and returns messages if dry_run is true. # Returns an array of [array of errors, array of notes]. If there are errors, # always rolls back (as with dry_run). - def self.import_csv(csv, tag, dry_run, editor, available_locales = []) + def self.import_csv(csv, tag, tag_behaviour, dry_run, editor, available_locales = []) errors = [] notes = [] available_locales = [I18n.default_locale] if available_locales.empty? @@ -357,7 +347,11 @@ class PublicBody < ActiveRecord::Base bodies_by_name = {} set_of_existing = Set.new() PublicBody.with_locale(I18n.default_locale) do - for existing_body in PublicBody.find_by_tag(tag) + bodies = (tag.nil? || tag.empty?) ? PublicBody.find(:all) : PublicBody.find_by_tag(tag) + for existing_body in bodies + # Hide InternalAdminBody from import notes + next if existing_body.id == PublicBody.internal_admin_body.id + bodies_by_name[existing_body.name] = existing_body set_of_existing.add(existing_body.name) end @@ -391,15 +385,28 @@ class PublicBody < ActiveRecord::Base next end - field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'home_page'] + field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'home_page', 'tag_string'] - if public_body = bodies_by_name[name] + if public_body = bodies_by_name[name] # Existing public body available_locales.each do |locale| PublicBody.with_locale(locale) do changed = {} field_list.each do |field_name| localized_field_name = (locale === I18n.default_locale) ? field_name : "#{field_name}.#{locale}" localized_value = field_names[localized_field_name] && row[field_names[localized_field_name]] + + # Tags are a special case, as we support adding to the field, not just setting a new value + if localized_field_name == 'tag_string' + if localized_value.nil? + localized_value = tag unless tag.empty? + else + if tag_behaviour == 'add' + localized_value = "#{localized_value} #{tag}" unless tag.empty? + localized_value = "#{localized_value} #{public_body.tag_string}" + end + end + end + if !localized_value.nil? and public_body.send(field_name) != localized_value changed[field_name] = "#{public_body.send(field_name)}: #{localized_value}" public_body.send("#{field_name}=", localized_value) @@ -422,6 +429,11 @@ class PublicBody < ActiveRecord::Base field_list.each do |field_name| localized_field_name = (locale === I18n.default_locale) ? field_name : "#{field_name}.#{locale}" localized_value = field_names[localized_field_name] && row[field_names[localized_field_name]] + + if localized_field_name == 'tag_string' and tag_behaviour == 'add' + localized_value = "#{localized_value} #{tag}" unless tag.empty? + end + if !localized_value.nil? and public_body.send(field_name) != localized_value changed[field_name] = localized_value public_body.send("#{field_name}=", localized_value) @@ -431,7 +443,6 @@ class PublicBody < ActiveRecord::Base unless changed.empty? notes.push "line #{line.to_s}: creating new authority '#{name}' (locale: #{locale}):\n\t#{changed.to_json}" public_body.publication_scheme = public_body.publication_scheme || "" - public_body.tag_string = tag public_body.last_edit_editor = editor public_body.last_edit_comment = 'Created from spreadsheet' public_body.save! @@ -446,7 +457,7 @@ class PublicBody < ActiveRecord::Base # Give an error listing ones that are to be deleted deleted_ones = set_of_existing - set_of_importing if deleted_ones.size > 0 - notes.push "notes: Some " + tag + " bodies are in database, but not in CSV file:\n " + Array(deleted_ones).join("\n ") + "\nYou may want to delete them manually.\n" + notes.push "Notes: Some " + tag + " bodies are in database, but not in CSV file:\n " + Array(deleted_ones).join("\n ") + "\nYou may want to delete them manually.\n" end # Rollback if a dry run, or we had errors @@ -515,7 +526,7 @@ class PublicBody < ActiveRecord::Base end def notes_without_html # assume notes are reasonably behaved HTML, so just use simple regexp on this - self.notes.gsub(/<\/?[^>]*>/, "") + self.notes.nil? ? '' : self.notes.gsub(/<\/?[^>]*>/, "") end def json_for_api diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb index e244aaac9..f46ce33c5 100644 --- a/app/models/request_mailer.rb +++ b/app/models/request_mailer.rb @@ -61,7 +61,8 @@ class RequestMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "New response to your FOI request - " + info_request.title @body = { :incoming_message => incoming_message, :info_request => info_request, :url => url } @@ -79,7 +80,8 @@ class RequestMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = user.name_and_email @subject = "Delayed response to your FOI request - " + info_request.title @body = { :info_request => info_request, :url => url } @@ -97,7 +99,8 @@ class RequestMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = user.name_and_email @subject = "You're long overdue a response to your FOI request - " + info_request.title @body = { :info_request => info_request, :url => url } @@ -116,7 +119,8 @@ class RequestMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "Was the response you got to your FOI request any good?" @body = { :incoming_message => incoming_message, :info_request => info_request, :url => url } @@ -126,7 +130,8 @@ class RequestMailer < ApplicationMailer def old_unclassified_updated(info_request) @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "Someone has updated the status of your request" url = main_url(request_url(info_request)) @@ -146,7 +151,8 @@ class RequestMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "Clarify your FOI request - " + info_request.title @body = { :incoming_message => incoming_message, :info_request => info_request, :url => url } @@ -156,7 +162,8 @@ class RequestMailer < ApplicationMailer def comment_on_alert(info_request, comment) @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "Somebody added a note to your FOI request - " + info_request.title @body = { :comment => comment, :info_request => info_request, :url => main_url(comment_url(comment)) } @@ -164,7 +171,8 @@ class RequestMailer < ApplicationMailer def comment_on_alert_plural(info_request, count, earliest_unalerted_comment) @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from, # not much we can do if the user's email is broken - 'Auto-Submitted' => 'auto-generated' # http://tools.ietf.org/html/rfc3834 + 'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'X-Auto-Response-Suppress' => 'OOF' @recipients = info_request.user.name_and_email @subject = "Some notes have been added to your FOI request - " + info_request.title @body = { :count => count, :info_request => info_request, :url => main_url(comment_url(earliest_unalerted_comment)) } diff --git a/app/models/track_mailer.rb b/app/models/track_mailer.rb index 4b7c603a7..85b1fedd8 100644 --- a/app/models/track_mailer.rb +++ b/app/models/track_mailer.rb @@ -26,6 +26,12 @@ class TrackMailer < ApplicationMailer @body = { :user => user, :email_about_things => email_about_things, :unsubscribe_url => unsubscribe_url } end + def contact_from_name_and_email + contact_name = MySociety::Config.get("TRACK_SENDER_NAME", 'Alaveteli') + contact_email = MySociety::Config.get("TRACK_SENDER_EMAIL", 'contact@localhost') + return "#{contact_name} <#{contact_email}>" + 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 @@ -40,6 +46,8 @@ class TrackMailer < ApplicationMailer return false end for user in users + next if !user.should_be_emailed? + 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 @@ -85,7 +93,11 @@ class TrackMailer < ApplicationMailer # If we have anything to send, then send everything for the user in one mail if email_about_things.size > 0 # Send the email + + previous_locale = I18n.locale + I18n.locale = user.get_locale TrackMailer.deliver_event_digest(user, email_about_things) + I18n.locale = previous_locale end # Record that we've now sent those alerts to that user diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index 1cd957549..b74f7dad5 100644 --- a/app/models/track_thing.rb +++ b/app/models/track_thing.rb @@ -22,6 +22,7 @@ # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # # $Id: track_thing.rb,v 1.53 2009-09-17 21:10:05 francis Exp $ +require 'set' class TrackThing < ActiveRecord::Base belongs_to :tracking_user, :class_name => 'User' @@ -67,6 +68,63 @@ class TrackThing < ActiveRecord::Base TrackThing.track_type_description(self.track_type) end + def track_query_description + # XXX this is very brittle... we should probably ask users + # simply to name their tracks when they make them? + self.track_query = self.track_query.gsub(/([()]|OR)/, "") + filters = self.track_query.scan /\b\S+:\S+\b/ + text = self.track_query + varieties = Set.new + date = "" + statuses = Set.new + for filter in filters + text = text.sub(filter, "") + if filter =~ /variety:user/ + varieties << _("users") + end + if filter =~ /variety:comment/ + varieties << _("comments") + end + if filter =~ /variety:authority/ + varieties << _("authorities") + end + if filter =~ /(variety:(sent|followup_sent|response)|latest_status)/ + varieties << _("requests") + end + if filter =~ /[0-9\/]+\.\.[0-9\/]+/ + date = _("between two dates") + end + if filter =~ /(rejected|not_held)/ + statuses << _("unsuccessful") + end + if filter =~ /(:successful|:partially_successful)/ + statuses << _("successful") + end + if filter =~ /waiting/ + statuses << _("awaiting a response") + end + end + if filters.empty? + text = self.track_query + end + descriptions = [] + if varieties.include? _("requests") + descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).join(_(' or '))) + varieties -= [_("requests")] + end + if descriptions.empty? and varieties.empty? + varieties << _("anything") + end + descriptions += Array(varieties) + text = text.strip + descriptions = descriptions.join(_(" or ")) + if !text.empty? + descriptions += _("{{list_of_things}} matching text '{{search_query}}'", :list_of_things => "", :search_query => text) + end + return descriptions + end + + def TrackThing.create_track_for_request(info_request) track_thing = TrackThing.new track_thing.track_type = 'request_updates' @@ -119,6 +177,11 @@ class TrackThing < ActiveRecord::Base end end track_thing.track_query = query + # XXX should extract requested_by:, request:, requested_from: + # and stick their values into the respective relations. + # Should also update "params" to make the list_description + # nicer and more generic. It will need to do some clever + # parsing of the query to do this nicely return track_thing end @@ -129,16 +192,16 @@ class TrackThing < ActiveRecord::Base if self.track_type == 'request_updates' @params = { # Website - :list_description => "'<a href=\"/request/" + CGI.escapeHTML(self.info_request.url_title) + "\">" + CGI.escapeHTML(self.info_request.title) + "</a>', a request", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how + :list_description => _("'{{link_to_request}}', a request", :link_to_request => "<a href=\"/request/" + CGI.escapeHTML(self.info_request.url_title) + "\">" + CGI.escapeHTML(self.info_request.title) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how :verb_on_page => _("Track this request by email"), :verb_on_page_already => _("You are already tracking this request by email"), # Email - :title_in_email => "New updates for the request '" + self.info_request.title + "'", - :title_in_rss => "New updates for the request '" + self.info_request.title + "'", + :title_in_email => _("New updates for the request '{{request_title}}'", :request_title => self.info_request.title), + :title_in_rss => _("New updates for the request '{{request_title}}'", :request_title => self.info_request.title), # Authentication - :web => "To follow updates to the request '" + CGI.escapeHTML(self.info_request.title) + "'", - :email => "Then you will be emailed whenever the request '" + CGI.escapeHTML(self.info_request.title) + "' is updated.", - :email_subject => "Confirm you want to follow updates to the request '" + self.info_request.title + "'", + :web => _("To follow updates to the request '{{request_title}}'", :request_title => CGI.escapeHTML(self.info_request.title)), + :email => _("Then you will be emailed whenever the request '{{request_title}}' is updated.", :request_title => CGI.escapeHTML(self.info_request.title)), + :email_subject => _("Confirm you want to follow updates to the request '{{request_title}}'", :request_title => self.info_request.title), # RSS sorting :feed_sortby => 'newest' } @@ -180,7 +243,7 @@ class TrackThing < ActiveRecord::Base elsif self.track_type == 'public_body_updates' @params = { # Website - :list_description => "'<a href=\"/body/" + CGI.escapeHTML(self.public_body.url_name) + "\">" + CGI.escapeHTML(self.public_body.name) + "</a>', a public authority", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how + :list_description => _("'{{link_to_authority}}', a public authority", :link_to_authority => "<a href=\"/body/" + CGI.escapeHTML(self.public_body.url_name) + "\">" + CGI.escapeHTML(self.public_body.name) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how :verb_on_page => _("Track requests to {{public_body_name}} by email",:public_body_name=>CGI.escapeHTML(self.public_body.name)), :verb_on_page_already => _("You are already tracking requests to {{public_body_name}} by email", :public_body_name=>CGI.escapeHTML(self.public_body.name)), # Email @@ -196,7 +259,7 @@ class TrackThing < ActiveRecord::Base elsif self.track_type == 'user_updates' @params = { # Website - :list_description => "'<a href=\"/user/" + CGI.escapeHTML(self.tracked_user.url_name) + "\">" + CGI.escapeHTML(self.tracked_user.name) + "</a>', a person", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how + :list_description => _("'{{link_to_user}}', a person", :link_to_user => "<a href=\"/user/" + CGI.escapeHTML(self.tracked_user.url_name) + "\">" + CGI.escapeHTML(self.tracked_user.name) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how :verb_on_page => _("Track this person by email"), :verb_on_page_already => _("You are already tracking this person by email"), # Email @@ -212,7 +275,7 @@ class TrackThing < ActiveRecord::Base elsif self.track_type == 'search_query' @params = { # Website - :list_description => "'<a href=\"/search/" + CGI.escapeHTML(self.track_query) + "/newest\">" + CGI.escapeHTML(self.track_query) + "</a>' in new requests/responses", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how + :list_description => "<a href=\"/search/" + CGI.escapeHTML(self.track_query) + "/newest/advanced\">" + self.track_query_description + "</a>", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how :verb_on_page => _("Track things matching this search by email"), :verb_on_page_already => _("You are already tracking things matching this search by email"), # Email diff --git a/app/models/user.rb b/app/models/user.rb index fddb6b035..e98d777b1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -16,6 +16,8 @@ # admin_level :string(255) default("none"), not null # ban_text :text default(""), not null # about_me :text default(""), not null +# email_bounced_at :datetime +# email_bounce_message :text default(""), not null # # models/user.rb: @@ -96,6 +98,15 @@ class User < ActiveRecord::Base end end end + + def get_locale + if !self.locale.nil? + locale = self.locale + else + locale = I18n.locale + end + return locale.to_s + end def visible_comments self.comments.find(:all, :conditions => 'visible') @@ -341,15 +352,37 @@ class User < ActiveRecord::Base } end + def record_bounce(message) + self.email_bounced_at = Time.now + self.email_bounce_message = message + self.save! + end + + def should_be_emailed? + return (self.email_confirmed && self.email_bounced_at.nil?) + end + + ## Private instance methods private + def create_new_salt + self.salt = self.object_id.to_s + rand.to_s + end + + ## Class methods def User.encrypted_password(password, salt) string_to_hash = password + salt # XXX need to add a secret here too? Digest::SHA1.hexdigest(string_to_hash) end - - def create_new_salt - self.salt = self.object_id.to_s + rand.to_s + + def User.record_bounce_for_email(email, message) + user = User.find_user_by_email(email) + return false if user.nil? + + if user.email_bounced_at.nil? + user.record_bounce(message) + end + return true end end diff --git a/app/models/user_mailer.rb b/app/models/user_mailer.rb index 0972e167d..7adf5b63c 100644 --- a/app/models/user_mailer.rb +++ b/app/models/user_mailer.rb @@ -46,7 +46,5 @@ class UserMailer < ApplicationMailer @body[:old_email] = old_email @body[:new_email] = new_email end - - end |