Video posting

This commit is contained in:
Guillem Hernandez Sola
2026-05-08 09:53:59 +02:00
parent 3cbb0a5853
commit 7deeec0a41

View File

@@ -322,31 +322,41 @@ def upload_image(
def upload_video_and_wait( def upload_video_and_wait(
client: Client, client: Client,
video_data: bytes, video_data: bytes,
alt_text: str = "", alt_text: str = ""
password: str = ""
) -> models.AppBskyEmbedVideo.Main | None: ) -> models.AppBskyEmbedVideo.Main | None:
try: try:
logging.info("🎬 Requesting Service Auth for Video Upload...")
# 1. Get a Service Auth token from your home PDS (eurosky.social)
# The audience (aud) MUST be the DID of the Bluesky Video Service
VIDEO_SERVICE_DID = "did:web:video.bsky.app"
auth_response = client.com.atproto.server.get_service_auth({
'aud': VIDEO_SERVICE_DID
})
service_auth_token = auth_response.token
logging.info("🎬 Uploading video to Bluesky Video Service...") logging.info("🎬 Uploading video to Bluesky Video Service...")
# Create a temporary client pointing to the official Bluesky service # 2. Create a temporary client pointing to the dedicated video service
# just for the video upload video_client = Client(base_url="https://video.bsky.app")
video_client = Client(base_url="https://bsky.social")
# We must manually set the session so it knows who we are # 3. Inject the Service Auth token into the headers
if client.me and password: # We don't call .login() on this client; we just set the authorization header manually.
# Login using the explicitly passed password video_client._session = models.ComAtprotoServerCreateSession.Response(
video_client.login(client.me.handle, password) access_jwt=service_auth_token,
else: refresh_jwt="",
logging.error("❌ Main client is not logged in or password missing.") handle=client.me.handle,
return None did=client.me.did,
active=True
)
# 1. Upload the video to the official service # 4. Upload the video to the official service
response = video_client.app.bsky.video.upload_video(video_data) response = video_client.app.bsky.video.upload_video(video_data)
job_id = response.job_id job_id = response.job_id
logging.info(f"⏳ Video uploaded! Job ID: {job_id}. Waiting for processing...") logging.info(f"⏳ Video uploaded! Job ID: {job_id}. Waiting for processing...")
# 2. Poll the job status using the video client # 5. Poll the job status using the video client
while True: while True:
status_resp = video_client.app.bsky.video.get_job_status({'job_id': job_id}) status_resp = video_client.app.bsky.video.get_job_status({'job_id': job_id})
state = status_resp.job_status.state state = status_resp.job_status.state
@@ -392,7 +402,9 @@ def post_to_bsky(
video_data = f.read() video_data = f.read()
# Pass the password to our custom polling function # Pass the password to our custom polling function
video_embed = upload_video_and_wait(client, video_data, alt_text, password) # Use our custom polling function (no password needed)
video_embed = upload_video_and_wait(client, video_data, alt_text)
if not video_embed: if not video_embed:
logging.error("❌ Aborting post: video upload/processing failed.") logging.error("❌ Aborting post: video upload/processing failed.")