Browse Source

first commit

master
cquest 7 years ago
parent
commit
7815113bdb
3 changed files with 111 additions and 0 deletions
  1. +11
    -0
      cron-sample.sh
  2. +4
    -0
      requirements.txt
  3. +96
    -0
      tootbot.py

+ 11
- 0
cron-sample.sh View File

@@ -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

+ 4
- 0
requirements.txt View File

@@ -0,0 +1,4 @@
feedparser
Mastodon.py
requests


+ 96
- 0
tootbot.py View File

@@ -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()

Loading…
Cancel
Save