-
Notifications
You must be signed in to change notification settings - Fork 8
/
tweet_updates.py
113 lines (92 loc) · 4.03 KB
/
tweet_updates.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
from time import sleep
from datetime import datetime, timedelta
from requests.exceptions import ConnectionError
from polybot import Bot
import tempfile
from geonames import GeoNamesGeocoder
from epic import EPIC
from processing import process_image
def suffix(d):
return 'th' if 11 <= d <= 13 else {1: 'st', 2: 'nd', 3: 'rd'}.get(d % 10, 'th')
class TweetEPIC(Bot):
def __init__(self):
super().__init__('tweet_epic')
self.parser.add_argument('--now', action='store_true',
help="Tweet the next image now")
self.epic = EPIC()
self.geocoder = GeoNamesGeocoder()
self.state = {'image_queue': {},
'last_posted_image': datetime(2015, 9, 1),
'last_post_time': datetime(2015, 9, 1)}
self.post_interval = timedelta(minutes=60)
self.post_interval_fast = timedelta(minutes=45)
def poll(self):
try:
most_recent = sorted(self.state['image_queue'].keys())[-1]
except IndexError:
most_recent = self.state['last_posted_image']
try:
images = self.epic.get_recent_images(most_recent, 20)
except (ConnectionError, ValueError):
self.log.exception("Unable to fetch images")
images = []
added = 0
for image in images:
if (image['date'] not in self.state['image_queue'] and
image['date'] > self.state['last_posted_image']):
self.state['image_queue'][image['date']] = image
added += 1
if added > 0:
self.log.info("Added %s images to queue", added)
if len(self.state['image_queue']) > 20:
to_drop = len(self.state['image_queue']) - 20
self.log.info("Dropping %s images from queue", to_drop)
for key in sorted(self.state['image_queue'])[0:to_drop]:
del self.state['image_queue'][key]
if len(self.state['image_queue']) > 12:
interval = self.post_interval_fast
else:
interval = self.post_interval
if self.state['last_post_time'] < (datetime.now() - interval) \
and len(self.state['image_queue']) > 0:
try:
self.do_tweet()
except ConnectionError:
self.log.exception("Unable to fetch image file")
self.save_state()
def do_tweet(self):
image_date = sorted(self.state['image_queue'].keys())[0]
image = self.state['image_queue'][image_date]
self.log.info("Tweeting an image")
with tempfile.NamedTemporaryFile(suffix='.png') as imagefile:
self.fetch_image(image, imagefile)
self.post_tweet(image, imagefile)
del self.state['image_queue'][image_date]
self.state['last_posted_image'] = image_date
self.state['last_post_time'] = datetime.now()
self.log.info("One image tweeted, %s left in queue", len(self.state['image_queue']))
def post_tweet(self, image, imagefile):
lat = image['centroid_coordinates']['lat']
lon = image['centroid_coordinates']['lon']
self.log.info("Geocoding %s, %s", lat, lon)
geocoded = self.geocoder.geocode(lat, lon)
if geocoded[0] is not None:
place = " ".join(geocoded)
datestring = "%s %s%s" % (image['date'].strftime("%H:%M on %A %B"),
image['date'].day, suffix(image['date'].day))
if geocoded[0] is not None:
text = "%s, %s" % (datestring, place)
else:
text = datestring
self.post(text, imagefile=imagefile, lat=lat, lon=lon)
def fetch_image(self, image, destfile):
with tempfile.NamedTemporaryFile(suffix='.png') as downloadfile:
self.epic.download_image(image, downloadfile)
process_image(downloadfile.name, destfile.name)
def main(self):
if self.args.now:
self.state['last_post_time'] = datetime(2015, 9, 1)
while True:
self.poll()
sleep(120)
TweetEPIC().run()