from PIL import Image, ImageFile from common import get_api, get_new_notifications, list_read, list_append import datetime import gettext import requests import os import sys import random import string ImageFile.LOAD_TRUNCATED_IMAGES = True bot_name = "faggotree" coordinates = [ (350,200), (275,350), (425,350), (200,500), (350,500), (500,500), (125,650), (275,650), (425,650), (575,650), ] def generate_random_filename(): length = random.randint(10, 15) # Random length between 5-15 characters chars = string.ascii_lowercase + string.digits filename = ''.join(random.choice(chars) for _ in range(length)) return filename + '.png' temp_image_name = generate_random_filename() print("generated random image filename: " + temp_image_name) def get_ordered_accounts_ids(account_id): print("getting ordered accounts ids") current_year = datetime.date.today().year accounts = {} stop = False max_id=None loops = 0 while stop == False: statuses = api.account_statuses(account_id, exclude_reblogs=True, max_id=max_id, limit=40) for status in statuses: if(status.created_at.year < current_year): stop = True break print("mentions: " + str(len(status.mentions))) for mention in status.mentions: print(mention.username) if mention.username == bot_name or mention.username == status.account.username: print("skipping: " + mention.username) else: if mention.id not in accounts: accounts[mention.id] = 1 else: accounts[mention.id] = accounts[mention.id] + 1 max_id=status.id loops = loops + 1 if loops > 10 : stop = True print("stopping loop") accounts_list = sorted(accounts, key=accounts.get, reverse=True) accounts_list.insert(0,account_id) accounts_list.pop return accounts_list def get_accounts(accounts_ids): print("getting accounts: " + str(len(accounts_ids))) accounts = [] for i in range(len(accounts_ids)): account = api.account(accounts_ids[i]) accounts.append(account) if len(accounts) == len(coordinates): break return accounts def get_avatar(): try: print("trying to open: " + temp_image_name) with Image.open(temp_image_name) as avatar: avatar.load() return avatar except: print("failed to use avatar so using a default") with Image.open('feditree/default.png') as avatar: avatar.load() return avatar def create_image(accounts): print("Creating image now") with Image.open("feditree/fediverse-christmas-tree.png") as feditree: feditree.load() with Image.open("feditree/bola_radio.png") as bola_radio: bola_radio.load() with Image.open("feditree/bola_mask.png") as bola_mask: bola_mask.load() for i in range(min(len(accounts),len(coordinates))): account = api.account(accounts[i]) avatar_url = account.avatar_static avatar_data = requests.get(avatar_url).content with open(temp_image_name, 'wb') as handler: handler.write(avatar_data) avatar = get_avatar() avatar = avatar.resize((100,100)).convert("RGB") avatar.paste(bola_radio, (0,0), bola_radio) feditree.paste(avatar, coordinates[i], bola_mask) feditree.save("feditree/feditree.png") bola_radio.close() bola_mask.close() avatar.close() feditree.close() description = _("A simple drawing of a fir tree, crowned with the pentagon symbolizing the Fediverse.") description = description + " " + _("There are some christmas bulbs hanging in the tree, which have the avatars of the mentioned accounts inside.") description = description + " " + _("The accounts appear in the tree in the same order as the mentions, from top to bottom and from left to right.") description = description + " " + _("The order symbolizes the number of interactions, from most to least.") description = description + "\n\n" + _("The Fediverse logo was created by @eudaimon@fe.disroot.org and the tree design was obtained from https://freesvgdesigns.com") return api.media_post("feditree/feditree.png", description=description) localedir = './locales' api = get_api('shitposter.world', bot_name) print("getting notifications") notifications = get_new_notifications(api, bot_name, ["mention"]) print("getting previous ids") previous_ids = list_read(bot_name + "_previous_ids") print("to handle: " + str(len(notifications))) for notification in notifications: i18n = gettext.translation(bot_name, localedir, fallback=True, languages=['en']) i18n.install() print("handling for: " + notification.account.username) try: if str(notification.account.id) in previous_ids: status = "@" + notification.account.acct + " " status += _("I have already generated a faggotree for you this year. Try again next year!") api.status_post(status, visibility="direct", in_reply_to_id=notification.status.id) continue else: list_append(bot_name + "_previous_ids", str(notification.account.id)) accounts_ids = get_ordered_accounts_ids(notification.account.id) accounts = get_accounts(accounts_ids) image = create_image(accounts) status = _("These are the fags who have adorned the #FaggoTree of") + " @" + notification.account.acct + ":\n\n" for account in accounts: status += " " + account.acct + "\n" api.status_post(status, media_ids=image, visibility="unlisted", in_reply_to_id=notification.status.id) previous_ids.append(notification.account.id) except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) print(e) api.status_post(_("An error ocurred. Please try again or contact my creator"), visibility="direct", in_reply_to_id=notification.status.id) print("deleting temp image file") try: os.remove(temp_image_name) except Exception: print(f"File {temp_image_name} does not exist")