cstromblad / infosec_mastodon

An automatically updated repository containing a CSV of Mastodon Importable Infosec people.
Apache License 2.0
3 stars 0 forks source link

I want this stuff added to a list #1

Open isotopp opened 6 months ago

isotopp commented 6 months ago

I do not want to follow these people globally, so I create a list "Infosec" in the list panel.

I then go into the Developer panel and create an application autosubber, read, write:follows, write:lists, follow (probably to large a scope)

I put these things into a .env file in the project directory.

$ cat .env

$ cat .env
CLIENT_KEY=redacted
CLIENT_SECRET=redacted
ACCESS_TOKEN=redacted

The project directory also has a requirements.txt and a main.py.

$ cat requirements.txt

Mastodon.py
python-dotenv

$ python3.12 -mvenv venv $ source venv/bin/activate (venv) $ pip install -U pip wheel (venv) $ pip install -r requirements.txt $ cat main.py

import csv
import os
from mastodon import Mastodon, MastodonError
from dotenv import load_dotenv
import time

MYINSTANCE="https://chaos.social"

# do the actual work
def process_file(filename, mastodon, listen_id, retry_filename):
    with open(filename, mode='r', newline='', encoding='utf-8') as file, \
         open(retry_filename, mode='a', newline='', encoding='utf-8') as retry_file:
        reader = csv.DictReader(file)
        writer = csv.DictWriter(retry_file, fieldnames=reader.fieldnames)

        for row in reader:
            try:
                print(f"Working on: {row['Account address']}")
                account = mastodon.account_search(row['Account address'], limit=1)
                if account:
                    try:
                        print("Following...")
                        mastodon.account_follow(account[0]['id'])
                    except MastodonError as e:
                        print(f"Error while following {row['Account address']}: {e}")
                        writer.writerow(row)
                        continue

                    try:
                        print("Add to List...")
                        mastodon.list_accounts_add(listen_id, account[0]['id'])
                    except MastodonError as e:i
                        if e.args[0] == ('Mastodon API returned error', 422, 'Unprocessable Content', 'Validation failed: Account has already been taken'):
                            print(f"Account {row['Account address']} is already in list.")
                        else:
                            print(f"error while adding to list: {row['Account address']}: {e}")
                            writer.writerow(row)

            except Exception as e:
                print(f"error working on {row['Account address']}: {e}")
                writer.writerow(row)
            print()
            time.sleep(1)

# load the env
load_dotenv()

# dotenv then serves fake getenv() data to os.getenv()
client_key = os.getenv('CLIENT_KEY')
client_secret = os.getenv('CLIENT_SECRET')
access_token = os.getenv('ACCESS_TOKEN')

# get a client
mastodon = Mastodon(
    client_id=client_key,
    client_secret=client_secret,
    access_token=access_token,
    api_base_url=MYINSTANCE
)

# check we have a list
listen_name = "Infosec"
listen_id = None
listen = mastodon.lists()

for liste in listen:
    if liste['title'] == listen_name:
        listen_id = liste['id']
        break

if listen_id is None:
    listen_id = mastodon.list_create(listen_name)['id']

# load stuff, and if stuff fails, write stuff out to retry.txt
retry_filename = 'retry.txt'
process_file('infosec.txt', mastodon, listen_id, retry_filename)
cstromblad commented 6 months ago

Hey @isotopp! Appreciate the contribution, but I was wondering if you would particularly mind if I add this as a separate program?

I also prefer to add people into specific lists, therefore your contribution appeals to me, but I also see them as serving two similar but somewhat separate purposes!

isotopp commented 6 months ago

I put a cleaner version of this into https://github.com/isotopp/subscribodil. You can do with it whatever you want, I made it available under the unlicense.

This now has proper timeouts, and takes the file and list names as parameters.