semantic bufo search find-bufo.com
bufo
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: handle conflict status for already-processed videos

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

zzstoatzz 026e833e d09abf9e

+23 -14
+23 -14
bot/src/bsky.zig
··· 362 362 return err; 363 363 }; 364 364 365 - if (result.status != .ok) { 366 - const err_response = aw.toArrayList(); 367 - std.debug.print("upload video failed with status: {} - {s}\n", .{ result.status, err_response.items }); 365 + const response = aw.toArrayList(); 366 + std.debug.print("upload video response ({s}): {s}\n", .{ @tagName(result.status), response.items }); 367 + 368 + // handle both .ok and .conflict (already_exists) as success 369 + if (result.status != .ok and result.status != .conflict) { 370 + std.debug.print("upload video failed with status: {}\n", .{result.status}); 368 371 return error.VideoUploadFailed; 369 372 } 370 373 371 - const response = aw.toArrayList(); 372 - std.debug.print("upload video response: {s}\n", .{response.items}); 373 - 374 374 const parsed = json.parseFromSlice(json.Value, self.allocator, response.items, .{}) catch return error.ParseError; 375 375 defer parsed.deinit(); 376 376 377 - const job_status = parsed.value.object.get("jobStatus") orelse { 378 - std.debug.print("no jobStatus in response\n", .{}); 379 - return error.NoJobStatus; 380 - }; 381 - if (job_status != .object) return error.NoJobStatus; 377 + // for conflict responses, jobId is at root level; for ok responses, it's in jobStatus 378 + var job_id_val: ?json.Value = null; 379 + if (parsed.value.object.get("jobStatus")) |job_status| { 380 + if (job_status == .object) { 381 + job_id_val = job_status.object.get("jobId"); 382 + } 383 + } 384 + // fallback to root level jobId (conflict case) 385 + if (job_id_val == null) { 386 + job_id_val = parsed.value.object.get("jobId"); 387 + } 382 388 383 - const job_id_val = job_status.object.get("jobId") orelse return error.NoJobId; 384 - if (job_id_val != .string) return error.NoJobId; 389 + const job_id = job_id_val orelse { 390 + std.debug.print("no jobId in response\n", .{}); 391 + return error.NoJobId; 392 + }; 393 + if (job_id != .string) return error.NoJobId; 385 394 386 - return try self.allocator.dupe(u8, job_id_val.string); 395 + return try self.allocator.dupe(u8, job_id.string); 387 396 } 388 397 389 398 pub fn waitForVideo(self: *BskyClient, job_id: []const u8) ![]const u8 {