diff --git a/src/main.zig b/src/main.zig
index 2033d90..ae97447 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3,7 +3,6 @@ const json = std.json;
const lambda = @import("lambda_runtime");
const rinnai = @import("rinnai");
const homeassistant = @import("homeassistant.zig");
-const alexa = @import("alexa.zig");
const timezone = @import("timezone.zig");
const Config = @import("Config.zig");
const builtin = @import("builtin");
@@ -38,6 +37,7 @@ pub fn main() !u8 {
return runLocal(allocator, config, args);
const Handler = struct {
+ // SAFETY: set 7 lines down...
var c: Config = undefined;
pub fn lambda_handler(alloc: std.mem.Allocator, event_data: []const u8) anyerror![]const u8 {
@@ -259,11 +259,15 @@ fn handleWeezTheJuice(allocator: std.mem.Allocator, config: Config) ![]const u8
null, // No timezone needed for toggle
) catch |err| {
log.err("Home Assistant error: {}", .{err});
- return buildAlexaResponse(allocator, "I had trouble weezin' the juice.", true);
+ return buildAlexaResponse(allocator,
+ \\Whoooaaa buuuddy. I had some trouble weezin' the juice, bro.
+ , true);
};
defer allocator.free(result.speech);
- return buildAlexaResponse(allocator, "No weezin' the juice!", true);
+ return buildAlexaResponse(allocator,
+ \\Whoooaaa, no weezin' the juice!
+ , true);
}
/// Parsed intent parameters for Home Assistant commands
@@ -388,7 +392,7 @@ fn resolveLocalTimezone(allocator: std.mem.Allocator) ?i32 {
return timezone.getUtcOffset(allocator, tz_name);
}
-/// Build an Alexa skill response JSON
+/// Build an Alexa skill response JSON with SSML
fn buildAlexaResponse(allocator: std.mem.Allocator, speech: []const u8, end_session: bool) ![]const u8 {
// Escape speech for JSON
var escaped_speech: std.ArrayList(u8) = .{};
@@ -415,7 +419,7 @@ fn buildAlexaResponse(allocator: std.mem.Allocator, speech: []const u8, end_sess
}
return try std.fmt.allocPrint(allocator,
- \\{{"version":"1.0","response":{{"outputSpeech":{{"type":"PlainText","text":"{s}"}},"shouldEndSession":{s}}}}}
+ \\{{"version":"1.0","response":{{"outputSpeech":{{"type":"SSML","ssml":"{s}"}},"shouldEndSession":{s}}}}}
, .{ escaped_speech.items, end_session_str });
}
@@ -606,8 +610,8 @@ test "buildAlexaResponse with speech and end session" {
try std.testing.expectEqualStrings("1.0", parsed.value.object.get("version").?.string);
const resp = parsed.value.object.get("response").?.object;
try std.testing.expect(resp.get("shouldEndSession").?.bool == true);
- try std.testing.expectEqualStrings("PlainText", resp.get("outputSpeech").?.object.get("type").?.string);
- try std.testing.expectEqualStrings("Hello world", resp.get("outputSpeech").?.object.get("text").?.string);
+ try std.testing.expectEqualStrings("SSML", resp.get("outputSpeech").?.object.get("type").?.string);
+ try std.testing.expectEqualStrings("Hello world", resp.get("outputSpeech").?.object.get("ssml").?.string);
}
test "buildAlexaResponse with speech and keep session open" {
@@ -644,8 +648,8 @@ test "buildAlexaResponse escapes special characters" {
const parsed = try json.parseFromSlice(json.Value, allocator, response, .{});
defer parsed.deinit();
- const text = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("Say \"hello\"\nNew line", text);
+ const ssml = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("Say \"hello\"\nNew line", ssml);
}
test "handler returns error response for invalid JSON" {
@@ -657,8 +661,8 @@ test "handler returns error response for invalid JSON" {
const parsed = try json.parseFromSlice(json.Value, allocator, response, .{});
defer parsed.deinit();
- const text = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("I couldn't understand that request.", text);
+ const ssml = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("I couldn't understand that request.", ssml);
}
test "handler returns error for missing request field" {
@@ -670,8 +674,8 @@ test "handler returns error for missing request field" {
const parsed = try json.parseFromSlice(json.Value, allocator, response, .{});
defer parsed.deinit();
- const text = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("Invalid request format.", text);
+ const ssml = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("Invalid request format.", ssml);
}
test "handler handles LaunchRequest" {
@@ -688,8 +692,8 @@ test "handler handles LaunchRequest" {
const resp = parsed.value.object.get("response").?.object;
try std.testing.expect(resp.get("shouldEndSession").?.bool == false);
- const text = resp.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expect(std.mem.indexOf(u8, text, "hot water") != null);
+ const ssml = resp.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expect(std.mem.indexOf(u8, ssml, "hot water") != null);
}
test "handler handles SessionEndedRequest" {
@@ -723,8 +727,8 @@ test "handler handles AMAZON.HelpIntent" {
const resp = parsed.value.object.get("response").?.object;
try std.testing.expect(resp.get("shouldEndSession").?.bool == false);
- const text = resp.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expect(std.mem.indexOf(u8, text, "recirculation") != null);
+ const ssml = resp.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expect(std.mem.indexOf(u8, ssml, "recirculation") != null);
}
test "handler handles AMAZON.StopIntent" {
@@ -741,8 +745,8 @@ test "handler handles AMAZON.StopIntent" {
const resp = parsed.value.object.get("response").?.object;
try std.testing.expect(resp.get("shouldEndSession").?.bool == true);
- const text = resp.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("Okay, goodbye.", text);
+ const ssml = resp.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("Okay, goodbye.", ssml);
}
test "handler handles AMAZON.CancelIntent" {
@@ -773,8 +777,8 @@ test "handler handles unknown intent" {
const parsed = try json.parseFromSlice(json.Value, allocator, response, .{});
defer parsed.deinit();
- const text = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("I don't know how to do that.", text);
+ const ssml = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("I don't know how to do that.", ssml);
}
test "handler handles unknown request type" {
@@ -789,8 +793,8 @@ test "handler handles unknown request type" {
const parsed = try json.parseFromSlice(json.Value, allocator, response, .{});
defer parsed.deinit();
- const text = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("text").?.string;
- try std.testing.expectEqualStrings("I didn't understand that.", text);
+ const ssml = parsed.value.object.get("response").?.object.get("outputSpeech").?.object.get("ssml").?.string;
+ try std.testing.expectEqualStrings("I didn't understand that.", ssml);
}
// =============================================================================