165 lines
5.4 KiB
Python
Executable File
165 lines
5.4 KiB
Python
Executable File
#!/usr/bin/python3
|
||
# coding: utf-8
|
||
|
||
import twitter
|
||
from mastodon import Mastodon
|
||
from configparser import ConfigParser
|
||
import urllib.request
|
||
import sys
|
||
import os.path
|
||
import re
|
||
|
||
|
||
__prog_name__ = 'tweet2toot'
|
||
__version__ = '0.2'
|
||
__description__ = 'Toot a tweet on Mastodon'
|
||
|
||
# Définition des variables
|
||
toot_status = ''
|
||
media_dict = None
|
||
DEBUG = False
|
||
url_tweet_regex = r'/^https?:\/\/twitter\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)$/'
|
||
temp_path = ''
|
||
|
||
# Function to scrap the tweet media file and attach them to the toot
|
||
def addmedia(medias):
|
||
for media in medias:
|
||
if media.type == 'photo':
|
||
media_url = media.media_url
|
||
if media.type == 'animated_gif':
|
||
media_url = media.video_info['variants'][0]['url']
|
||
if media.type == 'video':
|
||
bitratemax = 800000 # Mastodon media size limited to 8Mo
|
||
bitrate = 0
|
||
# Find the best media video
|
||
for i in media.video_info['variants']:
|
||
if ('bitrate' in i) and (i['bitrate'] > bitrate) \
|
||
and (i['bitrate'] < bitratemax):
|
||
bitrate = i['bitrate']
|
||
media_url = i['url']
|
||
media_url = media_url.split('?')[0]
|
||
# Get the media filename with the mediaurl
|
||
media_filename = media_url.split('/')[-1]
|
||
# Downloading the media
|
||
local_filename, headers = urllib.request.urlretrieve(
|
||
media_url,
|
||
filename=temp_path + '/' + media_filename,
|
||
reporthook=None,
|
||
data=None)
|
||
# Add this media to the MediaDict Toot
|
||
media_dict.append(mastodonAPI.media_post(local_filename))
|
||
return media_dict
|
||
|
||
|
||
# Reading the script parameters into config.ini
|
||
conf = ConfigParser()
|
||
conf.read('config.ini')
|
||
|
||
# Check if the cache directory exist
|
||
if not os.path.exists(conf['app']['cache_path_dir']):
|
||
os.mkdir(conf['app']['cache_path_dir'])
|
||
temp_path = conf['app']['cache_path_dir']
|
||
|
||
# Use the first argument passed as URL tweet or ask it
|
||
if len(sys.argv) > 1:
|
||
url_tweet = sys.argv[1]
|
||
else:
|
||
url_tweet = input("URL ? ")
|
||
|
||
# TODO : a reverifier
|
||
if re.match(url_tweet_regex, url_tweet) is not None:
|
||
print ('[ERROR] The URL status is incorrect')
|
||
print ('The correct format is : https://twitter.com/<username>/status/<ID>')
|
||
sys.exit(0)
|
||
else:
|
||
# Decompose the tweet URL to find the ID tweet
|
||
id_tweet = url_tweet.split('/')[-1]
|
||
|
||
# Log into Twitter via API
|
||
try:
|
||
twitterAPI = twitter.Api(
|
||
consumer_key=conf['twitter']['TWITTER_API_KEY'],
|
||
consumer_secret=conf['twitter']['TWITTER_API_SECRET'],
|
||
access_token_key=conf['twitter']['TWITTER_ACCESS_TOKEN'],
|
||
access_token_secret=conf['twitter']['TWITTER_ACCESS_TOKEN_SECRET'],
|
||
tweet_mode='extended'
|
||
)
|
||
twitter_hostname = conf['twitter']['TWITTER_INSTANCE']
|
||
twitter_username = twitterAPI.VerifyCredentials().screen_name
|
||
print ('[ OK ] Sucessfully authenticated on ' + twitter_hostname
|
||
+ ' as @' + twitter_username)
|
||
except BaseException as e:
|
||
print ('[ERROR] Error while logging into Twitter:', str(e))
|
||
sys.exit(0)
|
||
|
||
# Retrieve the tweet with the ID tweet
|
||
tweet = twitterAPI.GetStatus(status_id=id_tweet)
|
||
|
||
# Log into Mastodon via API
|
||
mastodon_hostname = conf['mastodon']['MASTODON_INSTANCE']
|
||
try:
|
||
mastodonAPI = Mastodon(
|
||
client_id=conf['mastodon']['MASTODON_APPID'],
|
||
client_secret=conf['mastodon']['MASTODON_APPSECRET'],
|
||
access_token=conf['mastodon']['MASTODON_APPTOKEN'],
|
||
api_base_url='https://' + mastodon_hostname)
|
||
masto_username = mastodonAPI.account_verify_credentials()['username']
|
||
print ('[ OK ] Sucessfully authenticated on ' + mastodon_hostname
|
||
+ ' as @' + masto_username)
|
||
except BaseException as e:
|
||
print ('[ERROR] Error while logging into Mastodon:', str(e))
|
||
sys.exit(0)
|
||
|
||
'''
|
||
Construct the toot status with the tweet status
|
||
'''
|
||
# The toot base
|
||
toot_status += 'RT @' + tweet.user.screen_name + '@twitter.com'
|
||
toot_status += '\n \n'
|
||
toot_status += tweet.full_text
|
||
# Attach the tweet media files to the toot
|
||
if tweet.media:
|
||
media_dict = []
|
||
addmedia(tweet.media)
|
||
# Retrieve the tweet quoted and
|
||
if tweet.quoted_status:
|
||
toot_status += '\n\n'
|
||
toot_status += '❝ '
|
||
#toot_status += '\n'
|
||
idtweetquoted = tweet.quoted_status.id_str
|
||
tweetquoted = twitterAPI.GetStatus(status_id=idtweetquoted)
|
||
toot_status += '@' + tweetquoted.user.screen_name + '@twitter.com'
|
||
toot_status += '\n'
|
||
toot_status += tweetquoted.full_text
|
||
#toot_status += '\n'
|
||
toot_status += ' ❞'
|
||
# Attach the tweet quoted media files to the toot
|
||
if tweetquoted.media:
|
||
media_dict = []
|
||
addmedia(tweetquoted.media)
|
||
# Add the tweet source link
|
||
toot_status += '\n\n'
|
||
toot_status += '🔗' + url_tweet
|
||
if DEBUG :
|
||
print(toot_status)
|
||
print(len(toot_status))
|
||
|
||
'''
|
||
Sending the toot
|
||
'''
|
||
|
||
try:
|
||
status = mastodonAPI.status_post(
|
||
status=toot_status,
|
||
in_reply_to_id=None,
|
||
media_ids=media_dict,
|
||
sensitive=False,
|
||
visibility='public',
|
||
spoiler_text=None
|
||
)
|
||
print (
|
||
'[ OK ] Posting this on Mastodon account with media attachment : '
|
||
+ status['url'])
|
||
except BaseException as e:
|
||
print ('[ERROR] Error while posting toot:' + str(e))
|
||
|