diff --git a/django/curator/autopost/autopost.py b/django/curator/autopost/autopost.py new file mode 100644 index 000000000..6eda43827 --- /dev/null +++ b/django/curator/autopost/autopost.py @@ -0,0 +1,61 @@ +import requests +from datetime import datetime, timezone +from curator.autopost import settings +from library.models import CodebaseRelease + + +BLUESKY_HANDLE = "test266.bsky.social" +BLUESKY_APP_PASSWORD = "password" + +class Autopost: + def __init__(self): + self.identifier = settings.BLUESKY_HANDLE + self.password = settings.BLUESKY_APP_PASSWORD + self.access_token = None + self.did = None + + def authenticate(self): + #handle authentication here + response = requests.post( + "https://bsky.social/xrpc/com.atproto.server.createSession", + json={ + "identifier": self.identifier, + "password": self.password, + }, + ) + response.raise_for_status() + session = response.json() + self.access_token = session["accessJwt"] + self.did = session["did"] + + def create_post(self, text): + #create a post here and post to bluesky + if not self.access_token or not self.did: + raise ValueError("Must authenticate before creating a post.") + + + post_content = { + "$type": "app.bsky.feed.post", + "text": text, + "createdAt": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + } + + response = requests.post( + "https://bsky.social/xrpc/com.atproto.repo.createRecord", + headers={"Authorization": f"Bearer {self.access_token}"}, + json={ + "repo": self.did, + "collection": "app.bsky.feed.post", + "record": post_content, + }, + ) + response.raise_for_status() + return response.json() + + +def autopost_to_bluesky(text): + #function to autopost to Bluesky. + autopost = Autopost() + autopost.authenticate() + return autopost.create_post(text) + diff --git a/django/curator/autopost/settings.py b/django/curator/autopost/settings.py new file mode 100644 index 000000000..85215ae28 --- /dev/null +++ b/django/curator/autopost/settings.py @@ -0,0 +1,7 @@ +import environ + +env = environ.Env() +environ.Env.read_env() + +BLUESKY_HANDLE = env("BLUESKY_HANDLE", default="default_handle") +BLUESKY_APP_PASSWORD = env("BLUESKY_APP_PASSWORD", default="default_password") diff --git a/django/curator/autopost/urls.py b/django/curator/autopost/urls.py new file mode 100644 index 000000000..957160dea --- /dev/null +++ b/django/curator/autopost/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from .views import autopost_view + +urlpatterns = [ + path('autopost/', autopost_view, name='autopost'), +] diff --git a/django/curator/autopost/views.py b/django/curator/autopost/views.py new file mode 100644 index 000000000..f497e4b66 --- /dev/null +++ b/django/curator/autopost/views.py @@ -0,0 +1,10 @@ +from django.http import JsonResponse +from .autopost import autopost_to_bluesky + +def autopost_view(request): + try: + text = "This is an autopost" + response = autopost_to_bluesky(text) + return JsonResponse({"success": True, "data": response}) + except Exception as e: + return JsonResponse({"error": str(e)}, status=500) diff --git a/django/curator/management/commands/create_post.py b/django/curator/management/commands/create_post.py new file mode 100644 index 000000000..5d2b2e712 --- /dev/null +++ b/django/curator/management/commands/create_post.py @@ -0,0 +1,16 @@ +from django.core.management.base import BaseCommand +from curator.autopost.autopost import autopost_to_bluesky + +class Command(BaseCommand): + help = 'Post a message to Bluesky' + + def add_arguments(self, parser): + parser.add_argument('message', type=str, help='The message to post on Bluesky') + + def handle(self, *args, **options): + message = options['message'] + try: + response = autopost_to_bluesky(message) + self.stdout.write(self.style.SUCCESS(f"Post created successfully: {response}")) + except Exception as e: + self.stderr.write(self.style.ERROR(f"Error creating post: {e}"))