# app/controllers/track_controller.rb: # Publically visible email alerts and RSS - think an alert system crossed with # social bookmarking. # # Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class TrackController < ApplicationController protect_from_forgery # See ActionController::RequestForgeryProtection for details before_filter :medium_cache # Track all updates to a particular request def track_request @info_request = InfoRequest.find_by_url_title!(params[:url_title]) @track_thing = TrackThing.create_track_for_request(@info_request) return atom_feed_internal if params[:feed] == 'feed' if self.track_set redirect_to request_url(@info_request) end end # Track all new/successful requests def track_list @view = params[:view] if @view == 'recent' || @view.nil? # the blank one for backwards compatibility @track_thing = TrackThing.create_track_for_all_new_requests elsif @view == 'successful' @track_thing = TrackThing.create_track_for_all_successful_requests else raise "unknown request list view " + @view.to_s end return atom_feed_internal if params[:feed] == 'feed' if self.track_set redirect_to request_list_url(:view => @view) end end # Track all updates to a particular public body def track_public_body @public_body = PublicBody.find_by_url_name_with_historic(params[:url_name]) raise ActiveRecord::RecordNotFound.new("None found") if @public_body.nil? # If found by historic name, or alternate locale name, redirect to new name if @public_body.url_name != params[:url_name] redirect_to track_public_body_url(:url_name => @public_body.url_name, :feed => params[:feed], :event_type => params[:event_type]) return end if params[:event_type] @track_thing = TrackThing.create_track_for_public_body(@public_body, params[:event_type]) else @track_thing = TrackThing.create_track_for_public_body(@public_body) end return atom_feed_internal if params[:feed] == 'feed' if self.track_set redirect_to public_body_url(@public_body) end end # Track a user def track_user @track_user = User.find_by_url_name(params[:url_name]) raise ActiveRecord::RecordNotFound.new("No such user") if @track_user.nil? @track_thing = TrackThing.create_track_for_user(@track_user) return atom_feed_internal if params[:feed] == 'feed' if self.track_set redirect_to user_url(@track_user) end end # Track a search term def track_search_query @query = params[:query_array] # XXX more hackery to make alternate formats still work with query_array if /^(.*)\.json$/.match(@query) @query = $1 params[:format] = "json" end @track_thing = TrackThing.create_track_for_search_query(@query) return atom_feed_internal if params[:feed] == 'feed' if self.track_set if @query.scan("variety").length == 1 # we're making a track for a simple filter, for which # there's an expression in the UI (rather than relying # on index:value strings in the query) if @query =~ /variety:user/ postfix = "users" @query.sub!("variety:user", "") elsif @query =~ /variety:authority/ postfix = "bodies" @query.sub!("variety:authority", "") elsif @query =~ /variety:sent/ postfix = "requests" @query.sub!("variety:sent", "") end @query.strip! end redirect_to search_url([@query, postfix]) end end # Generic request tracker - set @track_thing before calling def track_set if @user @existing_track = TrackThing.find_by_existing_track(@user, @track_thing) if @existing_track flash[:notice] = _("You are already following updates about {{track_description}}", :track_description => @track_thing.params[:list_description]) return true end end if not authenticated?(@track_thing.params) return false end @track_thing.track_medium = 'email_daily' @track_thing.tracking_user_id = @user.id @track_thing.save! if @user.receive_email_alerts flash[:notice] = _('You will now be emailed updates about {{track_description}}. Prefer not to receive emails?', :track_description => @track_thing.params[:list_description], :change_email_alerts_url => url_for(:controller => "user", :action => "wall", :url_name => @user.url_name)) else flash[:notice] = _('You are now following updates about {{track_description}}', :track_description => @track_thing.params[:list_description], :wall_url_user => url_for(:controller => "user", :action => "wall", :url_name => @user.url_name)) end return true end # Old-Style atom track. We're phasing this out, so for now issue a # 301 Redirect. Most aggregators should honour this, but we should # keep an eye on the logs to see which ones are still used before # deleting this (or for safety, we may wish to move them to a new # table) def atom_feed @track_thing = TrackThing.find(params[:track_id].to_i) if @track_thing.track_medium != 'feed' raise "can only view feeds for feed tracks, not email ones" end redirect_to do_track_url(@track_thing, 'feed'), :status => :moved_permanently end def atom_feed_internal @xapian_object = perform_search([InfoRequestEvent], @track_thing.track_query, @track_thing.params[:feed_sortby], nil, 25, 1) respond_to do |format| format.json { render :json => @xapian_object.results.map { |r| r[:model].json_for_api(true, lambda { |t| view_context.highlight_and_excerpt(t, @xapian_object.words_to_highlight, 150) } ) } } format.any { render :template => 'track/atom_feed.atom', :layout => false, :content_type => 'application/atom+xml' } end end # Change or delete a track def update track_thing = TrackThing.find(params[:track_id].to_i) if not authenticated_as_user?(track_thing.tracking_user, :web => _("To cancel this alert"), :email => _("Then you can cancel the alert."), :email_subject => _("Cancel a {{site_name}} alert",:site_name=>site_name) ) # do nothing - as "authenticated?" has done the redirect to signin page for us return end new_medium = params[:track_medium] if new_medium == 'delete' track_thing.destroy flash[:notice] = _("You are no longer following {{track_description}}.", :track_description => track_thing.params[:list_description]) redirect_to params[:r] # Reuse code like this if we let medium change again. #elsif new_medium == 'email_daily' # track_thing.track_medium = new_medium # track_thing.created_at = Time.now() # as created_at is used to limit the alerts to start with # track_thing.save! # flash[:notice] = "You are now tracking " + track_thing.params[:list_description] + " by email daily" # redirect_to user_url(track_thing.tracking_user) else raise "new medium not handled " + new_medium end end # Remove all tracks of a certain type (e.g. requests / users / bodies) def delete_all_type user_id = User.find(params[:user].to_i) if not authenticated_as_user?(user_id, :web => _("To cancel these alerts"), :email => _("Then you can cancel the alerts."), :email_subject => _("Cancel some {{site_name}} alerts",:site_name=>site_name) ) # do nothing - as "authenticated?" has done the redirect to signin page for us return end track_type = params[:track_type] flash[:notice] = _("You will no longer be emailed updates for those alerts") for track_thing in TrackThing.find(:all, :conditions => [ "track_type = ? and tracking_user_id = ?", track_type, user_id ]) track_thing.destroy end flash[:notice] += "" redirect_to params[:r] end end