aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/assets/images/missing_profile_image.pngbin0 -> 9350 bytes
-rw-r--r--app/assets/stylesheets/_tweets.css.sass23
-rw-r--r--app/controllers/application_controller.rb18
-rw-r--r--app/controllers/i_controller.rb6
-rw-r--r--app/controllers/users_controller.rb8
-rw-r--r--app/helpers/application_helper.rb30
-rw-r--r--app/models/user.rb10
-rw-r--r--app/views/i/show.haml4
-rw-r--r--app/views/main/index.haml2
-rw-r--r--app/views/shared/_tweet.haml25
-rw-r--r--app/views/shared/_tweets.haml2
-rw-r--r--client/Gemfile1
-rw-r--r--client/Gemfile.lock9
-rw-r--r--client/worker.rb131
-rw-r--r--config/unicorn.rb2
-rw-r--r--lib/receiver/worker.rb4
-rw-r--r--public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css106
-rw-r--r--public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css.gzbin0 -> 767 bytes
-rw-r--r--public/assets/manifest-4b1ee8498d7a15fdf2a8795fb52ff876.json1
-rw-r--r--public/assets/missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.pngbin0 -> 9350 bytes
20 files changed, 257 insertions, 125 deletions
diff --git a/app/assets/images/missing_profile_image.png b/app/assets/images/missing_profile_image.png
new file mode 100644
index 0000000..3d1e0f9
--- /dev/null
+++ b/app/assets/images/missing_profile_image.png
Binary files differ
diff --git a/app/assets/stylesheets/_tweets.css.sass b/app/assets/stylesheets/_tweets.css.sass
index 818d099..a2a2706 100644
--- a/app/assets/stylesheets/_tweets.css.sass
+++ b/app/assets/stylesheets/_tweets.css.sass
@@ -61,8 +61,7 @@
//:border-radius 0 0 4px 4px
:padding 15px
//:background #edf0f4
- .favs_row,
- .retweets_row
+ .favs, .retweets
:margin-bottom 3px
.info
:width 60px
@@ -76,18 +75,18 @@
:font-size 14px
.type
:font-size 10px
- .users_content_fix
+ .height_fix
:float left
:height 48px
:width 0
- .users_content
+ .favoriters
:float left
- ul.users_row
- :list-style none
- li
- :float left
- img
- :width 48px
- :height 48px
- :vertical-align bottom
+ :list-style none
+ :width 480px
+ li
+ :float left
+ img
+ :width 48px
+ :height 48px
+ :vertical-align bottom
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 595eaf8..ef1614f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -17,13 +17,15 @@ class ApplicationController < ActionController::Base
return 1
end
- def get_user_cache(items)
- Hash[
- User.where(items
- .map{|m| [m.user_id, m.favorites.map{|u| u.user_id}, m.retweets.map{|u| u.user_id}]}
- .flatten
- .uniq.map{|m| "id = #{m}"}.join(" OR "))
- .map{|m| [m.id, m]}
- ]
+ def prepare_cache
+ # check
+ return unless @items
+
+ @favorite_cache = Favorite.where(@items.map{|m| "tweet_id = #{m.id}"}.join(" OR ")).sort_by{|m| m.id}.group_by{|m| m.tweet_id}
+ @retweet_cache = Retweet.where(@items.map{|m| "tweet_id = #{m.id}"}.join(" OR ")).sort_by{|m| m.id}.group_by{|m| m.tweet_id}
+ @user_cache = Hash[User.where(
+ (@items.to_a + @favorite_cache.values + @retweet_cache.values).flatten.map{|m| m.user_id}.uniq
+ .map{|m| "id = #{m}"}.join(" OR "))
+ .map{|m| [m.id, m]}]
end
end
diff --git a/app/controllers/i_controller.rb b/app/controllers/i_controller.rb
index c1a66f4..42b7111 100644
--- a/app/controllers/i_controller.rb
+++ b/app/controllers/i_controller.rb
@@ -1,8 +1,8 @@
class IController < ApplicationController
def show
id = params[:id].to_i
- @item = Tweet.find_by(:id => id)
- @user_cache = get_user_cache([@item])
- @title = "\"#{ApplicationController.helpers.strip_tags(ApplicationController.helpers.format_tweet_text(@item.text))[0...30]}\" from @#{@user_cache[@item.user_id].screen_name}"
+ @items = Tweet.where(:id => id).page(1)
+ prepare_cache
+ @title = "\"#{ApplicationController.helpers.strip_tags(ApplicationController.helpers.format_tweet_text(@items.first.text))[0...30]}\" from @#{@user_cache[@items.first.user_id].screen_name}"
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 1a944f7..4fe7b86 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -12,8 +12,8 @@ class UsersController < ApplicationController
else
@items = []
end
- @user_cache = get_user_cache(@items)
@title = "@#{screen_name}'s Best Tweets"
+ prepare_cache
end
def recent
@@ -29,8 +29,8 @@ class UsersController < ApplicationController
else
@items = []
end
- @user_cache = get_user_cache(@items)
@title = "@#{screen_name}'s Newest Tweets"
+ prepare_cache
end
def timeline
@@ -45,8 +45,8 @@ class UsersController < ApplicationController
else
@items = []
end
- @user_cache = get_user_cache(@items)
@title = "@#{screen_name}'s Newest Tweets"
+ prepare_cache
end
def my
@@ -67,8 +67,8 @@ class UsersController < ApplicationController
else
@items = []
end
- @user_cache = get_user_cache(@items)
@title = "@#{screen_name}'s Recent Discoveries"
+ prepare_cache
end
def info
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 8415602..93f7063 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -19,14 +19,36 @@ module ApplicationHelper
end
def status_url(tweet)
- "/#{@user_cache[tweet.user_id].screen_name}/status/#{tweet.id}"
+ "/#{u(tweet).screen_name}/status/#{tweet.id}"
end
def twitter_status_url(tweet)
- "https://twitter.com/#{@user_cache[tweet.user_id].screen_name}/status/#{tweet.id}"
+ "https://twitter.com/#{u(tweet).screen_name}/status/#{tweet.id}"
end
- def user_url(user_id)
- "/#{@user_cache[user_id].screen_name}"
+ def user_url(object)
+ "/#{u(object).screen_name}"
+ end
+
+ def u(object)
+ if object.is_a?(Tweet) ||
+ object.is_a?(Favorite) ||
+ object.is_a?(Retweet) ||
+ object.is_a?(Account)
+ u(object.user_id)
+ elsif object.is_a?(User)
+ object
+ elsif object.is_a?(Fixnum) ||
+ object.is_a?(Bignum)
+ @user_cache[object] || User.new(object)
+ end
+ end
+
+ def favoriters(item)
+ (@favorite_cache[item.id] || []).map{|m| u(m)}
+ end
+
+ def retweeters(item)
+ (@retweet_cache[item.id] || []).map{|m| u(m)}
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 9a090c8..d268fcb 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,14 @@
class User < ActiveRecord::Base
+ def initialize(attrs = {})
+ if attrs.is_a?(Fixnum) || attrs.is_a?(Bignum)
+ u = attrs
+ attrs = {:id => u}
+ end
+ attrs[:profile_image_url] ||= ActionController::Base.helpers.asset_path("missing_profile_image.png")
+ attrs[:name] ||= "Missing: id=#{u}"
+ super(attrs)
+ end
+
has_many :tweets, :dependent => :delete_all
has_many :favorites, :dependent => :delete_all
has_many :retweets, :dependent => :delete_all
diff --git a/app/views/i/show.haml b/app/views/i/show.haml
index c712cdc..2672287 100644
--- a/app/views/i/show.haml
+++ b/app/views/i/show.haml
@@ -1,3 +1 @@
-.items
- = render :partial => "shared/tweet", :locals => {:item => @item, :user_cache => @user_cache}
-
+= render :partial => "shared/tweets", :locals => {:items => @items}
diff --git a/app/views/main/index.haml b/app/views/main/index.haml
index c4ca3b0..ec53ace 100644
--- a/app/views/main/index.haml
+++ b/app/views/main/index.haml
@@ -4,7 +4,7 @@
Favstar クローンです。UserStreams つかってます。
= link_to "@KOBA789", "https://twitter.com/KOBA789"
さんにサーバーを貸していただけることになりました…!!ありがとうございます!ありがとうございます!!!
-%strong まだ開発途中段階のものですがとりあえず動いています。登録後接続まで最大30分かかります。
+%strong まだ開発途中段階のものです。うごかなかったらごめんね
%strong 動作のテスト中ですので、途中で登録をうちきったりあまりにふぁぼられ・ふぁぼりが多いユーザーの登録を削除する可能性もあります。
%div
URLとかについて
diff --git a/app/views/shared/_tweet.haml b/app/views/shared/_tweet.haml
index d46e69f..d4edec6 100644
--- a/app/views/shared/_tweet.haml
+++ b/app/views/shared/_tweet.haml
@@ -1,15 +1,15 @@
.item
.tweet
.avatar
- %a{href: user_url(item.user_id)}
- %img{src: user_cache[item.user_id].profile_image_url}
+ - user = u(item)
+ = link_to image_tag(user.profile_image_url), user_url(user), :title => user.name
.tweet_content_fix
.tweet_content
.user
%span.name
- = link_to user_cache[item.user_id].name, user_url(item.user_id)
+ = link_to user.name, user_url(user)
%span.screen_name
- = link_to "@#{user_cache[item.user_id].screen_name}", user_url(item.user_id)
+ = link_to "@#{user.screen_name}", user_url(user)
.text
= raw format_tweet_text(item.text)
.meta.clearfix
@@ -18,17 +18,14 @@
%span.source
= raw format_source_text(item.source)
.stats
- - [["FAVS", item.favorites, "favs_row"], ["RETWEETS", item.retweets, "retweets_row"]].each do |type, data, cssclass|
+ - [["FAVS", favoriters(item), "favs"], ["RETWEETS", retweeters(item), "retweets"]].each do |type, users, cssclass|
%div{:class => "#{cssclass} clearfix"}
.info
- %span.count= data.length
+ %span.count= users.size
%span.type= type
- .users_content_fix
- .users_content
- - data.map{|m| user_cache[m.user_id]}.each_slice(10) do |row|
- %ul.users_row.clearfix
- - row.select{|m| m}.each do |u|
- %li
- %a{href: user_url(u.id)}><
- %img{src: u.profile_image_url}
+ .height_fix
+ %ul.favoriters.clearfix
+ - users.each do |m|
+ %li
+ = link_to image_tag(m.profile_image_url), user_url(m), :title => m.name
diff --git a/app/views/shared/_tweets.haml b/app/views/shared/_tweets.haml
index 46ffe37..7dfb14b 100644
--- a/app/views/shared/_tweets.haml
+++ b/app/views/shared/_tweets.haml
@@ -1,4 +1,4 @@
.items
- = render :partial => "shared/tweet", :collection => items, :as => :item, :locals => {:user_cache => @user_cache}
+ = render :partial => "shared/tweet", :collection => items, :as => :item
- if items.size > 0
= paginate items
diff --git a/client/Gemfile b/client/Gemfile
index 58a9039..70e4e02 100644
--- a/client/Gemfile
+++ b/client/Gemfile
@@ -5,5 +5,4 @@ gem 'foreman'
gem 'settingslogic'
gem 'em-twitter'
-gem 'twitter'
gem 'yajl-ruby', :require => "yajl"
diff --git a/client/Gemfile.lock b/client/Gemfile.lock
index c52698d..28f9b51 100644
--- a/client/Gemfile.lock
+++ b/client/Gemfile.lock
@@ -6,20 +6,12 @@ GEM
http_parser.rb (~> 0.5)
simple_oauth (~> 0.1)
eventmachine (1.0.3)
- faraday (0.8.6)
- multipart-post (~> 1.1)
foreman (0.62.0)
thor (>= 0.13.6)
http_parser.rb (0.5.3)
- multi_json (1.6.1)
- multipart-post (1.2.0)
settingslogic (2.0.9)
simple_oauth (0.2.0)
thor (0.17.0)
- twitter (4.6.0)
- faraday (~> 0.8, < 0.10)
- multi_json (~> 1.0)
- simple_oauth (~> 0.2)
yajl-ruby (1.1.0)
PLATFORMS
@@ -29,5 +21,4 @@ DEPENDENCIES
em-twitter
foreman
settingslogic
- twitter
yajl-ruby
diff --git a/client/worker.rb b/client/worker.rb
index 578f63f..25ff766 100644
--- a/client/worker.rb
+++ b/client/worker.rb
@@ -1,6 +1,5 @@
require "time"
require "em-twitter"
-require "twitter"
require "yajl"
require "./settings"
require "./logger"
@@ -8,7 +7,7 @@ require "./logger"
module EM
class Connection
def send_chunk(data)
- puts data
+ #puts data
send_data(data + "\r\n")
end
end
@@ -18,13 +17,14 @@ class Worker
class DBProxyClient < EM::Connection
def initialize
@clients = []
+ @user_ids = []
@receive_buf = ""
end
def format_text(status)
- chars = status.text.to_s.split(//)
+ chars = status[:text].to_s.split(//)
- entities = status.attrs[:entities].values.flatten.sort_by{|entity| entity[:indices].first}
+ entities = status[:entities].values.flatten.sort_by{|entity| entity[:indices].first}
result = []
last_index = entities.inject(0) do |last_index, entity|
@@ -46,58 +46,58 @@ class Worker
end
def format_source(status)
- if status.source.index("<a")
- url = status.source.scan(/href="(.+?)"/).flatten.first
- name = status.source.scan(/>(.+?)</).flatten.first
+ if status[:source].index("<a")
+ url = status[:source].scan(/href="(.+?)"/).flatten.first
+ name = status[:source].scan(/>(.+?)</).flatten.first
"<url:#{CGI.escape(url)}:#{CGI.escape(name)}>"
else
- status.source
+ status[:source]
end
end
def send_user(user)
- out = {:id => user.id,
- :screen_name => user.screen_name,
- :name => user.name,
- :profile_image_url => user.profile_image_url_https}
+ out = {:id => user[:id],
+ :screen_name => user[:screen_name],
+ :name => user[:name],
+ :profile_image_url => user[:profile_image_url_https]}
send_chunk("USER #{Yajl::Encoder.encode(out)}")
end
def send_tweet(status)
- send_user(status.user)
- out = {:id => status.id,
+ send_user(status[:user])
+ out = {:id => status[:id],
:text => format_text(status),
:source => format_source(status),
- :tweeted_at => status.created_at,
- :user_id => status.user.id}
+ :tweeted_at => status[:created_at],
+ :user_id => status[:user][:id]}
send_chunk("TWEET #{Yajl::Encoder.encode(out)}")
- $logger.debug("Sent Tweet: #{status.id}")
+ $logger.debug("Sent Tweet: #{status[:id]}")
end
def send_favorite(source, target_object)
send_tweet(target_object)
send_user(source)
- out = {:tweet_id => target_object.id,
- :user_id => source.id}
+ out = {:tweet_id => target_object[:id],
+ :user_id => source[:id]}
send_chunk("FAVORITE #{Yajl::Encoder.encode(out)}")
- $logger.debug("Sent Favorite: #{source.id} => #{target_object.id}")
+ $logger.debug("Sent Favorite: #{source[:id]} => #{target_object[:id]}")
end
def send_unfavorite(source, target_object)
- out = {:tweet_id => target_object.id,
- :user_id => source.id}
+ out = {:tweet_id => target_object[:id],
+ :user_id => source[:id]}
send_chunk("UNFAVORITE #{Yajl::Encoder.encode(out)}")
- $logger.debug("Sent Unfavorite: #{source.id} => #{target_object.id}")
+ $logger.debug("Sent Unfavorite: #{source[:id]} => #{target_object[:id]}")
end
def send_retweet(status)
- send_tweet(status.retweeted_status)
- send_user(status.user)
- out = {:id => status.id,
- :tweet_id => status.retweeted_status.id,
- :user_id => status.user.id}
+ send_tweet(status[:retweeted_status])
+ send_user(status[:user])
+ out = {:id => status[:id],
+ :tweet_id => status[:retweeted_status][:id],
+ :user_id => status[:user][:id]}
send_chunk("RETWEET #{Yajl::Encoder.encode(out)}")
- $logger.debug("Sent Retweet: #{status.user.id} => #{status.retweeted_status.id}")
+ $logger.debug("Sent Retweet: #{status[:user][:id]} => #{status[:retweeted_status][:id]}")
end
def send_delete(status_id, user_id)
@@ -135,44 +135,46 @@ class Worker
$logger.error("Error: #{arg.last}")
when "ACCOUNT"
begin
- hash = ::Yajl::Parser.parse(arg.last, :symbolize_keys => true)
+ account = ::Yajl::Parser.parse(arg.last, :symbolize_keys => true)
rescue Yajl::ParseError
$logger.error("JSON Parse Error: #{json}")
next
end
- @clients << client = EM::Twitter::Client.connect({
+ @user_ids << account[:user_id]
+ @clients << client = EM::Twitter::Client.new({
:host => "userstream.twitter.com",
:path => "/1.1/user.json",
:oauth => {
:consumer_key => Settings.consumer_key,
:consumer_secret => Settings.consumer_secret,
- :token => hash[:oauth_token],
- :token_secret => hash[:oauth_token_secret]},
- :method => "GET"})
- user_id = hash[:user_id]
- row_id = hash[:id]
+ :token => account[:oauth_token],
+ :token_secret => account[:oauth_token_secret]},
+ :method => "GET",
+ # monyo
+ :user_id => account[:user_id],
+ :row_id => account[:id]})
client.on_error do |message|
- $logger.warn("Unknown Error(##{user_id}): #{message}")
+ $logger.warn("Unknown Error(##{client.options[:user_id]}): #{message}")
end
client.on_unauthorized do
# revoked?
- $logger.warn("Unauthorized(##{user_id})")
- send_chunk("UNAUTHORIZED #{row_id}&#{user_id}")
+ $logger.warn("Unauthorized(##{client.options[:user_id]})")
+ send_chunk("UNAUTHORIZED #{client.options[:row_id]}&#{client.options[:user_id]}")
client.connection.stop
@clients.delete(client)
end
client.on_enhance_your_calm do
# limit?
- $logger.warn("Enhance your calm(##{user_id})")
+ $logger.warn("Enhance your calm(##{client.options[:user_id]})")
end
client.on_no_data_received do
# (?)
- $logger.warn("No data received(##{user_id})")
+ $logger.warn("No data received(##{client.options[:user_id]})")
client.close_connection
end
@@ -180,51 +182,56 @@ class Worker
begin
hash = Yajl::Parser.parse(chunk, :symbolize_keys => true)
rescue Yajl::ParseError
- $logger.warn("Unexpected chunk(##{user_id}): #{chunk}")
+ $logger.warn("Unexpected chunk(##{client.options[:user_id]}): #{chunk}")
next
end
if hash[:warning]
- $logger.info("Stall warning(##{user_id}): #{hash[:warning]}")
+ $logger.info("Stall warning(##{client.options[:user_id]}): #{hash[:warning]}")
elsif hash[:delete] && hash[:delete][:status]
send_delete(hash[:delete][:status][:id], hash[:delete][:status][:user_id])
- elsif hash[:limit]
- $logger.warn("UserStreams Limit Event(##{user_id}): #{hash[:limit][:track]}")
- elsif hash[:event]
+ elsif hash.key?(:limit)
+ $logger.warn("UserStreams Limit Event(##{client.options[:user_id]}): #{hash[:limit][:track]}")
+ elsif hash.key?(:event)
case hash[:event]
when "favorite"
- source = Twitter::User.new(hash[:source])
- target_object = Twitter::Tweet.new(hash[:target_object])
- unless target_object.user.protected && target_object.user.id != user_id
+ source = hash[:source]
+ target_object = hash[:target_object]
+ unless target_object[:user][:protected] && target_object[:user][:id] != client.options[:user_id]
send_favorite(source, target_object)
end
when "unfavorite"
- send_unfavorite(Twitter::User.new(hash[:source]), Twitter::Tweet.new(hash[:target_object]))
+ send_unfavorite(hash[:source], hash[:target_object])
end
- elsif hash[:text] && hash[:user]
+ elsif hash.key?(:user)
# tweet
- status = Twitter::Tweet.new(hash)
- if status.retweeted_status && (status.retweeted_status.user.id == user_id ||
- status.user.id == user_id)
- $logger.debug("Retweet(##{user_id})")
- send_retweet(status)
- elsif status.user.id == user_id
- send_tweet(status)
+ if hash.key?(:retweeted_status)
+ # p user_id
+ # p status.retweeted_status.user.id
+ if @user_ids.include?(hash[:retweeted_status][:user][:id]) || @user_ids.include?(hash[:user][:id])
+ $logger.debug("Retweet(##{client.options[:user_id]})")
+ send_retweet(hash)
+ end
+ elsif @user_ids.include?(hash[:user][:id])
+ send_tweet(hash)
end
+ else
+ $logger.debug("??")
end
end
client.on_reconnect do |timeout, retries|
- $logger.warn("Reconnected(##{user_id}): #{retries}")
+ $logger.warn("Reconnected(##{client.options[:user_id]}): #{retries}")
end
client.on_max_reconnects do |timeout, retries|
- $logger.warn("Max reconnects: #{row_id}/#{user_id}")
+ $logger.warn("Max reconnects: #{client.options[:row_id]}/#{client.options[:user_id]}")
client.connection.stop
@clients.delete(client)
end
- $logger.info("Connected(##{user_id})")
+ client.connect
+ $logger.info("Connected(##{client.options[:user_id]})")
end
end
end
@@ -236,7 +243,7 @@ class Worker
end
def initialize
- $logger = Aclog::Logger.new(:warn)
+ $logger = Aclog::Logger.new(:debug)
end
def start
diff --git a/config/unicorn.rb b/config/unicorn.rb
index b8e045a..27b275d 100644
--- a/config/unicorn.rb
+++ b/config/unicorn.rb
@@ -1,4 +1,4 @@
-worker_processes 8
+worker_processes 4
working_directory File.expand_path("../../", __FILE__)
diff --git a/lib/receiver/worker.rb b/lib/receiver/worker.rb
index 860d890..8c44c76 100644
--- a/lib/receiver/worker.rb
+++ b/lib/receiver/worker.rb
@@ -64,7 +64,7 @@ class Receiver::Worker < DaemonSpawn::Base
$logger.info("Can't Save Retweet: Duplicate")
end
when "DELETE"
- tweet = Tweet.find_by(:id => json[:id]) || Retweet.find_by(:id => json[:id])
+ tweet = Tweet.find_by(:id => json[:tweet_id]) || Retweet.find_by(:id => json[:tweet_id])
if tweet
tweet.destroy
end
@@ -90,7 +90,7 @@ class Receiver::Worker < DaemonSpawn::Base
def unbind
$connections.delete_if{|k, v| v == self}
- $logger.info("Connection closed")
+ $logger.info("Connection closed: #{@worker_number}")
end
def send_account_all
diff --git a/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css b/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css
new file mode 100644
index 0000000..b75ad98
--- /dev/null
+++ b/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css
@@ -0,0 +1,106 @@
+.items {
+ width: 572px;
+ margin: 15px 0 15px 18px; }
+ .items .item {
+ margin: 15px 0; }
+ .items .item .tweet {
+ overflow: hidden;
+ background: white;
+ border: 1px solid #c1c5cb;
+ border-width: 1px 0;
+ padding: 15px; }
+ .items .item .tweet .avatar {
+ width: 60px;
+ float: left; }
+ .items .item .tweet .avatar img {
+ width: 48px;
+ height: 48px; }
+ .items .item .tweet .tweet_content_fix {
+ float: left;
+ width: 0;
+ height: 85px; }
+ .items .item .tweet .tweet_content {
+ float: left;
+ width: 473px; }
+ .items .item .tweet .tweet_content .user {
+ padding: 0 5px 15px;
+ font-weight: bold; }
+ .items .item .tweet .tweet_content .user .name {
+ font-size: 14px; }
+ .items .item .tweet .tweet_content .user .screen_name {
+ font-size: 12px; }
+ .items .item .tweet .tweet_content .user a {
+ color: #666666; }
+ .items .item .tweet .tweet_content .text {
+ font-size: 18px;
+ line-height: 25px;
+ padding: 0 5px 15px;
+ word-wrap: break-word; }
+ .items .item .tweet .tweet_content .meta {
+ padding: 0 5px 15px;
+ color: #666666;
+ font-size: 12px; }
+ .items .item .tweet .tweet_content .meta .twitter_bird {
+ display: block;
+ float: left; }
+ .items .item .tweet .tweet_content .meta .twitter_bird img {
+ vertical-align: top;
+ margin-right: 2px;
+ margin-top: 1px; }
+ .items .item .tweet .tweet_content .meta .created_at {
+ display: block;
+ float: left; }
+ .items .item .tweet .tweet_content .meta .source {
+ display: block;
+ float: right; }
+ .items .item .stats {
+ clear: both;
+ padding: 15px; }
+ .items .item .stats .favs, .items .item .stats .retweets {
+ margin-bottom: 3px; }
+ .items .item .stats .favs .info, .items .item .stats .retweets .info {
+ width: 60px;
+ float: left; }
+ .items .item .stats .favs .info .count,
+ .items .item .stats .favs .info .type, .items .item .stats .retweets .info .count,
+ .items .item .stats .retweets .info .type {
+ color: #666666;
+ display: block; }
+ .items .item .stats .favs .info .count, .items .item .stats .retweets .info .count {
+ font-weight: bold;
+ font-size: 14px; }
+ .items .item .stats .favs .info .type, .items .item .stats .retweets .info .type {
+ font-size: 10px; }
+ .items .item .stats .favs .height_fix, .items .item .stats .retweets .height_fix {
+ float: left;
+ height: 48px;
+ width: 0; }
+ .items .item .stats .favs .favoriters, .items .item .stats .retweets .favoriters {
+ float: left;
+ list-style: none;
+ width: 480px; }
+ .items .item .stats .favs .favoriters li, .items .item .stats .retweets .favoriters li {
+ float: left; }
+ .items .item .stats .favs .favoriters li img, .items .item .stats .retweets .favoriters li img {
+ width: 48px;
+ height: 48px;
+ vertical-align: bottom; }
+
+* {
+ margin: 0;
+ padding: 0;
+ font-family: "Ubuntu", sans-serif; }
+
+a {
+ text-decoration: none;
+ color: #3b5998; }
+
+img {
+ border: none; }
+
+.clearfix:after {
+ content: ".";
+ visibility: hidden;
+ display: block;
+ height: 0;
+ clear: both; }
diff --git a/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css.gz b/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css.gz
new file mode 100644
index 0000000..1962472
--- /dev/null
+++ b/public/assets/application-8ad8039145e9fbab6b0de0f554e4487b.css.gz
Binary files differ
diff --git a/public/assets/manifest-4b1ee8498d7a15fdf2a8795fb52ff876.json b/public/assets/manifest-4b1ee8498d7a15fdf2a8795fb52ff876.json
new file mode 100644
index 0000000..7803527
--- /dev/null
+++ b/public/assets/manifest-4b1ee8498d7a15fdf2a8795fb52ff876.json
@@ -0,0 +1 @@
+{"files":{"bird_gray_16-93f51980875017e26744056b62aaac22.png":{"logical_path":"bird_gray_16.png","mtime":"2013-03-09T14:41:39+09:00","size":1106,"digest":"93f51980875017e26744056b62aaac22"},"missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.png":{"logical_path":"missing_profile_image.png","mtime":"2013-03-16T16:45:26+09:00","size":9350,"digest":"d5d708680693a18615dfb8f5b1a5a96c"},"rails-bc7d436ef8afbf0f88829742a43ba3a4.png":{"logical_path":"rails.png","mtime":"2013-02-25T21:20:52+09:00","size":6646,"digest":"bc7d436ef8afbf0f88829742a43ba3a4"},"application-47a9a60feaec5625a9c66b1c985a1179.js":{"logical_path":"application.js","mtime":"2013-03-09T01:51:23+09:00","size":743,"digest":"47a9a60feaec5625a9c66b1c985a1179"},"application-8ad8039145e9fbab6b0de0f554e4487b.css":{"logical_path":"application.css","mtime":"2013-03-16T18:11:28+09:00","size":3584,"digest":"8ad8039145e9fbab6b0de0f554e4487b"}},"assets":{"bird_gray_16.png":"bird_gray_16-93f51980875017e26744056b62aaac22.png","missing_profile_image.png":"missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.png","rails.png":"rails-bc7d436ef8afbf0f88829742a43ba3a4.png","application.js":"application-47a9a60feaec5625a9c66b1c985a1179.js","application.css":"application-8ad8039145e9fbab6b0de0f554e4487b.css"}} \ No newline at end of file
diff --git a/public/assets/missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.png b/public/assets/missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.png
new file mode 100644
index 0000000..3d1e0f9
--- /dev/null
+++ b/public/assets/missing_profile_image-d5d708680693a18615dfb8f5b1a5a96c.png
Binary files differ