diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/application_controller.rb | 86 | ||||
-rw-r--r-- | app/controllers/i_controller.rb | 13 | ||||
-rw-r--r-- | app/controllers/users_controller.rb | 180 | ||||
-rw-r--r-- | app/helpers/application_helper.rb | 18 | ||||
-rw-r--r-- | app/models/tweet.rb | 18 | ||||
-rw-r--r-- | app/views/main/index.html.haml | 8 | ||||
-rw-r--r-- | app/views/shared/_tweet.html.haml | 4 | ||||
-rw-r--r-- | app/views/shared/_tweet.json.jbuilder | 30 | ||||
-rw-r--r-- | app/views/shared/tweets.html.haml | 13 | ||||
-rw-r--r-- | app/views/users/show.json.jbuilder | 2 |
10 files changed, 188 insertions, 184 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4973e08..c0af3c8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,64 +1,35 @@ # -*- coding: utf-8 -*- class ApplicationController < ActionController::Base protect_from_forgery - before_filter :set_format, :get_include_user, :get_include_user_stats + before_filter :set_format after_filter :xhtml - - def set_format - unless request.format == :json || request.format == :html - request.format = :html - end - end - - def xhtml - if request.format == :html - response.content_type = "application/xhtml+xml" - - # remove invalid charactors - response.body = response.body.gsub(/[\x0-\x8\xb\xc\xe-\x1f]/, "") - end - end - - def get_include_user - @include_user ||= get_bool(params[:include_user]) - end - - def get_include_user_stats - if @include_user_stats ||= get_bool(params[:include_user_stats]) - @include_user = true - end - end - - def render_page(a = nil, &blk) - @items = (a || blk.call).page(page || 1).per(count) - @page_param = true - - render "shared/tweets" - end + before_filter :get_include_user def render_timeline(a = nil, &blk) @items = a || blk.call - if max_id - @items = @items.where("tweets.id <= ?", max_id) - end + @items = @items.where("tweets.id <= ?", max_id) if max_id + @items = @items.where("tweets.id > ?", since_id) if since_id - if since_id - @items = @items.where("tweets.id > ?", since_id) + if @force_page || page + @items = @items.page(page || 1).per(count) + else + @items = @items.limit(count) end - @items = @items.page(1).per(count) - render "shared/tweets" end + # params def page; get_int(params[:page], nil){|i| i > 0} end - def count; get_int(params[:count], 10){|i| (1..100) === i} end - def max_id; get_int(params[:max_id], nil){|i| i >= 0} end - def since_id; get_int(params[:since_id], nil){|i| i >= 0} end + def user_limit; get_int(params[:limit], 20){|i| i >= 0} end + + def force_page + @force_page = true + end def order case params[:order] @@ -71,21 +42,32 @@ class ApplicationController < ActionController::Base end end - def all; get_bool(params[:all]) end + private + def set_format + unless [:json, :html].include?(request.format.to_sym) + request.format = :html + end + end + + def xhtml + if request.format == :html + response.content_type = "application/xhtml+xml" + + # remove invalid charactors + response.body = response.body.gsub(/[\x0-\x8\xb\xc\xe-\x1f]/, "") + end + end - def full; get_bool(params[:full]) end + def get_include_user + @include_user ||= get_bool(params[:include_user]) + end - private def get_bool(str) - if /^(t.*|1)$/ =~ str - true - else - false - end + /^(t|true|1)$/ =~ str end def get_int(str, default = 0, &blk) - if str =~ /^\d+$/ + if str =~ /^[1-9]\d*$/ i = str.to_i if !block_given? || blk.call(i) return i diff --git a/app/controllers/i_controller.rb b/app/controllers/i_controller.rb index 89a887c..46c66b4 100644 --- a/app/controllers/i_controller.rb +++ b/app/controllers/i_controller.rb @@ -1,22 +1,26 @@ class IController < ApplicationController + before_filter :force_page, :only => [:best, :recent] + def best @title = "Best Tweets" - render_page do + render_timeline do Tweet .reacted - .order_by_reactions + .not_protected .original + .order_by_reactions end end def recent @title = "Recent Best Tweets" - render_page do + render_timeline do Tweet .recent .reacted - .order_by_reactions + .not_protected .original + .order_by_reactions end end @@ -25,6 +29,7 @@ class IController < ApplicationController render_timeline do Tweet .reacted + .not_protected .order_by_id end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index aeda688..dbd1206 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,10 +1,13 @@ class UsersController < ApplicationController - before_filter :get_user, :except => [:show, :favoriters] - before_filter :get_user_b + before_filter :force_page, :only => [:best, :recent] + before_filter :require_user, :except => [:show, :favoriters] + before_filter :include_user_b, :only => [:favorited_by, :retweeted_by, :given_favorites_to, :given_retweets_to] + after_filter :check_protected def best @title = "@#{@user.screen_name}'s Best Tweets" - render_page do + + render_timeline do case order when :favorite @user.tweets.reacted.order_by_favorites @@ -18,7 +21,8 @@ class UsersController < ApplicationController def recent @title = "@#{@user.screen_name}'s Recent Best Tweets" - render_page do + + render_timeline do case order when :favorite @user.tweets.recent.reacted.order_by_favorites @@ -31,11 +35,10 @@ class UsersController < ApplicationController end def timeline - raise Aclog::Exceptions::UserProtected if @user.protected - @title = "@#{@user.screen_name}'s Newest Tweets" + render_timeline do - if all + if get_bool(params[:all]) @user.tweets.order_by_id else @user.tweets.reacted.order_by_id @@ -45,6 +48,7 @@ class UsersController < ApplicationController def discovered @title = "@#{@user.screen_name}'s Recent Discoveries" + render_timeline do case params[:tweets] when /^fav/ @@ -58,59 +62,42 @@ class UsersController < ApplicationController end def info - raise Aclog::Exceptions::UserNotRegistered unless @user.account + raise Aclog::Exceptions::UserNotRegistered unless @user.registered? @title = "@#{@user.screen_name} (#{@user.name})'s Profile" - respond_to do |format| - format.html - format.json do - @include_user_stats = true - end - end + @include_user_stats = true end def favorited_by if @user_b - @title = "@#{@user.screen_name}'s Tweets" - render_timeline(@user.tweets.favorited_by(@user_b).order_by_id) + render_user_to_user else - @title = "Who Favorited @#{@user.screen_name}" - @event_type = "favs" - render_users_by(:favorite) + render_users_ranking end end def retweeted_by if @user_b - @title = "@#{@user.screen_name}'s Tweets" - render_timeline(@user.tweets.retweeted_by(@user_b).order_by_id) + render_user_to_user else - @title = "Who Retweeted @#{@user.screen_name}" - @event_type = "retweets" - render_users_by(:retweet) + render_users_ranking end end def given_favorites_to if @user_b - @title = "@#{@user_b.screen_name}'s Tweets" - render_timeline(@user_b.tweets.favorited_by(@user).order_by_id) + render_user_to_user else - @title = "@#{@user.screen_name}'s Favorites" - @event_type = "favs" - render_users_to(:favorite) + render_users_ranking end end def given_retweets_to if @user_b - @title = "@#{@user_b.screen_name}'s Tweets" - render_timeline(@user_b.tweets.retweeted_by(@user).order_by_id) + render_user_to_user else - @title = "@#{@user.screen_name}'s Retweets" - @event_type = "retweets" - render_users_to(:retweet) + render_users_ranking end end @@ -130,15 +117,7 @@ class UsersController < ApplicationController @title = "\"#{helpers.strip_tags(helpers.format_tweet_text(@item.text))[0...30]}\" from @#{@user.screen_name}" @title_b = "@#{@user.screen_name}'s Tweet" - respond_to do |format| - format.html do - @full = full - end - - format.json do - render "shared/_tweet", :locals => {:item => @item} - end - end + @full = get_bool(params[:full]) end # only json @@ -152,43 +131,63 @@ class UsersController < ApplicationController end private - def render_users_by(event) - case event - when :favorite - pr = -> tweet{tweet.favorites} - when :retweet - pr = -> tweet{tweet.retweets} - end - - @usermap = @user.tweets - .order_by_id - .limit(100) - .inject(Hash.new(0)){|hash, tweet| pr.call(tweet).each{|event| hash[event.user_id] += 1}; hash} - .sort_by{|id, count| -count} + def render_users_ranking + by = -> model do + model.joins( + "INNER JOIN (" + + "SELECT id FROM tweets WHERE tweets.user_id = #{@user.id} ORDER BY id DESC LIMIT 100" + + ") target ON tweet_id = target.id") + end - render "shared/users" - end + to = -> model do + Tweet.joins( + "INNER JOIN (" + + "SELECT tweet_id FROM #{model.table_name} WHERE #{model.table_name}.user_id = #{@user.id} ORDER BY id DESC LIMIT 500" + + ") action ON tweets.id = action.tweet_id") + end - def render_users_to(event) - case event - when :favorite - es = @user.favorites - when :retweet - es = @user.retweets + case params[:action].to_sym + when :favorited_by + @title = "Who Favorited @#{@user.screen_name}" + users_object = by.call(Favorite) + when :retweeted_by + @title = "Who Retweeted @#{@user.screen_name}" + users_object = by.call(Retweet) + when :given_favorites_to + @title = "@#{@user.screen_name}'s Favorites" + users_object = to.call(Favorite) + when :given_retweets_to + @title = "@#{@user.screen_name}'s Retweets" + users_object = to.call(Retweet) end - @usermap = es - .order_by_id - .limit(500) - .map{|e| Tweet.cached(e.tweet_id)} - .compact - .inject(Hash.new(0)){|hash, tweet| hash[tweet.user_id] += 1; hash} - .sort_by{|user_id, count| -count} + @usermap = users_object + .inject(Hash.new(0)){|hash, obj| hash[obj.user_id] += 1; hash} + .sort_by{|id, count| -count} render "shared/users" end - def get_user + def render_user_to_user + render_timeline do + case params[:action].to_sym + when :favorited_by + @title = "@#{@user.screen_name}'s Tweets" + @user.tweets.favorited_by(@user_b).order_by_id + when :retweeted_by + @title = "@#{@user.screen_name}'s Tweets" + @user.tweets.retweeted_by(@user_b).order_by_id + when :given_favorites_to + @title = "@#{@user_b.screen_name}'s Tweets" + @user_b.tweets.favorited_by(@user).order_by_id + when :given_retweets_to + @title = "@#{@user_b.screen_name}'s Tweets" + @user_b.tweets.retweeted_by(@user).order_by_id + end + end + end + + def require_user if params[:screen_name] == "me" if session[:user_id] params[:user_id] = session[:user_id] @@ -198,34 +197,35 @@ class UsersController < ApplicationController end if params[:user_id] - #@user = User.cached(params[:user_id].to_i) - @user = User.cached(params[:user_id].to_i) + user = User.cached(params[:user_id].to_i) end - if !@user && params[:screen_name] - #@user = User.where(:screen_name => params[:screen_name]).first - @user = User.cached(params[:screen_name]) + if !user && params[:screen_name] + user = User.cached(params[:screen_name]) end - raise Aclog::Exceptions::UserNotFound unless @user - raise Aclog::Exceptions::UserNotRegistered if @user.protected? && !@user.registered? + raise Aclog::Exceptions::UserNotFound unless user + + @user = user end - def get_user_b - if params[:screen_name_b] == "me" - if session[:user_id] - params[:user_id_b] = session[:user_id] - else - raise Aclog::Exceptions::LoginRequired - end + def include_user_b + if params[:user_id_b] + user_b = User.cached(params[:user_id_b].to_i) end - if params[:user_id_b] - @user_b = User.cached(params[:user_id_b].to_i) + if !user_b && params[:screen_name_b] + user_b = User.where(:screen_name => params[:screen_name_b]).first end - if !@user_b && params[:screen_name_b] - @user_b = User.where(:screen_name => params[:screen_name_b]).first + @user_b = user_b + end + + def check_protected + if @user && @user.protected? && !@user.registered? + unless session[:account] && session[:account].user_id == @user.id + raise Aclog::Exceptions::UserProtected if @user.protected + end end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 149b814..1ce3b7b 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -39,9 +39,21 @@ module ApplicationHelper link_to(body, :controller => "users", :action => "best", :screen_name => screen_name) end - # _tweet - def show_count(c) - params[:action] == "show" ? (@full ? c : 100) : 20 + def user_limit + i = params[:limit].to_i + if i == 0 + if params[:action] == "show" + if params[:full] == "true" + return nil + else + return 100 + end + else + return 20 + end + else + return i + end end # utf8 diff --git a/app/models/tweet.rb b/app/models/tweet.rb index cc30889..98b4f84 100644 --- a/app/models/tweet.rb +++ b/app/models/tweet.rb @@ -1,8 +1,8 @@ class Tweet < ActiveRecord::Base belongs_to :user - has_many :favorites, :dependent => :delete_all - has_many :retweets, :dependent => :delete_all + has_many :favorites, ->{order("favorites.id")}, :dependent => :delete_all + has_many :retweets, ->{order("retweets.id")}, :dependent => :delete_all has_many :favoriters, ->{order("favorites.id")}, :through => :favorites, :source => :user has_many :retweeters, ->{order("retweets.id")}, :through => :retweets, :source => :user @@ -10,23 +10,23 @@ class Tweet < ActiveRecord::Base has_one :original, :through => :stolen_tweet, :source => :original scope :recent, -> do - where("tweeted_at > ?", Time.zone.now - 3.days) + where("tweets.tweeted_at > ?", Time.zone.now - 3.days) end scope :reacted, -> do - where("favorites_count > 0 OR retweets_count > 0") + where("tweets.favorites_count > 0 OR tweets.retweets_count > 0") end scope :order_by_id, -> do - order("id DESC") + order("tweets.id DESC") end scope :order_by_favorites, -> do - order("favorites_count DESC") + order("tweets.favorites_count DESC") end scope :order_by_retweets, -> do - order("retweets_count DESC") + order("tweets.retweets_count DESC") end scope :order_by_reactions, -> do @@ -53,6 +53,10 @@ class Tweet < ActiveRecord::Base joins("LEFT JOIN stolen_tweets ON tweets.id = stolen_tweets.tweet_id").where(:stolen_tweets => {:tweet_id => nil}) end + scope :not_protected, -> do + includes(:user).where(:users => {:protected => false}) + end + def self.cached(id) Rails.cache.fetch("tweet/#{id}", :expires_in => 3.hour) do where(:id => id).first diff --git a/app/views/main/index.html.haml b/app/views/main/index.html.haml index 02d5b2b..7e1bbf2 100644 --- a/app/views/main/index.html.haml +++ b/app/views/main/index.html.haml @@ -4,8 +4,6 @@ %p UserStreams で登録ユーザーのふぁぼり・ふぁぼられ・RTを集めて表示するサービスです。あんふぁぼも反映されます。 %p - Favstar を参考に開発しています。現時点でトロフィー以外の機能はすべて使えるはずです。 -%p API も提供する予定です。about → api を見てください(まだ開発中であり、変更がある可能性もあります) .alert (04/04) 諸事情でアプリケーションを作り直しました。再認証(logout → login)すると新しいトークンで上書きされます。 @@ -13,14 +11,16 @@ = link_to "アプリ連携", "https://twitter.com/settings/applications" から不要な "AcLog" と "Aclog2" は解除しても大丈夫です。 %h4 - 今後の予定(2013/04/04) + 今後の予定(2013/04/16) %ul + %li ふぁぼ爆撃対策: TLふぁぼり(エタフォ)・ユーザーTLふぁぼり(fav2you)対策 %li 通知を細かく設定できるように %li パクリツイート対策 %li ふぁぼったー・Favstar からのデータの取り込み - %li ふぁぼ爆撃対策 %li トロフィー機能をいらないよね… %p + ふぁぼ爆撃(無差別なふぁぼなど)と判断された場合は数時間ふぁぼりの記録が停止されます。基準は相当高く設定しているので誤判定はまずないとは思いますがもしなにかあれば連絡ください。 +%p = link_to "ツイート", "https://twitter.com/share", :class => "twitter-share-button", :"data-text" => "aclog", :"data-count" => "none", :"data-url" => "http://aclog.koba789.com/" %hr %h5 diff --git a/app/views/shared/_tweet.html.haml b/app/views/shared/_tweet.html.haml index 3dd290b..c8c3a09 100644 --- a/app/views/shared/_tweet.html.haml +++ b/app/views/shared/_tweet.html.haml @@ -33,12 +33,12 @@ %dt %span.count= actions.count %span.type= type - - if actions.count > show_count(actions.count) + - if user_limit && params[:action] == "show" %span.full = link_to "show full", params.merge(:full => true) %dd %ul.inline - - actions.take(show_count(actions.count)).each do |m| + - actions.take(user_limit || actions.count).each do |m| %li = link_to_user_page m.screen_name do = image_tag m.profile_image_url, :alt => m.screen_name, :title => m.name diff --git a/app/views/shared/_tweet.json.jbuilder b/app/views/shared/_tweet.json.jbuilder index c048dee..15dae1b 100644 --- a/app/views/shared/_tweet.json.jbuilder +++ b/app/views/shared/_tweet.json.jbuilder @@ -1,26 +1,26 @@ json.(item, :id, :text, :source, :tweeted_at, :favorites_count, :retweets_count) -json.user do |json| +json.user do json.id item.user_id if @include_user json.partial! "shared/user", :user => item.user end end -json.favorites item.favorites.order("id") do |json, favorite| - json.user do |json| - json.id favorite.user_id - if @include_user - json.partial! "shared/user", :user => favorite.user - end - end -end -json.retweets item.retweets.order("id") do |json, retweet| - json.id retweet.id - json.user do |json| - json.id retweet.user_id - if @include_user - json.partial! "shared/user", :user => retweet.user +render_actions = -> name, data, render_id do + n = 0 + json.__send__(name, data) do |action| + json.id action.id if render_id + json.user do + json.id action.user_id + if @include_user && (!user_limit || n < user_limit) + json.partial! "shared/user", :user => action.user + end end + n += 1 end end + +render_actions.call(:favorites, item.favorites.includes(:user), false) +render_actions.call(:retweets, item.retweets.includes(:user), true) + diff --git a/app/views/shared/tweets.html.haml b/app/views/shared/tweets.html.haml index 0ab1a69..55e8e42 100644 --- a/app/views/shared/tweets.html.haml +++ b/app/views/shared/tweets.html.haml @@ -1,12 +1,11 @@ -- if @show_search +- if params[:action] == "search" = render :partial => "shared/search" .items = render :partial => "shared/tweet", :collection => @items, :as => :item .loading = image_tag "loading.gif", :alt => "loading...", :title => nil -- if @items - - if @page_param - = paginate(@items) - - elsif @items.last - .pagination - = link_to raw("Next ›"), params.merge(:max_id => @items.last.id - 1), :rel => :next +- if /offset/i =~ @items.to_sql + = paginate(@items) +- elsif @items.last + .pagination + = link_to raw("Next ›"), params.merge(:max_id => @items.last.id - 1), :rel => :next diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder new file mode 100644 index 0000000..bca1b00 --- /dev/null +++ b/app/views/users/show.json.jbuilder @@ -0,0 +1,2 @@ +json.partial! "shared/tweet", :item => @item + |