#!/usr/bin/python3 from mastodon import Mastodon from dateutil.parser import parse import tweepy, wget, os, time, json settings_path = './settings.json' with open(settings_path, 'r+') as fp: settings = json.load(fp) fp.close() mastodon_instance = settings["mastodon"]["instance"] clientcreds = settings["mastodon"]["clientcreds"] transitions = settings["transitions"] consumer_key = settings["twitter"]["consumer_key"] consumer_secret = settings["twitter"]["consumer_secret"] access_token_key = settings["twitter"]["access_token_key"] access_token_secret = settings["twitter"]["access_token_secret"] # Connect with Mastodon API if not os.path.isfile(clientcreds): Mastodon.create_app( 'MastoBot', api_base_url = mastodon_instance, to_file = clientcreds ) mastodon = Mastodon(client_id = clientcreds, api_base_url = mastodon_instance) #Connect with Twitter API auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token_key, access_token_secret) twitter_api = tweepy.API(auth) # Looping the accounts for account in transitions: # Connect with Mastodon-Account try: usercreds = mastodon.log_in( account['masto_username'].lower(), account['masto_passwd'] ) except: print(account['masto_username'].lower()) print("Login failed!") continue mastodon = Mastodon( client_id = clientcreds, access_token = usercreds, api_base_url = mastodon_instance ) # Looping the twitter statuses statuses = twitter_api.user_timeline(screen_name = account['twitter_handle'], since_id = int(account['last_id']), count=25, tweet_mode="extended") for status in reversed(statuses): mastodon_text = "" masto_media = [] # Does a extended_entities Array exist and does it contain info about media? if "extended_entities" in status._json and "media" in status._json['extended_entities']: media = status._json['extended_entities']['media'] # Post any media on Mastodon instance an save it to a list which will later be given to status. for medium in media: tmp_path = os.path.join("/tmp/", medium['id_str'] + '.jpg') if medium['type'] == 'photo': photo = wget.download(medium['media_url_https'], tmp_path) # masto_photo = mastodon.media_post(tmp_path) # masto_media.append(masto_photo) # Is the post a retweet? Then give info about source to toot and get full text from there. if 'retweeted_status' in status._json: mastodon_text += "RT from " + status._json['retweeted_status']['user']['name'] + ": \n" tweet_text = status._json['retweeted_status']['full_text'] tweet_origin = status._json['retweeted_status']['id_str'] # derefering twitter short urls to expanded for url in status._json['retweeted_status']['entities']["urls"]: tweet_text = tweet_text.replace(url["url"], url["expanded_url"]) else: tweet_text = status.full_text tweet_origin = status.id_str # derefering twitter short urls to expanded for url in status.entities["urls"]: tweet_text = tweet_text.replace(url["url"], url["expanded_url"]) mastodon_text += tweet_text # Add info about source and a related link to toot. mastodon_text += "\n\nPosted " + parse(str(status.created_at)).strftime("%d. %B %Y - %H:%M on Twitter") mastodon_text += "\nOrigin: https://twitter.com/" + account['twitter_handle'] + "/status/" + tweet_origin # Make sure that 500 char limit of Mastodon-API doesn't break the script if len(mastodon_text) > 500: mastodon_text = mastodon_text[:489] # Output text to stdout respect. post it to Mastodon. print(mastodon_text) try: # mastodon.status_post(mastodon_text, None, masto_media, True, None,spoiler_text="Twitter RT") continue except: print(account['twitter_handle'] + " couldn't toot to fediverse!\n") continue # mastodon.status_post(mastodon_text, None, masto_media, True) time.sleep(2) # If there are new statuses for account update the "last_id" to the newest one. if statuses: print(account['twitter_handle'] + " : " + str(status.id)) #account['last_id'] = str(status.id) # Write updated settings to json-file with open(settings_path, 'w') as fp: json.dump(settings,fp) fp.close()