Posting¶
longwei supports posting text statuses, media attachments, polls, scheduled statuses, and sensitive content with content warnings.
import httpx
from longwei import APClient, Visibility
async with httpx.AsyncClient() as client:
ap = await APClient.create(
instance="mastodon.social",
client=client,
access_token="your_token",
)
Text status¶
Visibility.PUBLIC is the default. To change it:
See Enums — Visibility for all visibility options.
Content warning / spoiler text¶
status = await ap.post_status(
"Detailed discussion of the plot twist...",
spoiler_text="Spoilers for Season 3",
)
The spoiler_text is shown as a content warning; the status body is hidden behind a
"Show more" button on most clients.
Sensitive content¶
Mark a status as sensitive (typically used for explicit media or political content):
Media attachments¶
1. Upload the file¶
with open("photo.jpg", "rb") as f:
result = await ap.post_media(
file=f,
mime_type="image/jpeg",
description="A cat sitting on a keyboard", # alt text for accessibility
)
media_id = result.id
2. Attach to a status¶
Multiple attachments¶
ids = []
for filename, mime_type in [("cat.jpg", "image/jpeg"), ("dog.png", "image/png")]:
with open(filename, "rb") as f:
result = await ap.post_media(file=f, mime_type=mime_type)
ids.append(result.id)
status = await ap.post_status("Cats vs dogs", media_ids=ids)
The maximum number of attachments is server-specific. After APClient.create(), check
ap.max_attachments for the current instance's limit.
Focal point¶
Specify a focal point for cropping previews. Coordinates range from -1.0 to 1.0,
with (0.0, 0.0) being the centre:
with open("portrait.jpg", "rb") as f:
result = await ap.post_media(
file=f,
mime_type="image/jpeg",
description="Portrait photo",
focus=(0.0, 0.5), # centre-top
)
Polls¶
Attach a poll by passing poll_options (at least 2 choices) and poll_expires_in
(duration in seconds). Polls are mutually exclusive with media_ids.
status = await ap.post_status(
"What is your favourite Python web framework?",
poll_options=["Django", "FastAPI", "Flask", "Other"],
poll_expires_in=86400, # 24 hours
)
Allow voters to pick more than one option with poll_multiple:
status = await ap.post_status(
"Which languages do you use regularly?",
poll_options=["Python", "Rust", "Go", "TypeScript"],
poll_expires_in=172800, # 48 hours
poll_multiple=True,
)
Hide the running totals until the poll closes with poll_hide_totals:
status = await ap.post_status(
"Tabs or spaces?",
poll_options=["Tabs", "Spaces"],
poll_expires_in=3600, # 1 hour
poll_hide_totals=True,
)
Scheduled statuses¶
Pass a datetime at least 5 minutes in the future. Naive datetimes are treated as UTC:
from datetime import datetime, timezone
# Using a timezone-aware datetime
scheduled = datetime(2025, 12, 25, 9, 0, 0, tzinfo=timezone.utc)
status = await ap.post_status(
"Happy holidays!",
scheduled_at=scheduled,
)
# Naive datetime — longwei will treat it as UTC
scheduled_naive = datetime(2025, 12, 25, 9, 0, 0)
status = await ap.post_status("Happy holidays!", scheduled_at=scheduled_naive)
Complete example¶
import httpx
from datetime import datetime, timezone
from longwei import APClient, Visibility
async def post_with_image(instance: str, token: str, image_path: str) -> None:
async with httpx.AsyncClient() as client:
ap = await APClient.create(
instance=instance,
client=client,
access_token=token,
)
# Upload media
with open(image_path, "rb") as f:
media = await ap.post_media(
file=f,
mime_type="image/jpeg",
description="An image",
)
# Post with attachment and content warning
status = await ap.post_status(
"Check out this photo!",
visibility=Visibility.PUBLIC,
media_ids=[media.id],
sensitive=False,
spoiler_text=None,
)
print(f"Posted: {status.url}")
print(f"Status ID: {status.id}")