101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
import logging
|
|
|
|
import requests
|
|
|
|
from imagebot import settings
|
|
from idescriptor.models import Image
|
|
|
|
|
|
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_image(self, status, image_path, alt_text):
|
|
"""
|
|
Uploads an image, then posts a status with that image and alt text.
|
|
:param status: The text of the status.
|
|
:param image_path: The path to the image file.
|
|
:param alt_text: The alt text for the image.
|
|
:return: The response from the Mastodon API.
|
|
"""
|
|
# Upload the image and get the media ID
|
|
media_id = self.upload_media(image_path, alt_text)
|
|
|
|
# Post the status with the uploaded image's media ID
|
|
return self.post_status(status, media_ids=[media_id])
|
|
|
|
|
|
def post():
|
|
ACCESS_TOKEN = settings.FEDIVERSE_TOKEN
|
|
API_BASE_URL = f"https://{settings.FEDIVERSE_SERVER}"
|
|
client = FediClient(ACCESS_TOKEN, API_BASE_URL)
|
|
|
|
image = Image.get_image_to_post()
|
|
|
|
status_text = image.title
|
|
image_path = f"{settings.MEDIA_ROOT}/{image.image}"
|
|
alt_text = image.alt_text
|
|
|
|
try:
|
|
response = client.post_status_with_image(status_text, image_path, alt_text)
|
|
logging.info(response)
|
|
image.set_image_posted()
|
|
except requests.exceptions.ConnectionError as e:
|
|
logging.error(f"Could not post image: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
post()
|