๐พ Archived View for m0yng.uk โบ 2022 โบ 05 โบ mastoWelcomer captured on 2022-07-16 at 13:28:01. Gemini links have been rewritten to link to archived content
โฌ ๏ธ Previous capture (2022-06-03)
โก๏ธ Next capture (2023-01-29)
-=-=-=-=-=-=-
Created 2022-05-22
[TOC]
I run mastodon.radio, and I have it set to require approval for new accounts. I also like to welcome every new user.
This can result in delays, as I need to do a complex dance, something like:
I wrote a snippet of JavaScript to run in the dev console to copy out the selected usernames, which helped but for security reasons you can't put stuff on the clipboard without user interaction so I still had to manually select and copy the string... the entire process is a faff.
Well, mastodon has an API, and there exists Mastodon.py
Guess what comes next?
That's right! SCOPE CREEP!
I wrote a small python script to fetch a list of pending accounts, show me the info, and let me pick which ones to approve. It then does that, and follows each account, and toots a welcome message.
It worked well!
Script output listing 3 pending accounts, details redacted [IMG]
But ...
So, I extended it a bit.
Now it also:
Script output listing 3 pending accounts, with the above improvements [IMG]
It's probably not much use to anyone else, but if you remove the callsign and QRZ lookups it might be a good base for your own?
from datetime import datetime, timezone from mastodon import Mastodon from random import choice from qrz import QRZ import humanize import pprint import re callsignRegex = '[a-zA-Z0-9]{1,3}[0-9][a-zA-Z0-9]{0,3}[a-zA-Z]' ruleCanary = 'hippo cornflakes' qrz = QRZ(cfg='./settings.cfg') pp = pprint.PrettyPrinter(indent=4) ''' create app - do this once Mastodon.create_app( 'mastoWelcome', scopes=['admin:read:accounts', 'admin:write:accounts', 'write:statuses', 'write:follows'], api_base_url = 'https://mastodon.radio', to_file = 'mastoWelcome_clientcred.secret' ) ''' ''' authorize - do this once mastodon = Mastodon( client_id = 'mastoWelcome_clientcred.secret', api_base_url = 'https://mastodon.radio' ) ''' ''' log in - do this as often as needed mastodon.log_in( 'username', 'password', scopes=['admin:read:accounts', 'admin:write:accounts', 'write:statuses', 'write:follows'], to_file = 'mastoWelcome_usercred.secret' ) ''' # connect with saved credentials mastodon = Mastodon( access_token = 'mastoWelcome_usercred.secret', api_base_url = 'https://mastodon.radio' ) pendingAccounts = mastodon.admin_accounts(status='pending') print(str(len(pendingAccounts)) + ' Pending accounts') i = 0 for pAccount in pendingAccounts: # easy to type ID print(f'\n{i}') # attempt to find callsigns allPossibleCallsigns = re.findall(callsignRegex, pAccount['username']) allPossibleCallsigns.extend(re.findall(callsignRegex, pAccount['email'])) allPossibleCallsigns.extend(re.findall(callsignRegex, pAccount['invite_request'])) # tell me about the account print(f"Username: {pAccount['username']}") print(f'{humanize.naturaltime(datetime.now(timezone.utc) - pAccount["created_at"])} {pAccount["email"]}') print(f'{pAccount["invite_request"]}') if ruleCanary in pAccount["invite_request"]: print(f'\033[93mRule Canary: {ruleCanary in pAccount["invite_request"]}\033[0m') else: print(f'\033[95mRule Canary: {ruleCanary in pAccount["invite_request"]}\033[0m') if pAccount["confirmed"]: print(f'\033[93mEmail confirmed: {pAccount["confirmed"]}\033[0m') else: print(f'\033[95mEmail confirmed: {pAccount["confirmed"]}\033[0m') # dedupe list possibleCallsigns = [] for call in allPossibleCallsigns: lowerCall = call.casefold() if lowerCall not in possibleCallsigns: possibleCallsigns.append(lowerCall) print(f'Possible Callsigns: {possibleCallsigns}') # get info from QRZ print('QRZ info') for call in possibleCallsigns: result = qrz.callsign(call) pp.pprint(result) i+=1 # ask me what accounts look OK approveWhat = input("Which accounts to approve?: ") # split the space separated list approveWhat = approveWhat.split() print('\nYou want to approve these account:') for aAccount in approveWhat: print(pendingAccounts[int(aAccount)]['username']) # make a case sensitive YES to make sure I'm paying attention confirmYES = ''.join(map(choice, zip('yes', 'YES'))) confirm = input(f"type '{confirmYES}' to confirm: ") # store the usernames in "@ + name" format userNames = '' if confirm == confirmYES: print('Approving the accounts...') for aAccount in approveWhat: updatedAccount = mastodon.admin_account_approve(pendingAccounts[int(aAccount)]['id']) print(f'Approved {updatedAccount["username"]}!') mastodon.account_follow(pendingAccounts[int(aAccount)]['id']) print('Followed them!') userNames += f'@{updatedAccount["username"]}\n' # YOU'LL WANT TO CHANGE THIS MESSAGE (I assume) mastodon.toot(f'Hello @{updatedAccount["username"]}\nPlease toot an introduction (using # introductions) so we can get to know you :alex_grin: add some hashtags too so we know what interests you\n\nYou can find more people on our server using the local timeline & directory\nhttps://mastodon.radio/web/directory\n\nThis list of radio amateurs on mastodon, may be of interest: https://pad.dc7ia.eu/p/radio_amateurs_on_the_fediverse\n\nI recommend the third-party apps\nhttps://joinmastodon.org/apps\nRemember to describe your images (ask for help!) + fill out your bio before following people', visibility='unlisted') print('Tooting to welcome them!') templateToot = f'Everyone, please welcome\n{userNames}\n\n#introductions' print('Tooting bulk welcome message...') mastodon.toot(templateToot) else: print('\nOk, DOING NOTHING.')
mastodon.radio isn't a big corporate server, we have rules that we enforce. Some are pretty common (don't be a dick) some are important for the community (describe your images) and I see people not describing their images. Which makes me think they haven't read the rules. So I wondered how I could check up on this.
Maybe you've heard of a warrant canary[1]? The idea being a message says that "The FBI has not been here" and is removed if they have been, even if an organisation is forbidden from saying, for example, that the FBI HAS been there.
1: https://en.wikipedia.org/wiki/Warrant_canary
Based on this idea I added "rule 7" to mastodon.radio, it reads
When apply for an account, if you've actually read these rules, please end your "Why do you want to join?" with the phrase "hippo cornflakes"
Very few requests mention cornflakes, or hippos. But that's not really the point, I'm not denying entry to people who don't. Yet. But it is interesting to see, from the administrator's view, who actually read the rules AND bothered to follow them.
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-
๐ค Black Lives Matter
๐๐ค๐ Trans Rights are Human Rights
โค๏ธ๐งก๐๐๐๐ Love is Love
Copyright ยฉ 2022 Christopher M0YNG
Code snippets are licenced under the Hippocratic License 3.0 (or later.)
Page generated 2022-07-11 by Complex 19