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