forked from ticketfrei/ticketfrei
changed twitterbot to python3 + tweepy #7
This commit is contained in:
commit
fb24c758a8
|
@ -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
|
12
retootbot.py
12
retootbot.py
|
@ -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(
|
||||||
|
|
|
@ -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()
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue