From 12901b406b4893d21e9d79f73c27584ebef86b00 Mon Sep 17 00:00:00 2001 From: m33m33 <m33@tok715.net> Date: Mon, 17 Aug 2020 14:51:12 +0200 Subject: [PATCH] Added token authentication method --- tootbot.py | 138 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 56 deletions(-) diff --git a/tootbot.py b/tootbot.py index c41db23..15513ce 100755 --- a/tootbot.py +++ b/tootbot.py @@ -4,53 +4,80 @@ import re import sqlite3 from datetime import datetime, timedelta from time import sleep - import feedparser from mastodon import Mastodon import requests +# Program configuration +auth_file = "tootbot.auth" +auth_session = auth_file+'.session' +mastodon_api = None + # Set to 1 to get some messages, 0 for error messages only debug=1 # Posting delay (s), wait between mastodon posts, reduces the "burst" effect on timoeline, and instance workload if you hit rate limiters posting_delay=1 -# URL substrings dediated to source image hosting +# URL substrings dedicated to source image hosting twitter_pics_hosting="https://pbs.twitimg.com/" nitter_pics_hosting="https://nitter.net/pic/" # Program logic below this line -if len(sys.argv) < 8: - print("Usage: python3 tootbot.py twitter_account mastodon_login mastodon_passwd mastodon_instance max_days footer_tags delay mastodon_account_email") # noqa +if len(sys.argv) < 4: + print("Usage: python3 tootbot.py [full path to config file] twitter_feed_or_twitter_account max_days footer_tags delay") # noqa sys.exit(1) +auth_file = sys.argv[1] +auth_session = auth_file+'.secret' +source = sys.argv[2] +days = int(sys.argv[3]) +tags = sys.argv[4] +delay = int(sys.argv[5]) + +# Returns the parameter from the specified file +def get_config(parameter, file_path): + # Check if secrets file exists + if not os.path.isfile(file_path): + print("ERROR: Config file (%s) not found"%file_path) + sys.exit(0) + + # Find parameter in file + with open( file_path ) as f: + for line in f: + if line.startswith( parameter ): + return line.replace(parameter + ":", "").strip() + + # Cannot find parameter, exit + print(file_path + " Missing parameter %s "%parameter) + sys.exit(0) +# end get_config() + +# Look for credentials in the coniguration file +auth_type = get_config("auth_type",auth_file) +if "token" in auth_type: + # We are using an application token (developer options in the mastodon account, new app...) + app_client_id = get_config("app_client_id",auth_file) + app_client_secret = get_config("app_client_secret",auth_file) + app_access_token = get_config("app_access_token",auth_file) +else: + if "email" in auth_type: + # We are using theuser account credential + mastodon_email_account = get_config("mastodon_email_account",auth_file) + mastodon_email_password = get_config("mastodon_email_password",auth_file) + else: + print("ERROR: Check the configuration file, no authentication method found") + sys.exit(1) + +instance = get_config("instance",auth_file) +mastodon_account = get_config("mastodon_account",auth_file)+'@'+instance + # sqlite db to store processed tweets (and corresponding toots ids) -sql = sqlite3.connect('tootbot.db') +sql = sqlite3.connect(os.path.dirname(auth_file) + '/tootbot' + mastodon_account + '.db') db = sql.cursor() db.execute('''CREATE TABLE IF NOT EXISTS tweets (tweet text, toot text, twitter text, mastodon text, instance text)''') -if len(sys.argv) > 4: - instance = sys.argv[4] - -if len(sys.argv) > 5: - days = int(sys.argv[5]) - -if len(sys.argv) > 6: - tags = sys.argv[6] - -if len(sys.argv) > 7: - delay = int(sys.argv[7]) - -if len(sys.argv) > 8: - mastodon_account_email = sys.argv[8] - -source = sys.argv[1] -mastodon = sys.argv[2] -passwd = sys.argv[3] - -mastodon_api = None - if source[:4] == 'http': if debug: print("Parsing source ",source," ...", end='') d = feedparser.parse(source) @@ -67,43 +94,41 @@ source=source.split("/search/")[0] for tweet in reversed(d.entries): # check if this tweet has been processed - db.execute('SELECT * FROM tweets WHERE tweet = ? AND twitter = ? and mastodon = ? and instance = ?', (tweet.id, source, mastodon, instance)) # noqa + db.execute('SELECT * FROM tweets WHERE tweet = ? AND twitter = ? and mastodon = ? and instance = ?', (tweet.id, source, mastodon_account, instance)) # noqa last = db.fetchone() dt = tweet.published_parsed - age = datetime.now()-datetime(dt.tm_year, dt.tm_mon, dt.tm_mday, - dt.tm_hour, dt.tm_min, dt.tm_sec) + age = datetime.now()-datetime(dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec) # process only unprocessed tweets less than 1 day old, after delay if last is None and age < timedelta(days=days) and age > timedelta(days=delay): - if mastodon_api is None: - # Create application if it does not exist + if "token" in auth_type and mastodon_api is None: try: - Mastodon.create_app('tootbot', api_base_url='https://'+instance, to_file='/var/run/lock/'+instance+'.secret') + mastodon_api = Mastodon(client_id=app_client_id, client_secret=app_client_secret, access_token=app_access_token, api_base_url='https://'+instance) except: - print('FATAL ERROR: Failed to create app on instance '+instance) - sys.exit(1) - - try: - if debug: print("Trying to connect with ",instance+'.secret'," to ",'https://'+instance," ...", end='') - mastodon_api = Mastodon( - client_id='/var/run/lock/'+instance+'.secret', - api_base_url='https://'+instance - ) - if debug: print(" ok.") - except: - print("FATAL ERROR: Can't connect to Mastodon instance") + print("FATAL ERROR: Can't construct the mastodon client app") sys.exit(1) + else: + if mastodon_api is None: + # Create application if it does not exist + try: + Mastodon.create_app('tootbot', api_base_url='https://'+instance, to_file=auth_session) + except: + print('FATAL ERROR: Failed to create app on instance '+instance) + sys.exit(1) + try: + if debug: print("Trying to connect with ", instance+'.secret', " to ", 'https://'+instance, " ...", end='') + mastodon_api = Mastodon(client_id=auth_session, api_base_url='https://'+instance) + if debug: print(" ok.") + except: + print("FATAL ERROR: Can't connect to Mastodon instance") + sys.exit(1) - if debug: print("Login with email ",mastodon_account_email," ...", end='') - try: - mastodon_api.log_in( - mastodon_account_email, - passwd, - to_file='/var/run/lock/'+instance+'.secret' - ) - if debug: print(" ok.") - except: - print("FATAL ERROR: First Login Failed !") - sys.exit(1) + if debug: print("Login with email ", mastodon_email_account, " ...", end='') + try: + mastodon_api.log_in(mastodon_email_account, mastodon_email_password, to_file=auth_session) + if debug: print(" ok.") + except: + print("FATAL ERROR: First Login Failed !") + sys.exit(1) # construct the toot toot_body = tweet.title @@ -164,7 +189,7 @@ for tweet in reversed(d.entries): try: toot = mastodon_api.status_post(toot_body, in_reply_to_id=None, media_ids=toot_media, sensitive=False, visibility='public', spoiler_text=None) if "id" in toot: - db.execute("INSERT INTO tweets VALUES ( ? , ? , ? , ? , ? )",(tweet.id, toot["id"], source, mastodon, instance)) + db.execute("INSERT INTO tweets VALUES ( ? , ? , ? , ? , ? )",(tweet.id, toot["id"], source, mastodon_account, instance)) sql.commit() except: print("ERROR: Can't toot! Sorry, skipping this one") @@ -174,3 +199,4 @@ for tweet in reversed(d.entries): if debug: print(".",end='') if debug: print(" done.") +# end -- GitLab