Fix segfault: keep JSON body alive for parsed string refs
- Root cause: parseFromSlice returns slices pointing into the raw JSON body, but body was freed immediately after parsing in getUpdates - Fix: return OwnedParsed wrapper that keeps both parsed result and raw body alive together - Switch HTTP layer to curl subprocess (more reliable than std.http with static linking) - Fix downloadToFile: use spawnAndWait instead of collectOutput (collectOutput requires both pipes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
15
src/main.zig
15
src/main.zig
@@ -24,14 +24,14 @@ pub fn main() !void {
|
||||
var offset: i64 = 0;
|
||||
|
||||
while (true) {
|
||||
const updates = bot.getUpdates(offset, 30) catch |err| {
|
||||
var updates = bot.getUpdates(offset, 30) catch |err| {
|
||||
log.err("getUpdates failed: {s}", .{@errorName(err)});
|
||||
std.Thread.sleep(5 * std.time.ns_per_s);
|
||||
continue;
|
||||
};
|
||||
defer updates.deinit();
|
||||
|
||||
for (updates.value.result) |update| {
|
||||
for (updates.parsed.value.result) |update| {
|
||||
offset = update.update_id + 1;
|
||||
processUpdate(allocator, &bot, update, whisper_url, language);
|
||||
}
|
||||
@@ -80,15 +80,19 @@ fn handleTranscription(
|
||||
language: []const u8,
|
||||
) !void {
|
||||
// Get file path from Telegram
|
||||
log.info("Step 1: getFilePath", .{});
|
||||
const file_path = try bot.getFilePath(file_id);
|
||||
defer allocator.free(file_path);
|
||||
log.info("Step 1 done: {s}", .{file_path});
|
||||
|
||||
// Download file
|
||||
const ext: []const u8 = if (is_video) ".mp4" else ".ogg";
|
||||
const tmp_input = try std.fmt.allocPrint(allocator, "/tmp/tg_{d}{s}", .{ message.message_id, ext });
|
||||
defer allocator.free(tmp_input);
|
||||
|
||||
log.info("Step 2: downloadFile to {s}", .{tmp_input});
|
||||
try bot.downloadFile(file_path, tmp_input);
|
||||
log.info("Step 2 done", .{});
|
||||
defer std.fs.deleteFileAbsolute(tmp_input) catch {};
|
||||
|
||||
// Convert video to audio if needed
|
||||
@@ -100,6 +104,7 @@ fn handleTranscription(
|
||||
};
|
||||
|
||||
if (is_video) {
|
||||
log.info("Step 2.5: ffmpeg conversion", .{});
|
||||
const out_path = try std.fmt.allocPrint(allocator, "/tmp/tg_{d}.ogg", .{message.message_id});
|
||||
tmp_audio = out_path;
|
||||
|
||||
@@ -117,15 +122,21 @@ fn handleTranscription(
|
||||
}
|
||||
|
||||
audio_path = out_path;
|
||||
log.info("Step 2.5 done", .{});
|
||||
}
|
||||
|
||||
// Transcribe
|
||||
log.info("Step 3: transcribe {s}", .{audio_path});
|
||||
const text = try whisper.transcribe(allocator, whisper_url, audio_path, language);
|
||||
defer allocator.free(text);
|
||||
log.info("Step 3 done, text length: {d}", .{text.len});
|
||||
|
||||
// Send response
|
||||
log.info("Step 4: sendMessage", .{});
|
||||
if (text.len == 0) {
|
||||
try bot.sendMessage(message.chat.id, "(empty transcription)", message.message_id);
|
||||
} else {
|
||||
try bot.sendMessage(message.chat.id, text, message.message_id);
|
||||
}
|
||||
log.info("Step 4 done", .{});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user