public
Description: no really, i need to know
Homepage: http://islostonyet.com
Clone URL: git://github.com/technoweenie/islostonyet.com.git
seaofclouds (author)
Sat Jan 17 01:10:50 -0800 2009
commit  5b937afcdbb7f3e31f243cf6416c6d834b8c1e66
tree    3a913724f91b0c11892878e815bdd317d7d8236b
parent  6028fc412b52c8583c96846a052e36762552c6a6
100644 155 lines (134 sloc) 4.425 kb
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module IsLOSTOnYet
  class Post < Sequel.Model(:posts)
    many_to_one :user, :class => "IsLOSTOnYet::User"
 
    def self.find_updates(page = 1)
      filtered_for_updates.where(:visible => true).paginate(page, 30).to_a
    end
 
    def self.find_replies(page = 1)
      filtered_for_replies.where(:visible => true).paginate(page, 30).to_a
    end
 
    def self.find_by_tags(tags, page = 1)
      return [] if tags.empty?
      filtered_for_replies.
        where([Array.new(tags.size, "tag LIKE ?") * " AND ", *tags.map { |t| "%[#{t}]%" }]).
        where(:visible => true).paginate(page, 30).to_a
    end
 
    def self.process_updates
      args = [:user]
      if post = latest_update
        args << {:since_id => post.external_id}
      end
      process_tweets(IsLOSTOnYet.twitter.timeline(*args)) { |user, post| !post.reply? }
      IsLOSTOnYet.twitter_user.reload
    end
 
    def self.process_replies
      now = Time.now.utc
      args = []
      answer = IsLOSTOnYet.answer(now)
      if post = latest_reply
        args << {:since_id => post.external_id}
      end
      process_tweets(IsLOSTOnYet.twitter.replies(*args)) do |user, post|
        if post.inquiry?
          IsLOSTOnYet.twitter.update("@#{user.login} #{answer.reason}")
          false
        else
          post
        end
      end
    end
 
    def self.latest_update
      filtered_for_updates.select(:external_id).first
    end
 
    def self.latest_reply
      filtered_for_replies.select(:external_id).first
    end
 
    # a @reply tweet
    def reply?
      body.strip =~ /^@/
    end
 
    # A tweet from a user asking the twitter bot if the show is on
    def inquiry?
      body.strip =~ /^@#{IsLOSTOnYet.twitter_login}\s*\?$/i
    end
 
    def visible?
      visible == true || visible == 1
    end
 
    def hash_tags
      @hash_tags ||= begin
        tags = body.scan(/(^|[^&])#([\w\d]+)/i).map { |s| s.last }
        tags.flatten!
        tags.each { |tag| tag.downcase! }
      end
    end
 
    def save_hash_tags
      existing = Tag.where(:name => hash_tags).to_a
      creating = hash_tags - existing.map { |t| t.name }
      creating.each do |name|
        existing << Tag.create(:name => name)
      end
      existing.each do |tag|
        Tagging << {:tag_id => tag.id, :post_id => id}
      end
      self.tag = existing.map { |tag| "[#{tag.name}]" }.sort! * " "
      save
    end
 
  protected
    def self.filtered_for_updates
      user_id = IsLOSTOnYet.twitter_user ? IsLOSTOnYet.twitter_user.id : 0
      filter_and_order(:user_id => user_id)
    end
 
    def self.filtered_for_replies
      user_id = IsLOSTOnYet.twitter_user ? IsLOSTOnYet.twitter_user.id : 0
      filter_and_order(['user_id != ?', user_id])
    end
 
    def self.filter_and_order(*args)
      where(*args).order(:created_at.desc)
    end
 
    def self.process_tweets(tweets, &block)
      return nil if tweets.empty?
      users = {}
      posts = []
      tweets.reverse!
      tweets.each do |s|
        users[s.user.id.to_i] = {:login => s.user.screen_name, :avatar_url => s.user.profile_image_url}
        posts << {:body => s.text, :user_id => s.user.id, :created_at => Time.parse(s.created_at).utc, :external_id => s.id}
      end
 
      existing_users = User.where(:external_id => users.keys).to_a
      Sequel::Model.db.transaction do
        process_users(users, existing_users)
        process_posts(posts, users, &block)
      end
    end
 
    # replace user hash values with saved user records
    def self.process_users(users, existing_users)
      user_ids = users.keys
      existing_users.each do |existing|
        user_ids.delete existing.external_id
        process_user users, existing
      end
 
      user_ids.each do |external_id|
        process_user users, User.new(:external_id => external_id)
      end
    end
 
    def self.process_user(users, user)
      users[user.external_id].each do |key, value|
        user.send("#{key}=", value)
      end
      user.save!
      users[user.external_id] = user
    end
 
    def self.process_posts(posts, users, &block)
      posts.each do |attributes|
        user = users[attributes.delete(:user_id).to_i]
        post = Post.new(:user_id => user.id)
        attributes.each do |key, value|
          post.send("#{key}=", value)
        end
        post.visible = !! (!block || block.call(user, post))
        post.save
        post.save_hash_tags
      end
    end
  end
end