tootbot/tootbot.py

135 lines
4.4 KiB
Python
Raw Normal View History

2017-05-28 07:41:05 +00:00
import os.path
import sys
2019-04-03 15:44:07 +00:00
import re
import sqlite3
from datetime import datetime, timedelta
2017-05-28 07:41:05 +00:00
import feedparser
from mastodon import Mastodon
import requests
if len(sys.argv) < 4:
2019-06-25 13:05:16 +00:00
print("Usage: python3 tootbot.py twitter_account mastodon_login mastodon_passwd mastodon_instance [max_days [footer_tags [delay]]]") # noqa
2017-05-28 07:41:05 +00:00
sys.exit(1)
# sqlite db to store processed tweets (and corresponding toots ids)
sql = sqlite3.connect('tootbot.db')
db = sql.cursor()
2019-04-03 15:46:13 +00:00
db.execute('''CREATE TABLE IF NOT EXISTS tweets (tweet text, toot text,
twitter text, mastodon text, instance text)''')
2017-05-28 07:41:05 +00:00
2019-04-03 15:46:13 +00:00
if len(sys.argv) > 4:
2017-05-28 07:41:05 +00:00
instance = sys.argv[4]
else:
instance = 'amicale.net'
2019-04-03 15:46:13 +00:00
if len(sys.argv) > 5:
days = int(sys.argv[5])
else:
days = 1
2019-04-03 15:47:28 +00:00
if len(sys.argv) > 6:
tags = sys.argv[6]
else:
tags = None
2019-06-25 13:05:16 +00:00
if len(sys.argv) > 7:
delay = int(sys.argv[7])
else:
delay = 0
2019-04-03 15:47:28 +00:00
source = sys.argv[1]
2017-05-28 07:41:05 +00:00
mastodon = sys.argv[2]
passwd = sys.argv[3]
mastodon_api = None
2017-05-28 07:41:05 +00:00
2019-04-03 15:47:28 +00:00
if source[:4] == 'http':
d = feedparser.parse(source)
twitter = None
else:
d = feedparser.parse('http://twitrss.me/twitter_user_to_rss/?user='+source)
twitter = source
2017-05-28 07:41:05 +00:00
for t in reversed(d.entries):
# check if this tweet has been processed
2019-04-03 15:46:13 +00:00
db.execute('SELECT * FROM tweets WHERE tweet = ? AND twitter = ? and mastodon = ? and instance = ?', (t.id, source, mastodon, instance)) # noqa
2017-05-28 07:41:05 +00:00
last = db.fetchone()
2019-04-03 15:46:53 +00:00
dt = t.published_parsed
age = datetime.now()-datetime(dt.tm_year, dt.tm_mon, dt.tm_mday,
dt.tm_hour, dt.tm_min, dt.tm_sec)
2019-06-25 13:05:16 +00:00
# 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 not os.path.isfile(instance+'.secret'):
if Mastodon.create_app(
'tootbot',
api_base_url='https://'+instance,
2019-04-03 15:46:13 +00:00
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)
2017-05-28 07:41:05 +00:00
c = t.title
2019-04-03 15:47:28 +00:00
if twitter and t.author.lower() != ('(@%s)' % twitter).lower():
2017-06-09 13:00:10 +00:00
c = ("RT https://twitter.com/%s\n" % t.author[2:-1]) + c
2017-05-28 07:41:05 +00:00
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'])
2019-04-03 15:47:28 +00:00
# replace short links by original URL
2017-05-28 07:41:05 +00:00
m = re.search(r"http[^ \xa0]*", c)
2019-04-03 15:47:28 +00:00
if m is not None:
2017-05-28 07:41:05 +00:00
l = m.group(0)
r = requests.get(l, allow_redirects=False)
2019-04-03 15:46:13 +00:00
if r.status_code in {301, 302}:
c = c.replace(l, r.headers.get('Location'))
2017-05-28 07:41:05 +00:00
# remove pic.twitter.com links
m = re.search(r"pic.twitter.com[^ \xa0]*", c)
2019-04-03 15:47:28 +00:00
if m is not None:
2017-05-28 07:41:05 +00:00
l = m.group(0)
2019-04-03 15:46:13 +00:00
c = c.replace(l, ' ')
2017-05-28 07:41:05 +00:00
# remove ellipsis
2019-04-03 15:47:28 +00:00
c = c.replace('\xa0', ' ')
if twitter is None:
c = c + '\nSource: '+ t.authors[0].name +'\n\n' + t.link
if tags:
c = c + '\n' + tags
2017-05-28 07:41:05 +00:00
if toot_media is not None:
2019-04-03 15:46:13 +00:00
toot = mastodon_api.status_post(c, in_reply_to_id=None,
media_ids=toot_media,
sensitive=False,
visibility='public',
spoiler_text=None)
2017-05-28 07:41:05 +00:00
if "id" in toot:
db.execute("INSERT INTO tweets VALUES ( ? , ? , ? , ? , ? )",
2019-04-03 15:47:28 +00:00
(t.id, toot["id"], source, mastodon, instance))
2017-05-28 07:41:05 +00:00
sql.commit()