#!/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//status/') 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))