#!/usr/bin/python3.8 from mastodon import Mastodon import sys import os import re import sys import argparse import time parser = argparse.ArgumentParser(description='Remove follow requests that match the following filters:\n1: Has less than n (defaults to 1) posts\n2: Has no profile picture\n3: Has no bio\n\nAdding extra filters is somewhat easy if you are familiar with python as well as the mastodon.py wrapper.', formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-t', '--threshold', action='store', type=int, help='The amount of filters the request has to pass to not be automatically declined, defaults to 1 (setting this to a number higher than the amount of availible filters will deny every request in the list)', default=1, dest='threshold' ) parser.add_argument('-i', '--instances', action='store', type=str, help='block follow requests from these instances (comma seperated list)', default=None, dest='instances' ) parser.add_argument('-p', '--posts', action='store', type=int, help='The minimum number of posts a user must have to pass the posts filter (does not include boosts), defaults to 1', default=1, dest='minposts' ) parser.add_argument('-y', '--yes', action='store_const', const=True, help='Skips asking for confirmation before denying requests, use this if you want to automate this script.', default=False, dest='auto' ) parser.add_argument('-s', '--simulate', action='store_const', const=True, help='Simulates the process without modifying anything', default=False, dest='simulate' ) parser.add_argument('-a', '--accept', action='store_const', const=True, help='Automatically accept requests that arent rejected', default=False, dest='accept' ) parser.add_argument('-l', '--loop', action='store', type=int, help='Loop command every x hours', default=None, dest='loop' ) args = parser.parse_args() threshold = args.threshold minposts = args.minposts auto = args.auto simulate = args.simulate accept= args.accept loop = args.loop instances = args.instances if instances is not None: instances = instances.split(", ") if type(loop) == int: loop = loop * 60 * 60 # Ensure Fediverse credentials parent = os.path.dirname(os.path.realpath(__file__)) if os.path.exists(os.path.join(parent, '.creds')) == False: os.mkdir(os.path.join(parent, '.creds')) if os.path.exists(os.path.join(parent, '.creds', 'client.secret')) == False: instance = input('Please enter your instance: ') if not instance[:4] == 'http': instance = 'https://' + instance Mastodon.create_app('Wardyns fedi tools', api_base_url = instance, to_file = os.path.join(parent, '.creds', 'client.secret')) mastodon = Mastodon( client_id = os.path.join(parent, '.creds', 'client.secret'), ) if os.path.exists(os.path.join(parent, '.creds', 'user.secret')) == False: username = input('Enter your username: ') password = input('Enter your password: ') mastodon.log_in(username=username, password=password, scopes=['read', 'write'], to_file=os.path.join(parent, '.creds', 'user.secret')) mastodon = Mastodon( access_token = os.path.join(parent, '.creds', 'user.secret') ) def filterposts(min, request): posts = request['statuses_count'] if posts >= min: return(True) else: return(False) def filterbio(request): if request['note'] == '

': return(False) else: return(True) def filterpfp(request): if request['avatar'] == mastodon.api_base_url + '/avatars/original/missing.png' or request['avatar'] == mastodon.api_base_url + '/images/avi.png': return(False) else: return(True) while True: denied=[] accepted=[] while True: try: requests = mastodon.follow_requests() break except: continue if len(requests) > 0: for request in requests: #print(request['fqn']) #print(request['id']) postcheck = filterposts(minposts, request) pfpcheck = filterpfp(request) biocheck = filterbio(request) #print('Has more than one post?: ' + str(postcheck)) #print('Has a pfp?: ' + str(pfpcheck)) #print('Has a bio?: ' + str(biocheck)) following = mastodon.account_relationships(request)[0]['following'] blockedinstance = False if instances is not None: blockedinstance = request['fqn'].split('@')[-1] in instances if postcheck + biocheck + pfpcheck < threshold and following == False or blockedinstance == True: denied.append(request) elif accept == True: accepted.append(request) print('DENIED: ') for request in denied: print(request['fqn']) confirm = None if auto == False: while True: confirm = input('Deny these requests? (y/n): ') if confirm == 'n': pass elif not confirm == 'y': print('Not recognized, try again') continue break if auto == True or confirm == 'y': for request in denied: if simulate: print('This is where ' + request['fqn'] + ' would be rejected') else: mastodon.follow_request_reject(request['id']) for request in accepted: if simulate: print('This is where ' + request['fqn'] + ' would be accepted') else: mastodon.follow_request_authorize(request['id']) if loop == None: break else: time.sleep(loop)