changed twitterbot to python3 + tweepy #7

This commit is contained in:
b3yond 2017-12-30 01:11:28 +01:00
commit fb24c758a8
4 changed files with 62 additions and 53 deletions

View file

@ -11,7 +11,7 @@ To this date, we have never heard of this happening though.
Website: https://wiki.links-it.de/IT/Ticketfrei Website: https://wiki.links-it.de/IT/Ticketfrei
# Install ## Install
Setting up a ticketfrei bot for your city is quite easy. Here are the few steps: Setting up a ticketfrei bot for your city is quite easy. Here are the few steps:
@ -81,4 +81,4 @@ Desktop/pycharm-community-2017.1.4/bin/pycharm.sh
- [x] put shutdown contact in ticketfrei.cfg - [x] put shutdown contact in ticketfrei.cfg
- [x] document what you have to configure if you setup the bot in another city - [x] document what you have to configure if you setup the bot in another city
- [ ] write a script to setup the bot easily. ask the admin for the necessary information - [ ] write a script to setup the bot easily. ask the admin for the necessary information
- [ ] write a web interface, so we can host the bot for other cities - ppl don't have to know the command line or own a server - [ ] ongoing: solve issues

View file

@ -34,22 +34,22 @@ class RetootBot(object):
""" """
Writing an error message to a logfile in logs/ and prints it. Writing an error message to a logfile in logs/ and prints it.
:param message(string): Log message to be displayed :param message: (string) Log message to be displayed
:param tb: String of the Traceback :param tb: String of the Traceback
""" """
time = str(datetime.datetime.now()) timenow = str(datetime.datetime.now())
if tb: if tb:
message = message + " The traceback is located at " + os.path.join("logs" + time) message = message + " The traceback is located at " + os.path.join("logs" + timenow)
with open(os.path.join("logs", time), 'w+') as f: with open(os.path.join("logs", timenow), 'w+') as f:
f.write(tb) f.write(tb)
line = "[" + time + "] "+ message + "\n" line = "[" + timenow + "] " + message + "\n"
with open(self.logpath, 'a') as f: with open(self.logpath, 'a') as f:
try: try:
f.write(line) f.write(line)
except UnicodeEncodeError: except UnicodeEncodeError:
self.log("Failed to save log message due to UTF-8 error. ") self.log("Failed to save log message due to UTF-8 error. ")
traceback.print_exc() traceback.print_exc()
print line, print(line, end="")
def register(self): def register(self):
self.client_id = os.path.join( self.client_id = os.path.join(

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python3
import twitter import tweepy
import os import os
import sys
import datetime import datetime
import requests import requests
import pytoml as toml import pytoml as toml
@ -32,27 +33,34 @@ class RetweetBot(object):
:param logpath: Path to the file where the log is stored :param logpath: Path to the file where the log is stored
""" """
self.config = config self.config = config
# initialize API access
keys = self.get_api_keys() keys = self.get_api_keys()
self.api = twitter.Api(consumer_key=keys[0], auth = tweepy.OAuthHandler(consumer_key=keys[0],
consumer_secret=keys[1], consumer_secret=keys[1])
access_token_key=keys[2], auth.set_access_token(keys[2], # access_token_key
access_token_secret=keys[3]) keys[3]) # access_token_secret
self.historypath = historypath self.api = tweepy.API(auth)
# intialize shutdown contact
try: try:
self.no_shutdown_contact = False self.no_shutdown_contact = False
self.user_id = self.config['tapp']['shutdown_contact_userid']
self.screen_name = \ self.screen_name = \
self.config['tapp']['shutdown_contact_screen_name'] self.config['tapp']['shutdown_contact_screen_name']
except KeyError: except KeyError:
self.no_shutdown_contact = True self.no_shutdown_contact = True
self.historypath = historypath
self.last_mention = self.get_history(self.historypath) self.last_mention = self.get_history(self.historypath)
self.trigger = trigger self.trigger = trigger
self.waitcounter = 0 self.waitcounter = 0
# initialize logging
if logpath: if logpath:
self.logpath = logpath self.logpath = logpath
else: else:
self.logpath = os.path.join("logs", str(datetime.datetime.now())) self.logpath = os.path.join("logs", str(datetime.datetime.now()))
print "Path of logfile: " + self.logpath print("Path of logfile: " + self.logpath)
def get_api_keys(self): def get_api_keys(self):
""" """
@ -69,18 +77,15 @@ class RetweetBot(object):
:return: keys: list of these 4 strings. :return: keys: list of these 4 strings.
""" """
keys = [] keys = [self.config['tapp']['consumer_key'], self.config['tapp']['consumer_secret'],
keys.append(self.config['tapp']['consumer_key']) self.config['tuser']['access_token_key'], self.config['tuser']['access_token_secret']]
keys.append(self.config['tapp']['consumer_secret'])
keys.append(self.config['tuser']['access_token_key'])
keys.append(self.config['tuser']['access_token_secret'])
return keys return keys
def log(self, message, tb=False): def log(self, message, tb=False):
""" """
Writing an error message to a logfile in logs/ and prints it. Writing an error message to a logfile in logs/ and prints it.
:param message(string): Log message to be displayed :param message: (string) Log message to be displayed
:param tb: String of the Traceback :param tb: String of the Traceback
""" """
time = str(datetime.datetime.now()) time = str(datetime.datetime.now())
@ -88,14 +93,14 @@ class RetweetBot(object):
message = message + " The traceback is located at " + os.path.join("logs" + time) message = message + " The traceback is located at " + os.path.join("logs" + time)
with open(os.path.join("logs", time), 'w+') as f: with open(os.path.join("logs", time), 'w+') as f:
f.write(tb) f.write(tb)
line = "[" + time + "] "+ message + "\n" line = "[" + time + "] " + message + "\n"
with open(self.logpath, 'a') as f: with open(self.logpath, 'a') as f:
try: try:
f.write(line) f.write(line)
except UnicodeEncodeError: except UnicodeEncodeError:
self.log("Failed to save log message due to UTF-8 error. ") self.log("Failed to save log message due to UTF-8 error. ")
traceback.print_exc() traceback.print_exc()
print line, print(line, end="")
def get_history(self, path): def get_history(self, path):
""" This counter is needed to keep track of your mentions, so you """ This counter is needed to keep track of your mentions, so you
@ -133,8 +138,8 @@ class RetweetBot(object):
def format_mastodon(self, status): def format_mastodon(self, status):
""" """
Bridge your Retweets to mastodon. Bridge your Retweets to mastodon.
:todo vmann: add all the mastodon API magic.
:rtype: string
:param status: Object of a tweet. :param status: Object of a tweet.
:return: toot: text tooted on mastodon, e.g. "_b3yond: There are :return: toot: text tooted on mastodon, e.g. "_b3yond: There are
uniformed controllers in the U2 at Opernhaus." uniformed controllers in the U2 at Opernhaus."
@ -150,9 +155,12 @@ class RetweetBot(object):
""" """
try: try:
if not self.waiting(): if not self.waiting():
mentions = self.api.GetMentions(since_id=self.last_mention) if self.last_mention == 0:
mentions = self.api.mentions_timeline()
else:
mentions = self.api.mentions_timeline(since_id=self.last_mention)
return mentions return mentions
except twitter.TwitterError: except tweepy.RateLimitError:
self.log("Twitter API Error: Rate Limit Exceeded.") self.log("Twitter API Error: Rate Limit Exceeded.")
self.waitcounter += 60*15 + 1 self.waitcounter += 60*15 + 1
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
@ -169,21 +177,22 @@ class RetweetBot(object):
""" """
while 1: while 1:
try: try:
self.api.PostRetweet(status.id) self.api.retweet(status.id)
self.log("Retweeted: " + self.format_mastodon(status)) self.log("Retweeted: " + self.format_mastodon(status))
if status.id > self.last_mention: if status.id > self.last_mention:
self.last_mention = status.id self.last_mention = status.id
return self.format_mastodon(status) return self.format_mastodon(status)
# maybe one day we get rid of this error. If not, try to uncomment # maybe one day we get rid of this error. If not, try to uncomment
# these lines. # these lines.
except twitter.error.TwitterError:
self.log("Twitter API Error: You probably already retweeted this tweet: " + status.text)
if status.id > self.last_mention:
self.last_mention = status.id
return None
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
self.log("Twitter API Error: Bad Connection.") self.log("Twitter API Error: Bad Connection.")
sleep(10) sleep(10)
except tweepy.TweepError as error:
self.log("Twitter Error " + error.api_code + ": " + error.reason + error.response)
# self.log("Twitter API Error: You probably already retweeted this tweet: " + status.text)
if status.id > self.last_mention:
self.last_mention = status.id
return None
def tweet(self, post): def tweet(self, post):
""" """
@ -195,7 +204,7 @@ class RetweetBot(object):
post = post[:280 - 4] + u' ...' post = post[:280 - 4] + u' ...'
while 1: while 1:
try: try:
self.api.PostUpdate(status=post) self.api.update_status(status=post)
return return
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
self.log("Twitter API Error: Bad Connection.") self.log("Twitter API Error: Bad Connection.")
@ -243,11 +252,11 @@ class RetweetBot(object):
return return
self.save_last_mention() self.save_last_mention()
try: try:
self.api.PostDirectMessage("Help! I broke down. restart me pls :$", self.api.send_direct_message(self.screen_name, "Help! I broke down. restart me pls :$")
self.user_id, self.screen_name)
except: except:
traceback.print_exc() # traceback.print_exc()
print bot.log(traceback.extract_tb(sys.exc_info()[2]))
print()
if __name__ == "__main__": if __name__ == "__main__":
@ -263,8 +272,8 @@ if __name__ == "__main__":
bot.flow() bot.flow()
sleep(60) sleep(60)
except KeyboardInterrupt: except KeyboardInterrupt:
print "Good bye! Remember to restart the bot." print("Good bye! Remember to restart the bot.")
except: except:
traceback.print_exc() bot.log(traceback.extract_tb(sys.exc_info()[2]))
print print()
bot.shutdown() bot.shutdown()

View file

@ -7,15 +7,15 @@ password = 'yourpassword' # Password of your Mastodon account
server = 'yourmastodoninstance' # Instance where you have your Mastodon account server = 'yourmastodoninstance' # Instance where you have your Mastodon account
[tapp] [tapp]
consumer_key = "yourconsumerkey" # consumer key for the twitter API consumer_key = "OD0CLn6twBxHjN2DqMkKuSvli"
consumer_secret = "yourconsumersecret" # consumer secret for the twitter API consumer_secret = "XkvbViwjBWoWoJzIlseJLXmg2fqluq4HYqvwOwoSHGwxdTNi4l"
# shutdown_contact_userid = 012345 # twitter id of your shutdown contact shutdown_contact_userid = 801098086005243904
# shutdown_contact_screen_name = 'yourscreenname' # twitter name of your shutdown contact shutdown_contact_screen_name = 'links_tech'
[tuser] [tuser]
access_token_key = "youraccesstokenkey" # access token key for the twitter API access_token_key = "876046057721008128-J35moxFXUvLb24MnaMVbVpqiEtxBlcc"
access_token_secret = "youraccesstokensecret" # access token secret for the twitter API access_token_secret = "I7PQZMHuJDS5WslgUhqEeZbEWGhwLhmOetvwFoTn8YDKW"
# [trigger] # [trigger]
# goodlists are one regex per line. # goodlists are one regex per line.