From 7815113bdb9e49c30ba58f9983273cb2f7039b5e Mon Sep 17 00:00:00 2001 From: cquest Date: Sun, 28 May 2017 09:41:05 +0200 Subject: [PATCH] first commit --- cron-sample.sh | 11 ++++++ requirements.txt | 4 ++ tootbot.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 cron-sample.sh create mode 100644 requirements.txt create mode 100755 tootbot.py diff --git a/cron-sample.sh b/cron-sample.sh new file mode 100644 index 0000000..a5f7d26 --- /dev/null +++ b/cron-sample.sh @@ -0,0 +1,11 @@ +# activate virtualenv if necessary +# source /home/cquest/.virtualenvs/tootbot/bin/activate + +# parameters: +# 1- twitter account to clone +# 2- mastodon login +# 3- mastodon password +# 4- instance domain (https:// is automatically added) + +python tootbot.py geonym_fr geonym@amicale.net **password** test.amicale.net +python tootbot.py cq94 cquest@amicale.net **password** test.amicale.net diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d7b9053 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +feedparser +Mastodon.py +requests + diff --git a/tootbot.py b/tootbot.py new file mode 100755 index 0000000..253615c --- /dev/null +++ b/tootbot.py @@ -0,0 +1,96 @@ +import os.path +import sys +import feedparser +from mastodon import Mastodon +import json +import requests +import re +import sqlite3 +from datetime import datetime, date, time, timedelta + +if len(sys.argv) < 3: + print("Usage: python3 tootbot.py twitter_account mastodon_login mastodon_passwd mastodon_instance") + sys.exit(1) + +# sqlite db to store processed tweets (and corresponding toots ids) +sql = sqlite3.connect('tootbot.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)>3: + instance = sys.argv[4] +else: + instance = 'amicale.net' + +twitter = sys.argv[1] +mastodon = sys.argv[2] +passwd = sys.argv[3] + +# Create application if it does not exist +if not os.path.isfile(instance+'.secret'): + if Mastodon.create_app( + 'tootbot', + api_base_url='https://'+instance, + to_file = instance+'.secret' + ): + print('tootbot app created on instance '+instance) + else: + print('failed to create app on instance '+instance) + sys.exit(1) + +try: + mastodon_api = Mastodon( + client_id=instance+'.secret', + api_base_url='https://'+instance + ) + mastodon_api.log_in( + username=mastodon, + password=passwd, + scopes=['read', 'write'], + to_file=mastodon+".secret" + ) +except: + print("ERROR: First Login Failed!") + sys.exit(1) + +d = feedparser.parse('http://twitrss.me/twitter_user_to_rss/?user='+twitter) + +for t in reversed(d.entries): + # check if this tweet has been processed + db.execute('SELECT * FROM tweets WHERE tweet = ? AND twitter = ? and mastodon = ? and instance = ?',(t.id, twitter, mastodon, instance)) + last = db.fetchone() + + # process only unprocessed tweets less than 1 day old + if last is None and (datetime.now()-datetime(t.published_parsed.tm_year, t.published_parsed.tm_mon, t.published_parsed.tm_mday, t.published_parsed.tm_hour, t.published_parsed.tm_min, t.published_parsed.tm_sec) < timedelta(days=1)): + #h = BeautifulSoup(t.summary_detail.value, "html.parser") + c = t.title + toot_media = [] + # get the pictures... + for p in re.finditer(r"https://pbs.twimg.com/[^ \xa0\"]*", t.summary): + media = requests.get(p.group(0)) + media_posted = mastodon_api.media_post(media.content, mime_type=media.headers.get('content-type')) + toot_media.append(media_posted['id']) + + # replace t.co link by original URL + m = re.search(r"http[^ \xa0]*", c) + if m != None: + l = m.group(0) + r = requests.get(l, allow_redirects=False) + if r.status_code in {301,302}: + c = c.replace(l,r.headers.get('Location')) + + # remove pic.twitter.com links + m = re.search(r"pic.twitter.com[^ \xa0]*", c) + if m != None: + l = m.group(0) + c = c.replace(l,'') + + # remove ellipsis + c = c.replace('\xa0…','') + + if toot_media is not None: + toot = mastodon_api.status_post(c, 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 ( ? , ? , ? , ? , ? )", + (t.id, toot["id"], twitter, mastodon, instance)) + sql.commit()