feat: Add "Post to Fediverse"
This commit is contained in:
95
src/fellchensammlung/tools/fedi.py
Normal file
95
src/fellchensammlung/tools/fedi.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from fellchensammlung.models import SocialMediaPost, PlatformChoices
|
||||
from notfellchen import settings
|
||||
|
||||
|
||||
class FediClient:
|
||||
def __init__(self, access_token, api_base_url):
|
||||
"""
|
||||
:param access_token: Your server API access token.
|
||||
:param api_base_url: The base URL of the Fediverse instance (e.g., 'https://gay-pirate-assassins.de').
|
||||
"""
|
||||
self.access_token = access_token
|
||||
self.api_base_url = api_base_url.rstrip('/')
|
||||
self.headers = {
|
||||
'Authorization': f'Bearer {self.access_token}',
|
||||
}
|
||||
|
||||
def upload_media(self, image_path, alt_text):
|
||||
"""
|
||||
Uploads media (image) to the server and returns the media ID.
|
||||
:param image_path: Path to the image file to upload.
|
||||
:param alt_text: Description (alt text) for the image.
|
||||
:return: The media ID of the uploaded image.
|
||||
"""
|
||||
|
||||
media_endpoint = f'{self.api_base_url}/api/v2/media'
|
||||
|
||||
with open(image_path, 'rb') as image_file:
|
||||
files = {
|
||||
'file': image_file,
|
||||
'description': (None, alt_text)
|
||||
}
|
||||
response = requests.post(media_endpoint, headers=self.headers, files=files)
|
||||
|
||||
# Raise exception if upload fails
|
||||
response.raise_for_status()
|
||||
|
||||
# Parse and return the media ID from the response
|
||||
media_id = response.json().get('id')
|
||||
return media_id
|
||||
|
||||
def post_status(self, status, media_ids=None):
|
||||
"""
|
||||
Posts a status to Mastodon with optional media.
|
||||
:param status: The text of the status to post.
|
||||
:param media_ids: A list of media IDs to attach to the status (optional).
|
||||
:return: The response from the Mastodon API.
|
||||
"""
|
||||
status_endpoint = f'{self.api_base_url}/api/v1/statuses'
|
||||
|
||||
payload = {
|
||||
'status': status,
|
||||
'media_ids[]': media_ids if media_ids else []
|
||||
}
|
||||
response = requests.post(status_endpoint, headers=self.headers, data=payload)
|
||||
|
||||
# Raise exception if posting fails
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
||||
def post_status_with_images(self, status, images):
|
||||
"""
|
||||
Uploads one or more image, then posts a status with that images and alt text.
|
||||
:param status: The text of the status.
|
||||
:param image_paths: The paths to the image file.
|
||||
:param alt_text: The alt text for the image.
|
||||
:return: The response from the Mastodon API.
|
||||
"""
|
||||
media_ids = []
|
||||
for image in images:
|
||||
# Upload the image and get the media ID
|
||||
media_ids = self.upload_media(f"{settings.MEDIA_ROOT}/{image.image}", image.alt_text)
|
||||
|
||||
# Post the status with the uploaded image's media ID
|
||||
return self.post_status(status, media_ids=media_ids)
|
||||
|
||||
|
||||
def post_an_to_fedi(adoption_notice):
|
||||
client = FediClient(settings.fediverse_access_token, settings.fediverse_api_base_url)
|
||||
|
||||
status_text = adoption_notice.name
|
||||
images = adoption_notice.get_photos()
|
||||
|
||||
if images is not None:
|
||||
response = client.post_status_with_images(status_text, images)
|
||||
else:
|
||||
response = client.post_status(status_text)
|
||||
logging.info(response)
|
||||
post = SocialMediaPost.objects.create(adoption_notice=adoption_notice,
|
||||
platform=PlatformChoices.FEDIVERSE,
|
||||
url=response['url'], )
|
||||
return post
|
Reference in New Issue
Block a user