Remove mastodon.py dependency
This commit is contained in:
parent
e256ad251c
commit
69b73260e7
|
@ -0,0 +1 @@
|
|||
config.json
|
108
autodeny.py
108
autodeny.py
|
@ -1,13 +1,21 @@
|
|||
#!/usr/bin/python3.8
|
||||
from mastodon import Mastodon
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
|
||||
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)
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
if not os.path.exists(os.path.join(parent, 'config.json')):
|
||||
generate_config("Wardyn's feditools", "read write follow push")
|
||||
with open(os.path.join(parent, 'config.json'), 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
session = requests.Session()
|
||||
session.headers.update({"Authorization" : "Bearer " + config['user_token']})
|
||||
|
||||
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', formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('-t', '--threshold',
|
||||
action='store',
|
||||
type=int,
|
||||
|
@ -22,6 +30,13 @@ parser.add_argument('-i', '--instances',
|
|||
default=None,
|
||||
dest='instances'
|
||||
)
|
||||
parser.add_argument('-b', '--blank',
|
||||
action='store',
|
||||
type=str,
|
||||
default=None,
|
||||
help='If your instance has a custom image for blank pfps set, please specify the url to the image with this flag',
|
||||
dest='custompfp'
|
||||
)
|
||||
parser.add_argument('-p', '--posts',
|
||||
action='store',
|
||||
type=int,
|
||||
|
@ -65,81 +80,56 @@ simulate = args.simulate
|
|||
accept= args.accept
|
||||
loop = args.loop
|
||||
instances = args.instances
|
||||
custompfp = args.custompfp
|
||||
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'))
|
||||
blanks = [config['instance'] + '/avatars/original/missing.png', config['instance'] + '/images/avi.png']
|
||||
if custompfp:
|
||||
blanks.append(custompfp)
|
||||
|
||||
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']
|
||||
def filterposts(min, follow_request):
|
||||
posts = follow_request['statuses_count']
|
||||
if posts >= min:
|
||||
return(True)
|
||||
else:
|
||||
return(False)
|
||||
def filterbio(request):
|
||||
if request['note'] == '<p></p>':
|
||||
def filterbio(follow_request):
|
||||
if follow_request['note'] == '<p></p>':
|
||||
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':
|
||||
def filterpfp(follow_request):
|
||||
if follow_request['avatar'] in blanks:
|
||||
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']
|
||||
|
||||
follow_requests = session.get(config['instance'] + '/api/v1/follow_requests', params={'limit':80}).json()
|
||||
|
||||
if len(follow_requests) > 0:
|
||||
for follow_request in follow_requests:
|
||||
postcheck = filterposts(minposts, follow_request)
|
||||
pfpcheck = filterpfp(follow_request)
|
||||
biocheck = filterbio(follow_request)
|
||||
|
||||
following = session.get(config['instance'] + '/api/v1/accounts/relationships', params={'id':follow_request['id']}).json()[0]['following']
|
||||
blockedinstance = False
|
||||
if instances is not None:
|
||||
blockedinstance = request['fqn'].split('@')[-1] in instances
|
||||
blockedinstance = follow_request['fqn'].split('@')[-1] in instances
|
||||
if postcheck + biocheck + pfpcheck < threshold and following == False or blockedinstance == True:
|
||||
denied.append(request)
|
||||
denied.append(follow_request)
|
||||
elif accept == True:
|
||||
accepted.append(request)
|
||||
accepted.append(follow_request)
|
||||
print('DENIED: ')
|
||||
for request in denied:
|
||||
print(request['fqn'])
|
||||
for follow_request in denied:
|
||||
print(follow_request['fqn'])
|
||||
confirm = None
|
||||
if auto == False:
|
||||
while True:
|
||||
|
@ -151,16 +141,16 @@ while True:
|
|||
continue
|
||||
break
|
||||
if auto == True or confirm == 'y':
|
||||
for request in denied:
|
||||
for follow_request in denied:
|
||||
if simulate:
|
||||
print('This is where ' + request['fqn'] + ' would be rejected')
|
||||
print('This is where ' + follow_request['fqn'] + ' would be rejected')
|
||||
else:
|
||||
mastodon.follow_request_reject(request['id'])
|
||||
for request in accepted:
|
||||
session.post(config['instance'] + '/api/v1/follow_requests/' + follow_request['id'] + '/reject')
|
||||
for follow_request in accepted:
|
||||
if simulate:
|
||||
print('This is where ' + request['fqn'] + ' would be accepted')
|
||||
print('This is where ' + follow_request['fqn'] + ' would be accepted')
|
||||
else:
|
||||
mastodon.follow_request_authorize(request['id'])
|
||||
session.post(config['instance'] + '/api/v1/follow_requests/' + follow_request['id'] + '/authorize')
|
||||
if loop == None:
|
||||
break
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"instance":"",
|
||||
"client_id":"",
|
||||
"client_secret":"",
|
||||
"user_token":""
|
||||
}
|
|
@ -1,9 +1,19 @@
|
|||
# Import modules
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import html2text
|
||||
from argparse import ArgumentParser
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
if not os.path.exists(os.path.join(parent, 'config.json')):
|
||||
generate_config("Wardyn's feditools", "read write follow push")
|
||||
with open(os.path.join(parent, 'config.json'), 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
|
||||
session = requests.Session()
|
||||
session.headers.update({"Authorization" : "Bearer " + config['user_token']})
|
||||
|
||||
# Initialize arguments
|
||||
parser = ArgumentParser(description='Search a fedi users posts for a specific word or phrase')
|
||||
|
@ -36,30 +46,6 @@ dms = args.dms
|
|||
account = args.account
|
||||
pattern = args.pattern
|
||||
|
||||
# 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')
|
||||
)
|
||||
|
||||
# Main block
|
||||
if case == False:
|
||||
pattern = pattern.lower()
|
||||
|
@ -70,8 +56,8 @@ htmlconvert.body_width = 0
|
|||
if account[0] == '@':
|
||||
account = account[1:]
|
||||
if len(account.split('@')) == 1:
|
||||
account = account + '@' + mastodon.api_base_url.split('/')[2]
|
||||
accountlist = mastodon.account_search(account)
|
||||
account = account + '@' + config['instance'].split('/')[2]
|
||||
accountlist = session.get(config['instance'] + '/api/v2/search', params={'q':account}).json()['accounts']
|
||||
|
||||
for curaccount in accountlist:
|
||||
print(curaccount['fqn'])
|
||||
|
@ -85,20 +71,11 @@ accid = account['id']
|
|||
print('Searching for posts including "' + pattern + '" from user ' + account['fqn'])
|
||||
print('\n---\n')
|
||||
while True:
|
||||
while True:
|
||||
try:
|
||||
statuses = mastodon.account_statuses(accid, max_id=oldest_status_id, limit=1000)
|
||||
break
|
||||
except IndexError:
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if len(statuses) == 0:
|
||||
break
|
||||
statuses = session.get(config['instance'] + '/api/v1/accounts/' + accid + '/statuses', params={'max_id':oldest_status_id, 'limit':40}).json()
|
||||
oldest_status_id = statuses[-1]['id']
|
||||
for status in statuses:
|
||||
if status['reblog'] == None:
|
||||
if status['visibility'] == 'direct' and dms == False:
|
||||
if status['visibility'] == 'direct' and not dms:
|
||||
continue
|
||||
content = str(htmlconvert.handle(status['content']))
|
||||
if case == False:
|
||||
|
@ -107,4 +84,6 @@ while True:
|
|||
print(content)
|
||||
print('\nlink: ' + status['url'])
|
||||
print('\n---\n')
|
||||
if len(statuses) < 40:
|
||||
break
|
||||
print('Finished searching')
|
|
@ -0,0 +1,34 @@
|
|||
import os
|
||||
import requests
|
||||
import json
|
||||
from urllib.parse import urlencode
|
||||
|
||||
def generate_config(app_name, scopes):
|
||||
#Ensure Credentials
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
with open(os.path.join(parent, 'config_template.json'), 'r') as template:
|
||||
config = json.load(template)
|
||||
|
||||
#Create app
|
||||
instance = input('Please enter your instance: ')
|
||||
if not instance[:4] == 'http':
|
||||
instance = 'https://' + instance
|
||||
|
||||
response = requests.post(instance + '/api/v1/apps', data={'client_name':app_name,'scopes':scopes, 'redirect_uris':'urn:ietf:wg:oauth:2.0:oob'}).json()
|
||||
|
||||
client_id = config['client_id'] = response['client_id']
|
||||
client_secret = config['client_secret'] = response['client_secret']
|
||||
config['instance'] = instance
|
||||
|
||||
#Log in to user account
|
||||
|
||||
print(instance + '/oauth/authorize?', urlencode({'response_type':'code', 'client_id':client_id, 'redirect_uri':'urn:ietf:wg:oauth:2.0:oob', 'scope':scopes}))
|
||||
code = input("To generate a token to access your account, " + app_name + " needs an authorization code. Please authorize using the link above and enter the code it provides you \nCode: ")
|
||||
response = requests.post(instance + '/oauth/token', data={'grant_type':'authorization_code', 'code':code, 'client_id':client_id, 'client_secret':client_secret, 'redirect_uri':'urn:ietf:wg:oauth:2.0:oob', 'scope':scopes})
|
||||
config['user_token'] = response.json()['access_token']
|
||||
|
||||
with open(os.path.join(parent, 'config.json'), 'w') as config_file:
|
||||
config_file.write(json.dumps(config))
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_config("test_app", "read")
|
|
@ -1,55 +1,59 @@
|
|||
#!/usr/bin/python3.8
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import sys
|
||||
import html2text
|
||||
import json
|
||||
import requests
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
if os.path.exists('./.creds/') == False:
|
||||
os.mkdir('./.creds')
|
||||
if os.path.exists('./.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 = './.creds/client.secret')
|
||||
if not os.path.exists(os.path.join(parent, 'config.json')):
|
||||
generate_config("Wardyn's feditools", "read write follow push")
|
||||
with open(os.path.join(parent, 'config.json'), 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
session = requests.Session()
|
||||
session.headers.update({"Authorization" : "Bearer " + config['user_token']})
|
||||
|
||||
mastodon = Mastodon(
|
||||
client_id = './.creds/client.secret',
|
||||
)
|
||||
|
||||
if os.path.exists('./.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='./.creds/user.secret')
|
||||
|
||||
|
||||
mastodon = Mastodon(
|
||||
access_token = './.creds/user.secret'
|
||||
)
|
||||
if len(sys.argv) < 2:
|
||||
if len(sys.argv) != 2:
|
||||
print('Expected 1 argument (account)')
|
||||
quit()
|
||||
else:
|
||||
highestpost = None
|
||||
oldest_status_id = None
|
||||
htmlconvert = html2text.HTML2Text()
|
||||
htmlconvert.ignore_links = True
|
||||
htmlconvert.body_width = 0
|
||||
account = sys.argv[1]
|
||||
accid = mastodon.account_search(account)[0]['id']
|
||||
while True:
|
||||
statuses = mastodon.account_statuses(accid, max_id=oldest_status_id, limit=1000)
|
||||
try:
|
||||
oldest_status_id = statuses[-1]['id']
|
||||
except IndexError:
|
||||
print('Reached end of posts')
|
||||
quit()
|
||||
for status in statuses:
|
||||
statusscore = status['reblogs_count'] + status['favourites_count']
|
||||
if status['reblogged'] == False:
|
||||
if highestpost == None or statusscore > highestpost['score']:
|
||||
highestpost = {'score' : status['reblogs_count'] + status['favourites_count'], 'post' : status}
|
||||
content = str(htmlconvert.handle(status['content']))
|
||||
print(content)
|
||||
print('Favorites: ' + str(status['favourites_count']) + ' Boosts: ' + str(status['reblogs_count']))
|
||||
print('link: ' + status['url'])
|
||||
print('-------')
|
||||
|
||||
highestpost = None
|
||||
oldest_status_id = None
|
||||
htmlconvert = html2text.HTML2Text()
|
||||
htmlconvert.ignore_links = True
|
||||
htmlconvert.body_width = 0
|
||||
account = sys.argv[1]
|
||||
|
||||
if account[0] == '@':
|
||||
account = account[1:]
|
||||
if len(account.split('@')) == 1:
|
||||
account = account + '@' + config['instance'].split('/')[-1]
|
||||
|
||||
searchlist = session.get(config['instance'] + '/api/v2/search?', params={'q':account, 'type':'accounts'}).json()['accounts']
|
||||
acc_id = None
|
||||
for user in searchlist:
|
||||
if user['fqn'].lower() == account.lower():
|
||||
acc_id = user['id']
|
||||
acc_name = user['fqn']
|
||||
break
|
||||
if not acc_id:
|
||||
print("Could not find user: " + account)
|
||||
quit()
|
||||
|
||||
#accid = session.get(config['instance'] + '/api/v2/search?', params={'q':account, 'type':'accounts'}).json()['accounts'][0]['id']
|
||||
while True:
|
||||
statuses = session.get(config['instance'] + '/api/v1/accounts/' + acc_id + '/statuses', params={"max_id":oldest_status_id, "limit":40, "exclude_reblogs":True}).json()
|
||||
try:
|
||||
oldest_status_id = statuses[-1]['id']
|
||||
except IndexError:
|
||||
print('Reached end of posts')
|
||||
quit()
|
||||
for status in statuses:
|
||||
status_score = status['reblogs_count'] + status['favourites_count']
|
||||
if highestpost == None or status_score > highestpost['score']:
|
||||
highestpost = {'score' : status['reblogs_count'] + status['favourites_count'], 'post' : status}
|
||||
content = str(htmlconvert.handle(status['content']))
|
||||
print(content)
|
||||
print('Favorites: ' + str(status['favourites_count']) + ' Boosts: ' + str(status['reblogs_count']))
|
||||
print('link: ' + status['url'])
|
||||
print('-------')
|
|
@ -0,0 +1,45 @@
|
|||
import requests
|
||||
import json
|
||||
import os
|
||||
from argparse import ArgumentParser, FileType
|
||||
from generate_config import generate_config
|
||||
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# Initialize arguments
|
||||
parser = ArgumentParser(description='Import follows from a csv file')
|
||||
parser.add_argument('file',
|
||||
type=open,
|
||||
help='csv file containing users to follow',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
csv = args.file.read()
|
||||
|
||||
if not os.path.exists(os.path.join(parent, 'config.json')):
|
||||
generate_config("Wardyn's feditools", "read write follow push")
|
||||
with open(os.path.join(parent, 'config.json'), 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
|
||||
session = requests.Session()
|
||||
session.headers.update({"Authorization" : "Bearer " + config['user_token']})
|
||||
|
||||
|
||||
acclist = csv.split('\n')
|
||||
for account in acclist:
|
||||
searchlist = session.get(config['instance'] + '/api/v2/search?', params={'q':account, 'type':'accounts'}).json()
|
||||
searchlist = searchlist['accounts']
|
||||
found = False
|
||||
for user in searchlist:
|
||||
if user['fqn'] == account:
|
||||
account = user
|
||||
found = True
|
||||
break
|
||||
if found == False:
|
||||
print("Could not find user: " + account)
|
||||
continue
|
||||
relationship = account['pleroma']['relationship']
|
||||
if relationship['following'] == True:
|
||||
print('Already following: ' + account['fqn'])
|
||||
continue
|
||||
print("Following: " + account['fqn'])
|
||||
session.post(config['instance'] + '/api/v1/accounts/' + account['id'] + '/follow')
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
import websocket
|
||||
import os
|
||||
from playsound import playsound
|
||||
from generate_config import generate_config
|
||||
import json
|
||||
|
||||
parent = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
if not os.path.exists(os.path.join(parent, 'config.json')):
|
||||
generate_config("Wardyn's feditools", "read write follow push")
|
||||
with open(os.path.join(parent, 'config.json'), 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
|
||||
sound = os.path.join(parent, 'notification.mp3')
|
||||
|
||||
def on_message(ws, message):
|
||||
print('Received notification')
|
||||
playsound(sound)
|
||||
def on_open(ws):
|
||||
print('Websocket opened')
|
||||
def on_close(ws):
|
||||
print('Websocket closed, attempting to reconnect')
|
||||
connect_websocket()
|
||||
|
||||
def connect_websocket():
|
||||
ws = websocket.WebSocketApp("wss://" + config['instance'].split('/')[-1] + "/api/v1/streaming?access_token=" + config['user_token'] + "&stream=user:notification",
|
||||
on_message = on_message, on_open = on_open, on_close = on_close, on_error=on_close)
|
||||
ws.run_forever()
|
||||
|
||||
connect_websocket()
|
Loading…
Reference in New Issue