Skip to content

Instantly share code, notes, and snippets.

@extratone
Last active October 17, 2025 15:40
Show Gist options
  • Select an option

  • Save extratone/b06a894f0fdeb3052102bc9b849ec7c6 to your computer and use it in GitHub Desktop.

Select an option

Save extratone/b06a894f0fdeb3052102bc9b849ec7c6 to your computer and use it in GitHub Desktop.
A script querying the mastodon API for all status urls found for a given Mastodon-formatted search query.
import requests
import sys
import argparse
import time
from datetime import datetime
from dateutil import parser as date_parser
from dateutil import tz
from markdownify import markdownify as md
# --- Configuration ---
INSTANCE = "mastodon.social"
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"
# Set your local timezone to correctly format the timestamp.
# For Columbia, Missouri, 'America/Chicago' is the correct IANA time zone name.
LOCAL_TIMEZONE = "America/Chicago"
# --- End Configuration ---
def format_status_as_embed(status: dict) -> str:
"""
Formats a single status object into the specified ad-Mastodon embed string.
"""
# --- 1. Parse and Format Timestamp ---
utc_time = date_parser.isoparse(status['created_at'])
local_tz = tz.gettz(LOCAL_TIMEZONE)
local_time = utc_time.astimezone(local_tz)
# Format to MMddYYYY-HHmmss ("davodtime")
davodtime_str = local_time.strftime("%m%d%Y-%H%M%S")
# --- 2. Convert Content from HTML to Markdown ---
# The 'content' from the API is HTML
content_md = md(status.get('content', '')).strip()
# --- 3. Get Status URL ---
status_url = status.get('url', '')
# --- 4. Build the Embed Block ---
embed_lines = [
"\`\`\`ad-Mastodon",
"title: Mastodon",
f"{content_md}",
]
# --- 5. Conditionally Add Attachments ---
attachments = status.get('media_attachments', [])
if attachments:
embed_lines.append("") # Add a blank line before attachments
for attachment in attachments:
attachment_url = attachment.get('url')
if attachment_url:
# Format as a Markdown image/embed link
embed_lines.append(f"![]({attachment_url})")
# --- 6. Add the Timestamp Link ---
embed_lines.append("") # Add a blank line before the footer
embed_lines.append(f"[{davodtime_str}]({status_url})")
embed_lines.append("\`\`\`")
return "\n".join(embed_lines)
def run_search(query: str):
"""
Executes a paginated search and prints a formatted embed for each result.
"""
if ACCESS_TOKEN == "YOUR_ACCESS_TOKEN":
print("Error: Please update the ACCESS_TOKEN in the script.", file=sys.stderr)
sys.exit(1)
headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'}
api_endpoint = f"https://{INSTANCE}/api/v2/search"
params = {'q': query, 'type': 'statuses', 'limit': 40, 'resolve': 'true'}
total_found = 0
page_count = 0
while True:
page_count += 1
print(f"Fetching page {page_count}...", file=sys.stderr)
try:
response = requests.get(api_endpoint, headers=headers, params=params)
response.raise_for_status()
statuses = response.json().get('statuses', [])
if not statuses:
print("No more results found.", file=sys.stderr)
break
# Process each status and print the formatted embed
for status in statuses:
embed_output = format_status_as_embed(status)
print(embed_output)
print() # Add a line break between each embed block
total_found += 1
# Update params for the next page request
params['max_id'] = statuses[-1]['id']
time.sleep(1)
except requests.exceptions.RequestException as e:
print(f"\nAn error occurred: {e}", file=sys.stderr)
break
print("---", file=sys.stderr)
print(f"Search complete. Generated embeds for {total_found} statuses.", file=sys.stderr)
def main():
parser = argparse.ArgumentParser(
description="Search Mastodon and generate formatted embeds for each status.",
epilog='Example: python3 generate_mastodon_embeds.py \'"Obsidian" from:DavidBlue\''
)
parser.add_argument("query", type=str, help="The search query string.")
args = parser.parse_args()
run_search(args.query)
if __name__ == "__main__":
main()
import requests
import sys
import argparse
# --- Configuration ---
# Your Mastodon instance. The script will be most effective on the instance
# where the user account in the query (if any) resides.
INSTANCE = "mastodon.social"
# Your access token from your instance's Preferences -> Development page.
# A token is required for the search endpoint.
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"
# --- End Configuration ---
def run_search(query: str):
"""
Executes the search against the Mastodon API and prints status URLs.
Args:
query: The search string, e.g., '"Obsidian" from:DavidBlue'.
"""
if ACCESS_TOKEN == "YOUR_ACCESS_TOKEN":
print("Error: Please replace 'YOUR_ACCESS_TOKEN' with your actual access token in the script.", file=sys.stderr)
sys.exit(1)
headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'}
# We use the v2 search endpoint, which is powerful and supports pagination.
# The initial request includes the search parameters.
api_endpoint = f"https://{INSTANCE}/api/v2/search"
params = {
'q': query,
'type': 'statuses', # We are only interested in statuses
'limit': 40, # Request the maximum number of results per page
'resolve': 'true' # Attempt to resolve non-local accounts and posts
}
found_urls = []
page_count = 0
while api_endpoint:
page_count += 1
print(f"Fetching page {page_count}...", file=sys.stderr)
try:
# The 'params' are only sent with the first request.
# Subsequent requests will use the full URL from the 'Link' header.
response = requests.get(api_endpoint, headers=headers, params=params)
response.raise_for_status() # Check for HTTP errors like 401 Unauthorized or 404 Not Found
# After the first request, we no longer need the params dictionary
if params:
params = None
data = response.json()
statuses = data.get('statuses', [])
if not statuses:
# No more statuses on this page, we are done.
break
for status in statuses:
status_url = status.get('url')
if status_url:
print(status_url) # Print the final URL directly to standard output
found_urls.append(status_url)
# The 'requests' library parses the 'Link' header for pagination.
# We look for the 'next' link to get the URL for the next page of results.
if 'next' in response.links:
api_endpoint = response.links['next']['url']
else:
# No 'next' link means we have reached the last page.
api_endpoint = None
except requests.exceptions.RequestException as e:
print(f"Error during API request: {e}", file=sys.stderr)
break
print("---", file=sys.stderr)
print(f"Search complete. Found {len(found_urls)} matching statuses.", file=sys.stderr)
def main():
"""
Parses command-line arguments and initiates the search.
"""
parser = argparse.ArgumentParser(
description="Search the Mastodon API for statuses and output their URLs.",
epilog='Example: python3 mastodon_search.py \'"Obsidian" from:DavidBlue\''
)
parser.add_argument(
"query",
type=str,
help="The search query string, enclosed in quotes if it contains spaces or special characters."
)
args = parser.parse_args()
run_search(args.query)
if __name__ == "__main__":
main()
@castleappsmom-maker
Copy link

The Pak games Apk is Pakistan’s top mobile earning app, offering real-cash rewards through JazzCash, Easypaisa, and bank transfers. Play Aviator, Color Prediction, Rummy, and more all in one lightweight Android APK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment