Browse Source

first commit

cquest 4 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

@@ -0,0 +1,11 @@
1
+# activate virtualenv if necessary
2
+# source /home/cquest/.virtualenvs/tootbot/bin/activate
3
+
4
+# parameters:
5
+# 1- twitter account to clone
6
+# 2- mastodon login
7
+# 3- mastodon password
8
+# 4- instance domain (https:// is automatically added)
9
+
10
+python tootbot.py geonym_fr geonym@amicale.net **password** test.amicale.net
11
+python tootbot.py cq94 cquest@amicale.net **password** test.amicale.net

+ 4 - 0
requirements.txt

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

+ 96 - 0
tootbot.py

@@ -0,0 +1,96 @@
1
+import os.path
2
+import sys
3
+import feedparser
4
+from mastodon import Mastodon
5
+import json
6
+import requests
7
+import re
8
+import sqlite3
9
+from datetime import datetime, date, time, timedelta
10
+
11
+if len(sys.argv) < 3:
12
+    print("Usage: python3 tootbot.py twitter_account mastodon_login mastodon_passwd mastodon_instance")
13
+    sys.exit(1)
14
+
15
+# sqlite db to store processed tweets (and corresponding toots ids)
16
+sql = sqlite3.connect('tootbot.db')
17
+db = sql.cursor()
18
+db.execute('''CREATE TABLE IF NOT EXISTS tweets (tweet text, toot text, twitter text, mastodon text, instance text)''')
19
+
20
+if len(sys.argv)>3:
21
+    instance = sys.argv[4]
22
+else:
23
+    instance = 'amicale.net'
24
+
25
+twitter = sys.argv[1]
26
+mastodon = sys.argv[2]
27
+passwd = sys.argv[3]
28
+
29
+# Create application if it does not exist
30
+if not os.path.isfile(instance+'.secret'):
31
+    if Mastodon.create_app(
32
+        'tootbot',
33
+        api_base_url='https://'+instance,
34
+        to_file = instance+'.secret'
35
+    ):
36
+        print('tootbot app created on instance '+instance)
37
+    else:
38
+        print('failed to create app on instance '+instance)
39
+        sys.exit(1)
40
+
41
+try:
42
+    mastodon_api = Mastodon(
43
+      client_id=instance+'.secret',
44
+      api_base_url='https://'+instance
45
+    )
46
+    mastodon_api.log_in(
47
+        username=mastodon,
48
+        password=passwd,
49
+        scopes=['read', 'write'],
50
+        to_file=mastodon+".secret"
51
+    )
52
+except:
53
+    print("ERROR: First Login Failed!")
54
+    sys.exit(1)
55
+
56
+d = feedparser.parse('http://twitrss.me/twitter_user_to_rss/?user='+twitter)
57
+
58
+for t in reversed(d.entries):
59
+    # check if this tweet has been processed
60
+    db.execute('SELECT * FROM tweets WHERE tweet = ? AND twitter = ?  and mastodon = ? and instance = ?',(t.id, twitter, mastodon, instance))
61
+    last = db.fetchone()
62
+
63
+    # process only unprocessed tweets less than 1 day old
64
+    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)):
65
+        #h = BeautifulSoup(t.summary_detail.value, "html.parser")
66
+        c = t.title
67
+        toot_media = []
68
+        # get the pictures...
69
+        for p in re.finditer(r"https://pbs.twimg.com/[^ \xa0\"]*", t.summary):
70
+            media = requests.get(p.group(0))
71
+            media_posted = mastodon_api.media_post(media.content, mime_type=media.headers.get('content-type'))
72
+            toot_media.append(media_posted['id'])
73
+
74
+        # replace t.co link by original URL
75
+        m = re.search(r"http[^ \xa0]*", c)
76
+        if m != None:
77
+            l = m.group(0)
78
+            r = requests.get(l, allow_redirects=False)
79
+            if r.status_code in {301,302}:
80
+                c = c.replace(l,r.headers.get('Location'))
81
+
82
+        # remove pic.twitter.com links
83
+        m = re.search(r"pic.twitter.com[^ \xa0]*", c)
84
+        if m != None:
85
+            l = m.group(0)
86
+            c = c.replace(l,'')
87
+
88
+        # remove ellipsis
89
+        c = c.replace('\xa0…','')
90
+
91
+        if toot_media is not None:
92
+            toot = mastodon_api.status_post(c, in_reply_to_id=None, media_ids=toot_media, sensitive=False, visibility='public', spoiler_text=None)
93
+            if "id" in toot:
94
+                db.execute("INSERT INTO tweets VALUES ( ? , ? , ? , ? , ? )",
95
+                (t.id, toot["id"], twitter, mastodon, instance))
96
+                sql.commit()