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