Merge branch 'master' of https://github.com/b3yond/ticketfrei into multi-deployment

This commit is contained in:
b3yond 2018-01-08 00:14:38 +01:00
commit 2b4d8650c9
6 changed files with 91 additions and 159 deletions

View file

@ -10,14 +10,14 @@ server = 'yourmastodoninstance' # Instance where you have your Mastodon account
[tapp] [tapp]
# You get those keys when you follow these steps: # You get those keys when you follow these steps:
# https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens # https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens
consumer_key = "OD0CLn6twBxHjN2DqMkKuSvli" consumer_key = "your_consumer_key"
consumer_secret = "XkvbViwjBWoWoJzIlseJLXmg2fqluq4HYqvwOwoSHGwxdTNi4l" consumer_secret = "your_consumer_secret"
[tuser] [tuser]
# You get those keys when you follow these steps: # You get those keys when you follow these steps:
# https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens # https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens
access_token_key = "876046057721008128-J35moxFXUvLb24MnaMVbVpqiEtxBlcc" access_token_key = "your_access_token_key"
access_token_secret = "I7PQZMHuJDS5WslgUhqEeZbEWGhwLhmOetvwFoTn8YDKW" access_token_secret = "your_acces_token_secret"
[mail] [mail]
# This is the mail the bot uses to send emails. # This is the mail the bot uses to send emails.

View file

@ -1,82 +0,0 @@
#!/usr/bin/env python3
import os
import datetime
import traceback
import sys
import sendmail
class Logger(object):
"""
builds log files, writes the log messages.
If a critical error occurs, handles the bugtracking and error
messages.
"""
def __init__(self, config):
"""
logs everything & sends bugtracking messages.
:param config: config file
"""
self.config = config
# initialize logging
if config["logging"]["logpath"]:
self.logpath = os.path.join(self.config["logging"]["logpath"], str(datetime.datetime.now()))
else:
self.logpath = os.path.join("logs", str(datetime.datetime.now()))
print("Path of logfile: " + self.logpath)
# intialize shutdown contact
try:
self.no_shutdown_contact = False
self.contact = self.config['mail']['contact']
except KeyError:
self.no_shutdown_contact = True
def log(self, message):
"""
Writing an error message & sometimes a traceback to a logfile in logs/
and prints it.
:param message: (string) Logger message to be displayed
"""
time = str(datetime.datetime.now())
line = "[" + time + "] " + message + "\n"
with open(self.logpath, 'a') as f:
try:
f.write(line)
except UnicodeEncodeError:
message = "Failed to save log message due to UTF-8 error. "
message = message + self.generate_tb(sys.exc_info())
self.log(message)
print(line, end="")
def generate_tb(self, exc):
tb = traceback.extract_tb(exc[2]) # returns StackSummary object
tb = "\n".join(tb.format()) # string of the actual traceback
message = ("Traceback (most recent call last):\n",
tb,
exc[0].__name__) # the type of the Exception
message = "".join(message) # concatenate to full traceback message
return message
def shutdown(self, tb):
""" If something breaks, it shuts down the bot and messages the owner.
:param tb: (string) traceback
"""
logmessage = "Shit went wrong, closing down.\n" + tb + "\n\n"
if self.no_shutdown_contact:
self.log(logmessage)
return
logmessage = logmessage + "Sending message to " + self.contact
self.log(logmessage)
try:
mailer = sendmail.Mailer(self.config)
mailer.send(tb, self.contact, "Ticketfrei Crash Report", attachment=self.logpath)
except:
self.log("Error while shutdown: " + self.generate_tb(sys.exc_info()))
print()

View file

@ -6,10 +6,11 @@ import time
import trigger import trigger
import datetime import datetime
import email import email
import logger import logging
import pytoml as toml import pytoml as toml
import imaplib import imaplib
import sys
logger = logging.getLogger(__name__)
class Mailbot(object): class Mailbot(object):
@ -18,7 +19,7 @@ class Mailbot(object):
other bots that it received mails. other bots that it received mails.
""" """
def __init__(self, config, trigger, logger, history_path="last_mail"): def __init__(self, config, trigger, history_path="last_mail"):
""" """
Creates a Bot who listens to mails and forwards them to other Creates a Bot who listens to mails and forwards them to other
bots. bots.
@ -27,7 +28,6 @@ class Mailbot(object):
""" """
self.config = config self.config = config
self.trigger = trigger self.trigger = trigger
self.logger = logger
self.history_path = history_path self.history_path = history_path
self.last_mail = self.get_history(self.history_path) self.last_mail = self.get_history(self.history_path)
@ -42,15 +42,18 @@ class Mailbot(object):
try: try:
self.mailbox.starttls(ssl_context=context) self.mailbox.starttls(ssl_context=context)
except: except:
logmsg = logger.generate_tb(sys.exc_info()) logger.error('StartTLS failed', exc_info=True)
logger.log(logmsg)
try: try:
self.mailbox.login(self.config["mail"]["user"], self.config["mail"]["passphrase"]) self.mailbox.login(self.config["mail"]["user"], self.config["mail"]["passphrase"])
except imaplib.IMAP4.error: except imaplib.IMAP4.error:
logmsg = "Login to mail server failed." logger.error("Login to mail server failed", exc_info=True)
logmsg = logmsg + logger.generate_tb(sys.exc_info()) try:
logger.log(logmsg) mailer = sendmail.Mailer(config)
logger.shutdown(logmsg) mailer.send('', config['mail']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
logger.error('Mail sending failed', exc_info=True)
def listen(self): def listen(self):
""" """
@ -67,8 +70,7 @@ class Mailbot(object):
for num in data[0].split(): for num in data[0].split():
rv, data = self.mailbox.fetch(num, '(RFC822)') rv, data = self.mailbox.fetch(num, '(RFC822)')
if rv != 'OK': if rv != 'OK':
logmsg = "Didn't receive mail. Error: " + rv + str(data) logger.error("Couldn't fetch mail %s %s" % (rv, str(data)))
self.logger.log(logmsg)
return msgs return msgs
msg = email.message_from_bytes(data[0][1]) msg = email.message_from_bytes(data[0][1])
@ -157,10 +159,12 @@ if __name__ == "__main__":
with open('config.toml') as configfile: with open('config.toml') as configfile:
config = toml.load(configfile) config = toml.load(configfile)
logger = logger.Logger(config) fh = logging.FileHandler(config['logging']['logpath'])
trigger = trigger.Trigger(config) fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
m = Mailbot(config, trigger, logger) trigger = trigger.Trigger(config)
m = Mailbot(config, trigger)
statuses = [] statuses = []
try: try:
while 1: while 1:
@ -169,8 +173,12 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
print("Good bye. Remember to restart the bot!") print("Good bye. Remember to restart the bot!")
except: except:
exc = sys.exc_info() # returns tuple [Exception type, Exception object, Traceback object] logger.error('Shutdown', exc_info=True)
message = logger.generate_tb(exc)
m.logger.log(message)
m.save_last_mail() m.save_last_mail()
m.logger.shutdown(message) try:
mailer = sendmail.Mailer(config)
mailer.send('', config['mail']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
logger.error('Mail sending failed', exc_info=True)

View file

@ -7,12 +7,14 @@ import pickle
import re import re
import time import time
import trigger import trigger
import logger import logging
import sys import sendmail
logger = logging.getLogger(__name__)
class RetootBot(object): class RetootBot(object):
def __init__(self, config, trigger, logger): def __init__(self, config, trigger):
self.config = config self.config = config
self.trigger = trigger self.trigger = trigger
self.client_id = self.register() self.client_id = self.register()
@ -25,8 +27,6 @@ class RetootBot(object):
except IOError: except IOError:
self.seen_toots = set() self.seen_toots = set()
self.logger = logger
def register(self): def register(self):
client_id = os.path.join( client_id = os.path.join(
'appkeys', 'appkeys',
@ -68,8 +68,7 @@ class RetootBot(object):
notification['status']['content']) notification['status']['content'])
if not self.trigger.is_ok(text_content): if not self.trigger.is_ok(text_content):
continue continue
self.logger.log('Boosting toot from %s: %s' % ( logger.info('Boosting toot from %s: %s' % (
# notification['status']['id'],
notification['status']['account']['acct'], notification['status']['account']['acct'],
notification['status']['content'])) notification['status']['content']))
self.m.status_reblog(notification['status']['id']) self.m.status_reblog(notification['status']['id'])
@ -92,10 +91,12 @@ if __name__ == '__main__':
with open('config.toml') as configfile: with open('config.toml') as configfile:
config = toml.load(configfile) config = toml.load(configfile)
trigger = trigger.Trigger(config) fh = logging.FileHandler(config['logging']['logpath'])
logger = logger.Logger(config) fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
bot = RetootBot(config, trigger, logger) trigger = trigger.Trigger(config)
bot = RetootBot(config, trigger)
try: try:
while True: while True:
@ -104,7 +105,11 @@ if __name__ == '__main__':
except KeyboardInterrupt: except KeyboardInterrupt:
print("Good bye. Remember to restart the bot!") print("Good bye. Remember to restart the bot!")
except: except:
exc = sys.exc_info() # returns tuple [Exception type, Exception object, Traceback object] logger.error('Shutdown', exc_info=True)
message = logger.generate_tb(exc) try:
bot.logger.log(message) mailer = sendmail.Mailer(config)
bot.logger.shutdown(message) mailer.send('', config['mail']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
logger.error('Mail sending failed', exc_info=True)

View file

@ -1,12 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import tweepy import tweepy
import sys
import requests import requests
import pytoml as toml import pytoml as toml
import trigger import trigger
from time import sleep from time import sleep
import logger import logging
import sendmail
logger = logging.getLogger(__name__)
class RetweetBot(object): class RetweetBot(object):
@ -22,7 +24,7 @@ class RetweetBot(object):
last_mention: the ID of the last tweet which mentioned you last_mention: the ID of the last tweet which mentioned you
""" """
def __init__(self, trigger, config, logger, history_path="last_mention"): def __init__(self, trigger, config, history_path="last_mention"):
""" """
Initializes the bot and loads all the necessary data. Initializes the bot and loads all the necessary data.
@ -47,8 +49,6 @@ class RetweetBot(object):
self.trigger = trigger self.trigger = trigger
self.waitcounter = 0 self.waitcounter = 0
self.logger = logger
def get_api_keys(self): def get_api_keys(self):
""" """
How to get these keys is described in doc/twitter_api.md How to get these keys is described in doc/twitter_api.md
@ -127,14 +127,10 @@ class RetweetBot(object):
mentions = self.api.mentions_timeline(since_id=self.last_mention) mentions = self.api.mentions_timeline(since_id=self.last_mention)
return mentions return mentions
except tweepy.RateLimitError: except tweepy.RateLimitError:
logmsg = "Twitter API Error: Rate Limit Exceeded." logger.error("Twitter API Error: Rate Limit Exceeded", exc_info=True)
logmsg = logmsg + self.logger.generate_tb(sys.exc_info())
self.logger.log(logmsg)
self.waitcounter += 60*15 + 1 self.waitcounter += 60*15 + 1
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logmsg = "Twitter API Error: Bad Connection." logger.error("Twitter API Error: Bad Connection", exc_info=True)
logmsg = logmsg + self.logger.generate_tb(sys.exc_info())
self.logger.log(logmsg)
self.waitcounter += 10 self.waitcounter += 10
return [] return []
@ -148,21 +144,16 @@ class RetweetBot(object):
while 1: while 1:
try: try:
self.api.retweet(status.id) self.api.retweet(status.id)
self.logger.log("Retweeted: " + self.format_mastodon(status)) logger.info("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)
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logmsg = "Twitter API Error: Bad Connection." logger.error("Twitter API Error: Bad Connection", exc_info=True)
logmsg = logmsg + self.logger.generate_tb(sys.exc_info())
self.logger.log(logmsg)
sleep(10) sleep(10)
# maybe one day we get rid of this error: # maybe one day we get rid of this error:
except tweepy.TweepError: except tweepy.TweepError:
logmsg = "Twitter Error." logger.error("Twitter Error", exc_info=True)
logmsg = logmsg + self.logger.generate_tb(sys.exc_info())
self.logger.log(logmsg)
# self.log.log("Twitter API Error: You probably already retweeted this tweet: " + status.text)
if status.id > self.last_mention: if status.id > self.last_mention:
self.last_mention = status.id self.last_mention = status.id
return None return None
@ -180,9 +171,7 @@ class RetweetBot(object):
self.api.update_status(status=post) self.api.update_status(status=post)
return return
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logmsg = "Twitter API Error: Bad Connection." logger.error("Twitter API Error: Bad Connection", exc_info=True)
logmsg = logmsg + self.logger.generate_tb(sys.exc_info())
self.logger.log(logmsg)
sleep(10) sleep(10)
def flow(self, to_tweet=()): def flow(self, to_tweet=()):
@ -221,10 +210,12 @@ if __name__ == "__main__":
with open('config.toml') as configfile: with open('config.toml') as configfile:
config = toml.load(configfile) config = toml.load(configfile)
trigger = trigger.Trigger(config) fh = logging.FileHandler(config['logging']['logpath'])
logger = logger.Logger(config) fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
bot = RetweetBot(trigger, config, logger) trigger = trigger.Trigger(config)
bot = RetweetBot(trigger, config)
try: try:
while True: while True:
bot.flow() bot.flow()
@ -232,8 +223,12 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
print("Good bye. Remember to restart the bot!") print("Good bye. Remember to restart the bot!")
except: except:
exc = sys.exc_info() # returns tuple [Exception type, Exception object, Traceback object] logger.error('Shutdown', exc_info=True)
message = logger.generate_tb(exc)
bot.logger.log(message)
bot.save_last_mention() bot.save_last_mention()
bot.logger.shutdown(message) try:
mailer = sendmail.Mailer(config)
mailer.send('', config['mail']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
logger.error('Mail sending failed', exc_info=True)

View file

@ -1,9 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging
import pytoml as toml import pytoml as toml
import logger
import time import time
import sys import sendmail
from retootbot import RetootBot from retootbot import RetootBot
from retweetbot import RetweetBot from retweetbot import RetweetBot
@ -15,12 +15,14 @@ if __name__ == '__main__':
with open('config.toml') as configfile: with open('config.toml') as configfile:
config = toml.load(configfile) config = toml.load(configfile)
logger = logging.getLogger()
fh = logging.FileHandler(config['logging']['logpath'])
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
trigger = Trigger(config) trigger = Trigger(config)
mbot = RetootBot(config, trigger)
logger = logger.Logger(config) tbot = RetweetBot(trigger, config)
mbot = RetootBot(config, trigger, logger)
tbot = RetweetBot(trigger, config, logger)
try: try:
statuses = [] statuses = []
@ -31,8 +33,12 @@ if __name__ == '__main__':
except KeyboardInterrupt: except KeyboardInterrupt:
print("Good bye. Remember to restart the bot!") print("Good bye. Remember to restart the bot!")
except: except:
exc = sys.exc_info() # returns tuple [Exception type, Exception object, Traceback object] logger.error('Shutdown', exc_info=True)
message = logger.generate_tb(exc)
tbot.logger.log(message)
tbot.save_last_mention() tbot.save_last_mention()
tbot.logger.shutdown(message) try:
mailer = sendmail.Mailer(config)
mailer.send('', config['mail']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
logger.error('Mail sending failed', exc_info=True)