Following the Elephant's Toots With the Python
At the time of the writing I am at the PyconIt 20231, in Florence, and I have a problem.
All the other Pycon I went, I saved all the user how tweet the official hashtag for the event. This year I won’t do it because of the pricing of the Twitter Api, so I was unhappy about of it.
So I decide to implement something similar for Mastodon.
The theory of the toot
I need to break the task in little steeps for easyer development:
- I need to get all the Toots with the hashtag: pycoit2023
- I need to collet the users of the toots
- Follow all the users (you need to follow someone to add to a list)
- Add all the users in the list PyconIt2023
So I wrote this code for a commandline
from typing import Annotated
import typer
import requests
from rich.console import Console
from rich.table import Table
import logging
logger = logging.getLogger(__name__)
app = typer.Typer()
class MastodonSocial:
def __init__(self, token: str, domain: str) -> None:
self.token = token
self.domain = domain
def follow(self, account_id: str) -> None:
url = f"https://{self.domain}/api/v1/accounts/{account_id}/follow"
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.post(url, headers=headers)
if response.status_code == 200:
logger.info("Success")
def get_users_from_hashtags(self, hashtag: str) -> None:
url = f"https://{self.domain}/api/v1/timelines/tag/{hashtag}"
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return list({user["account"]["id"] for user in response.json()})
else:
raise Exception("Error")
def get_list(self) -> list[dict]:
url = f"https://{self.domain}/api/v1/lists"
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
else:
raise Exception("Error")
def run_hashtag_follow(self, hashtag: str) -> None:
users = self.get_users_from_hashtags(hashtag)
for user in users:
self.follow(user)
def add_user_to_list(self, list_id: str, list_users_id: list[str]) -> None:
url = f"https://{self.domain}/api/v1/lists/{list_id}/accounts"
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(url, headers=headers)
present = {user["id"] for user in response.json()}
list_users_id = list(set(list_users_id) - present)
url = f"https://{self.domain}/api/v1/lists/{list_id}/accounts"
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.post(
url, headers=headers, json={"account_ids": list_users_id}
)
if response.status_code == 200:
logger.info("Success")
else:
logger.error(response.json())
raise Exception("Error")
def run_hashtag_follow_list(self, hashtag: str, list_id: str) -> None:
users = self.get_users_from_hashtags(hashtag)
self.add_user_to_list(list_id, users)
@app.command()
def get_lists(
token: Annotated[str, typer.Argument(help="Token for Mastodon")],
domain: Annotated[
str, typer.Argument(help="Mastodon Server")
] = "mastodon.social",
):
ms = MastodonSocial(token=token, domain=domain)
console = Console()
table = Table()
table.add_column("Id")
table.add_column("Title")
for e in ms.get_list():
table.add_row(e["id"], e["title"])
console.print(table)
@app.command()
def add_list_from_hashtag(
token: Annotated[str, typer.Argument(help="Token for Mastodon")],
hashtag: Annotated[
str, typer.Argument(help="The hash tag to find the followers")
],
list_id: Annotated[
str, typer.Argument(help="The id of the list to add the followers")
],
domain: Annotated[
str, typer.Argument(help="Mastodon Server")
] = "mastodon.social",
):
ms = MastodonSocial(token=token, domain=domain)
users = ms.get_users_from_hashtags(hashtag)
ms.add_user_to_list(list_id, users)
@app.command()
def follow_from_hashtag(
token: Annotated[str, typer.Argument(help="Token for Mastodon")],
hashtag: Annotated[
str, typer.Argument(help="The hash tag to find the followers")
],
domain: Annotated[
str, typer.Argument(help="Mastodon Server")
] = "mastodon.social",
):
ms = MastodonSocial(token=token, domain=domain)
ms.run_hashtag_follow(hashtag=hashtag)
if __name__ == "__main__":
app()
With this simple script2 now I can populate my Mastodon’s List with all the user Tooting about pyconit
Comments
To reply to this post, you can send a Webmention or you can toot me at [email protected]
You mentioned this post on your site? Send a Webmention