Posting Status
Currently minimal_activitypub only implements standard status posting (polls and direct messages / DMs are not currently implemented).
Posting Text Only Status
The sample code below shows a very simple text only status being posted.
from minimal_activitypub.client_2_server import ActivityPub
from minimal_activitypub import Status
async def post_status(instance_api: ActivityPub, status: str) -> Status:
posted_status = await instance_api.post_status(status=status)
return posted_status
Posting Status That Includes Media
The sample code below shows how to post a status with images attached. Basically the images/media needs to be posted first and the media id(s) need to be included when posting the status itself.
import aiofiles
import magic
from minimal_activitypub.client_2_server import ActivityPub
from minimal_activitypub import Status
from typing import Dict, Any
async def post_status_with_image(instance_api: ActivityPub, status: str, image_path: str) -> Dict[str, Any]:
# First determine mime-type
mime_type = magic.from_file(image_path, mime=True)
# Post media
async with aiofiles.open(image_path, "rb") as image_file:
posted_media = await instance_api.post_media(file=image_file, mime_type=mime_type)
# Determine media id to include when posting status
media_id = posted_media["id"]
# Post actual status and include image
posted_status = await instance_api.post_status(status=status, media_ids=[media_id])
return posted_status
Advanced Posting Options
Posting with Multiple Media Files
from minimal_activitypub.client_2_server import ActivityPub
from minimal_activitypub import Visibility
async def post_with_multiple_images(instance_api: ActivityPub, status: str, image_paths: list[str]) -> dict:
media_ids = []
for image_path in image_paths:
mime_type = magic.from_file(image_path, mime=True)
async with aiofiles.open(image_path, "rb") as image_file:
posted_media = await instance_api.post_media(file=image_file, mime_type=mime_type)
media_ids.append(posted_media["id"])
# Post status with all media
posted_status = await instance_api.post_status(
status=status,
media_ids=media_ids,
visibility=Visibility.PUBLIC
)
return posted_status
Posting Sensitive Content with Spoiler Text
from minimal_activitypub.client_2_server import ActivityPub
async def post_sensitive_content(instance_api: ActivityPub, status: str, spoiler_text: str, image_path: str) -> dict:
mime_type = magic.from_file(image_path, mime=True)
async with aiofiles.open(image_path, "rb") as image_file:
posted_media = await instance_api.post_media(
file=image_file,
mime_type=mime_type,
description="Image description for accessibility"
)
posted_status = await instance_api.post_status(
status=status,
media_ids=[posted_media["id"]],
sensitive=True,
spoiler_text=spoiler_text
)
return posted_status
Scheduling a Post
from datetime import datetime, timedelta
from pytz import UTC
from minimal_activitypub.client_2_server import ActivityPub
async def schedule_post(instance_api: ActivityPub, status: str, hours_from_now: int = 24) -> dict:
# Schedule post for 24 hours from now
scheduled_time = datetime.now(UTC) + timedelta(hours=hours_from_now)
posted_status = await instance_api.post_status(
status=status,
scheduled_at=scheduled_time
)
return posted_status
Method Signatures
ActivityPub.post_status(status: str, visibility: Visibility = Visibility.PUBLIC, media_ids: list[str] | None = None, sensitive: bool = False, spoiler_text: str | None = None, scheduled_at: datetime | None = None) -> dict
Posts a status to the fediverse with various options.
Parameters:
- status: The text content of the status
- visibility: One of public, unlisted, private, or direct (default: public)
- media_ids: List of media IDs to attach to the status
- sensitive: Whether the content should be marked as sensitive (default: False)
- spoiler_text: Content warning text that hides the status behind a warning
- scheduled_at: Datetime to schedule the post for future publication
Returns: A dictionary containing the posted status information.
ActivityPub.post_media(file: IO[bytes], mime_type: str, description: str | None = None, focus: tuple[float, float] | None = None) -> dict
Uploads a media file (image or video) to the instance.
Parameters:
- file: The file object to upload (must be opened in binary mode)
- mime_type: MIME type of the file (e.g., image/jpeg, image/png, video/mp4)
- description: Alt text for accessibility
- focus: Focal point coordinates as (x, y) tuple, each between -1.0 and 1.0
Returns: A dictionary containing the uploaded media information including the id needed for posting.
Complete Example
Here's a complete example that demonstrates the full posting workflow:
import asyncio
import aiofiles
import magic
from httpx import AsyncClient
from minimal_activitypub.client_2_server import ActivityPub
from minimal_activitypub import Visibility
async def main():
instance_url = "https://mastodon.social"
access_token = "your_access_token_here"
async with AsyncClient() as client:
# Create ActivityPub instance
ap = ActivityPub(
instance=instance_url,
client=client,
access_token=access_token
)
# Post a simple text status
simple_status = await ap.post_status(
status="Hello from minimal-activitypub! 🐘"
)
print(f"Posted simple status: {simple_status.get('url')}")
# Post a status with an image
image_path = "example.jpg"
mime_type = magic.from_file(image_path, mime=True)
async with aiofiles.open(image_path, "rb") as image_file:
media = await ap.post_media(
file=image_file,
mime_type=mime_type,
description="A beautiful sunset over the mountains"
)
status_with_image = await ap.post_status(
status="Check out this beautiful sunset! 🌅",
media_ids=[media["id"]],
visibility=Visibility.UNLISTED
)
print(f"Posted status with image: {status_with_image.get('url')}")
if __name__ == "__main__":
asyncio.run(main())
Notes
- Media files must be uploaded before posting a status that includes them.
- The maximum number of media attachments varies by instance (typically 4 for Mastodon).
- File size limits also vary by instance configuration.
- Scheduled posts must be at least 5 minutes in the future.
- Always include alt text (description) for images to improve accessibility.