forked from ketralnis/redditron
-
Notifications
You must be signed in to change notification settings - Fork 1
/
twittertron.py
executable file
·142 lines (112 loc) · 4.52 KB
/
twittertron.py
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
#!/usr/bin/env python
import re
import sys
import time
import twitter
import urllib2 # python-twitter throws exceptions from here
from markov import save_chains, create_sentences, limit
from backends import Cassandra as Cache
MAX_LENGTH = 140
def main(memc, op, username = '', password = '', newfriendname = ''):
cache = Cache(memc)
if username and password:
api = twitter.Api(username=username,
password=password)
else:
api = twitter.Api()
if op == 'save':
status = get_twitter_status(cache, api)
save_chains(cache, status)
elif op == 'load_user':
status = load_user(cache, api, newfriendname)
save_chains(cache, status)
elif op == 'commands':
process_commands(cache, api)
elif op == 'tweet':
while True:
x = make_tweet(cache)
if x:
print 'tweeting: %r' % x
try:
api.PostUpdate(x)
time.sleep(60*60) # post one per hour
except urllib2.HTTPError, e:
print "Couldn't tweet, will retry", e
time.sleep(120) # try again in a couple of minutes
else:
raise ValueError('unkown op %r?' % op)
def make_tweet(cache):
for x in create_sentences(cache, 100):
x = x.encode('utf-8')[:MAX_LENGTH].strip()
return x
follow_cmd_re = re.compile('^follow @?([A-Za-z0-9_]+)$')
tweetme_cmd_re = re.compile('^tweetme$')
def process_commands(cache, api):
while True:
try:
dms = api.GetDirectMessages()
except urllib2.HTTPError, e:
print "Couldn't get direct messages, will retry", e
time.sleep(120)
continue
for dm in cache.seen_iterator(dms, _seen_key):
follow_cmd_match = follow_cmd_re.match(dm.text.lower())
tweetme_cmd_match = not follow_cmd_match and tweetme_cmd_re.match(dm.text.lower())
if follow_cmd_match:
# one of our friends has given us the command to
# follow someone else
newfriendname = follow_cmd_match.group(1)
try:
print '%r has instructed me to follow %r' % (dm.sender_screen_name,
newfriendname)
api.CreateFriendship(newfriendname)
except (ValueError, twitter.TwitterError, urllib2.HTTPError), e:
print "couldn't follow %r" % (newfriendname,)
else:
status = load_user(cache, api, newfriendname)
save_chains(cache, status)
elif tweetme_cmd_match:
# someone wants us to send them a one-time tweet
tweet = make_tweet(cache)
if tweet:
print 'Tweeting to %r: %r' % (dm.sender_screen_name, tweet)
try:
api.PostDirectMessage(dm.sender_screen_name, tweet)
except (ValueError, twitter.TwitterError, urllib2.HTTPError), e:
print "couldn't tweetme to %r (%r)" % (dm.sender_screen_name, tweet)
else:
print 'Unrecognised message from %r: %r' % (dm.sender_screen_name, dm.text)
time.sleep(60)
def get_twitter_status(cache, api):
last = None
while True:
# the plural of status is status
try:
status = api.GetFriendsTimeline(since_id = last, count=200)
except urllib2.HTTPError, e:
print "Couldn't get timeline, will retry", e
time.sleep(120)
continue
status = cache.seen_iterator(status, _seen_key)
s = None
for s in status:
if s.user.screen_name.lower() != api._username.lower():
text = s.text.encode('utf8')
print 'Learning from %s: %r' % (s.user.screen_name, text)
yield text
if s is not None:
last = s.id
# 35 looks to be optimal for preventing rate-limiting
# http://apiwiki.twitter.com/Rate-limiting
time.sleep(35)
def load_user(cache, api, newfriendname):
status = api.GetUserTimeline(newfriendname, count=200)
status = cache.seen_iterator(status, _seen_key)
for s in status:
text = s.text.encode('utf-8')
print 'Learning from %s: %r' % (newfriendname, text)
yield s.text.encode('utf-8')
def _seen_key(i):
return str('seen_%s' % i.id)
if __name__=='__main__':
main(*sys.argv[1:])