f84fea6d6bd0bf8e2d738e5e09242c50276a48f4
[kiosk.git] / twitter_renderer.py
1 #!/usr/bin/env python3
2
3 import random
4 import re
5 import tweepy  # type: ignore
6 from typing import Dict, List
7
8 import file_writer
9 import renderer
10 import profanity_filter
11 import kiosk_secrets as secrets
12
13
14 class twitter_renderer(renderer.debuggable_abstaining_renderer):
15     def __init__(self, name_to_timeout_dict: Dict[str, int]) -> None:
16         super(twitter_renderer, self).__init__(name_to_timeout_dict, False)
17         self.debug = True
18         self.tweets_by_author: Dict[str, List[tweepy.models.Status]] = {}
19         self.handles_by_author: Dict[str, str] = {}
20         self.filter = profanity_filter.ProfanityFilter()
21         self.urlfinder = re.compile(
22             "((http|https)://[\-A-Za-z0-9\\.]+/[\?\&\-A-Za-z0-9_\\.]+)"
23         )
24
25         # == OAuth Authentication ==
26         #
27         # This mode of authentication is the new preferred way
28         # of authenticating with Twitter.
29
30         # The consumer keys can be found on your application's Details
31         # page located at https://dev.twitter.com/apps (under "OAuth settings")
32         consumer_key = secrets.twitter_consumer_key
33         consumer_secret = secrets.twitter_consumer_secret
34
35         # The access tokens can be found on your applications's Details
36         # page located at https://dev.twitter.com/apps (located
37         # under "Your access token")
38         access_token = secrets.twitter_access_token
39         access_token_secret = secrets.twitter_access_token_secret
40
41         auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
42         auth.set_access_token(access_token, access_token_secret)
43         self.api = tweepy.API(auth)
44
45     def debug_prefix(self) -> str:
46         return "twitter"
47
48     def linkify(self, value: str) -> str:
49         return self.urlfinder.sub(r'<a href="\1">\1</a>', value)
50
51     def periodic_render(self, key: str) -> bool:
52         if key == "Fetch Tweets":
53             return self.fetch_tweets()
54         elif key == "Shuffle Tweets":
55             return self.shuffle_tweets()
56         else:
57             raise Exception("Unexpected operation")
58
59     def fetch_tweets(self) -> bool:
60         try:
61             tweets = self.api.home_timeline(tweet_mode="extended", count=200)
62         except:
63             print("Exception while fetching tweets!")
64             return False
65         for tweet in tweets:
66             author = tweet.author.name
67             author_handle = tweet.author.screen_name
68             self.handles_by_author[author] = author_handle
69             if author not in self.tweets_by_author:
70                 self.tweets_by_author[author] = []
71             l = self.tweets_by_author[author]
72             l.append(tweet)
73         return True
74
75     def shuffle_tweets(self) -> bool:
76         authors = list(self.tweets_by_author.keys())
77         author = random.choice(authors)
78         handle = self.handles_by_author[author]
79         tweets = self.tweets_by_author[author]
80         already_seen = set()
81         with file_writer.file_writer("twitter_10_3600.html") as f:
82             f.write("<TABLE WIDTH=96%><TR><TD WIDTH=86%>")
83             f.write("<H2>%s (@%s)</H2></TD>\n" % (author, handle))
84             f.write('<TD ALIGN="right" VALIGN="top">')
85             f.write('<IMG SRC="twitter.png" WIDTH=42></TD></TR></TABLE>\n')
86             f.write("<HR>\n<UL>\n")
87             count = 0
88             length = 0
89             for tweet in tweets:
90                 text = tweet.full_text
91                 if (text not in already_seen) and (
92                     not self.filter.contains_bad_word(text)
93                 ):
94                     already_seen.add(text)
95                     text = self.linkify(text)
96                     f.write("<LI><B>%s</B>\n" % text)
97                     count += 1
98                     length += len(text)
99                     if count > 3 or length > 270:
100                         break
101             f.write("</UL>\n")
102         return True
103
104
105 # Test
106 # t = twitter_renderer(
107 #     {"Fetch Tweets" : 1,
108 #      "Shuffle Tweets" : 1})
109 # x = "bla bla bla https://t.co/EjWnT3UA9U bla bla"
110 # x = t.linkify(x)
111 # print(x)
112 # if t.fetch_tweets() == 0:
113 #     print("Error fetching tweets, none fetched.")
114 # else:
115 #     t.shuffle_tweets()