Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Version 2 Features Implementation #4

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

[DRAFT] Version 2 Features Implementation #4

wants to merge 6 commits into from

Conversation

ijaz26
Copy link
Collaborator

@ijaz26 ijaz26 commented Dec 12, 2024

Summary by CodeRabbit

  • New Features

    • Introduced new intents: AMAZON.ResumeIntent, AMAZON.PauseIntent, FavoriteAdhaanReciterIntent, and HadithIntent.
    • Added support for adhaan recitation with new prompts and touch handlers.
    • Enhanced interaction model with updated synonyms and sample phrases for existing intents.
    • Added German language support with localized prompts.
  • Bug Fixes

    • Corrected formatting issues in sample phrases across various intents.
  • Chores

    • Removed outdated interaction model files for certain languages.

Copy link

coderabbitai bot commented Dec 12, 2024

Walkthrough

The changes involve updates to several interaction model files for different languages, focusing on adding new intents related to adhaan recitation, modifying existing intents, and refining sample phrases. New intents such as FavoriteAdhaanReciterIntent, AMAZON.ResumeIntent, and AMAZON.PauseIntent have been introduced. Additionally, several existing intents have had their sample phrases updated for clarity, and some language files have been deleted to streamline the interaction models. The changes enhance the overall user experience by improving intent definitions and localization.

Changes

File Change Summary
interactionModels/de-DE.json Added intents: AMAZON.ResumeIntent, AMAZON.PauseIntent, HadithIntent. Modified NextPrayerTimeIntent (removed sample). Updated synonyms for prayerName.
interactionModels/en-AU.json File deleted.
interactionModels/en-CA.json File deleted.
interactionModels/en-GB.json File deleted.
interactionModels/en-IN.json File deleted.
interactionModels/en-US.json Added intent: FavoriteAdhaanReciterIntent with slot favouriteReciter. Updated samples for NextPrayerTimeIntent, AMAZON.FallbackIntent, and AllPrayerTimeIntent. Added intents: AMAZON.PauseIntent, AMAZON.ResumeIntent. Updated synonym for prayerName.
interactionModels/fr-CA.json File deleted.
interactionModels/fr-FR.json Added intent: FavoriteAdhaanReciterIntent with slot favouriteReciter. Updated samples for various intents. Added prompts for adhaan recitation.
lambda/aplDocuments/mosqueListApl.json Modified primaryAction to include a new argument in the SendEvent action.
lambda/datasources.js Added constant adhaanRecitation, updated getDataSourceforMosqueList, and added new functions: getDataSourceForAdhaanReciter, getMetadata.
lambda/handlers/audioPlayerHandler.js Added handlers: AudioPlayerEventHandler, PlaybackCommandHandler, AudioIntentHandler.
lambda/handlers/intentHandler.js Added handlers: FavoriteAdhaanReciterStartedHandler, FavoriteAdhaanReciterIntentHandler, HadithIntentHandler. Modified PlayAdhanIntentHandler for dynamic URL retrieval.
lambda/handlers/touchHandler.js Added AdhaanRecitationTouchEventHandler, modified MosqueListTouchEventHandler.
lambda/helperFunctions.js Added functions: callDirectiveService, splitLanguage. Modified checkForPersistenceData.
lambda/index.js Integrated new intent and touch event handlers into the request handler chain.
lambda/interceptors.js Enhanced error handling and control flow in various interceptors. Added utility function isValidRequestType.
lambda/languageStrings.js Added support for German (de-DE) language prompts.
lambda/prompts/de_DE.js Introduced German translations for various prompts related to the skill.
lambda/prompts/en_US.js Added prompts related to adhan recitation.
lambda/prompts/fr_FR.js Added prompts related to adhan recitation.
lambda/handlers/apiHandler.js Added function getRandomHadith to retrieve a random hadith based on language.
lambda/aplDocuments/characterDisplayApl.json New APL document added to define a character display template.

Poem

In the meadow, soft and bright,
New intents take joyful flight.
With adhaan calls and prayers near,
We celebrate with hops and cheer!
A skill refined, our voices blend,
In every heart, the blessings send. 🐇✨

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. This feature will be included in our Pro Plan when released.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🧹 Outside diff range and nitpick comments (12)
lambda/interceptors.js (4)

91-97: Unnecessary use of 'async' in 'LocalizationInterceptor'

The process method is declared as async but does not contain any await statements. Consider removing the async keyword if asynchronous operations are not utilized within the method.


94-96: Clarify conditional logic in 'LocalizationInterceptor'

The condition if(isValidRequestType(requestType)) checks for request types where localization should be skipped. Consider renaming the function isValidRequestType to shouldSkipLocalization or inverting the condition to improve code readability.


134-140: Update comment to reflect interceptor's purpose

The comment inside the if block mentions localization, which may not align with the purpose of the SavePersistenceAttributesToSession interceptor. Update the comment to accurately reflect that persistence attributes should not be saved when the skill is disabled.


190-192: Function name 'isValidRequestType' may be misleading

The function isValidRequestType returns true for request types where processing should be skipped. Consider renaming it to shouldSkipProcessing or isExcludedRequestType to better convey its purpose.

lambda/handlers/intentHandler.js (1)

659-659: Specify radix parameter in parseInt to avoid unexpected results

When using parseInt, it's best practice to specify the radix parameter to prevent unexpected behavior due to different number bases.

Apply this diff:

-const adhaanReciter = adhaanRecitation[parseInt(favouriteReciter) - 1];
+const adhaanReciter = adhaanRecitation[parseInt(favouriteReciter, 10) - 1];
lambda/handlers/audioPlayerHandler.js (1)

15-18: Fix operator precedence in canHandle method

The parentheses around the startsWith check are unnecessary and might be confusing.

   canHandle(handlerInput) {
-    return (
-      Alexa.getRequestType(handlerInput.requestEnvelope).startsWith("PlaybackController")
-    );
+    return Alexa.getRequestType(handlerInput.requestEnvelope).startsWith("PlaybackController");
   },
lambda/datasources.js (2)

114-138: Add input validation in getMetadata

The function assumes all required attributes exist and are valid.

 const getMetadata = (handlerInput, title) => {
+  if (!handlerInput || !title) {
+    throw new Error("Missing required parameters in getMetadata");
+  }
   const requestAttributes =
     handlerInput.attributesManager.getRequestAttributes();
+  if (!requestAttributes) {
+    throw new Error("Request attributes not available");
+  }
   let albumArtImage = requestAttributes.t("logoUrl");
+  if (!albumArtImage) {
+    albumArtImage = "default_logo_url";  // Add a default fallback
+  }
   let metadata = {
     title: title,
     subtitle: requestAttributes.t("skillName"),

110-112: Add JSDoc documentation for getDataSourceForAdhaanReciter

The function lacks documentation about its parameters and return value.

+/**
+ * Generates data source for adhaan reciter list
+ * @param {Object} handlerInput - The Alexa skill handler input
+ * @param {Array} adhaanRecitation - List of available adhaan recitations
+ * @returns {Promise<Object>} Data source for the APL template
+ */
 const getDataSourceForAdhaanReciter = async (handlerInput, adhaanRecitation) => {
     return getDataSourceforMosqueList(handlerInput, adhaanRecitation, "titleForAdhaanReciterList");
 };
lambda/prompts/en_US.js (1)

49-53: Ensure consistent user experience across touch and voice interactions.

The prompts effectively guide users through both voice and touch interactions for selecting adhan recitations. However, consider adding validation feedback when users make their selection to confirm their choice before finalizing it.

 adhanReciterPrompt: `Which recitation would you like to set as favourite for the adhan? You can choose between %s. You can choose by saying the number associated with the recitation `,
+adhanReciterConfirmationPrompt: `You've selected %s. Is this correct? Say yes to confirm or no to choose again.`,
 adhanReciterErrorPrompt: `Sorry, I couldn't find any recitations for the adhan. Please try again.`,
 adhanReciterSuccessPrompt: `Perfect, %s is now your favorite recitation for the adhan! `,
lambda/index.js (1)

46-54: Enhance error handling for directive service failures

While logging the error is good, consider providing a graceful fallback for users when the directive service fails.

 async handle(handlerInput) {
   const { attributesManager } = handlerInput;
   const requestAttributes = attributesManager.getRequestAttributes();
   await helperFunctions
     .callDirectiveService(handlerInput, requestAttributes.t("welcomePrompt"))
     .catch((error) => {
       console.log("Error while calling directive service: ", error);
+      // Provide a graceful fallback response
+      handlerInput.responseBuilder.speak(requestAttributes.t("welcomePrompt"));
     });
   return await helperFunctions.checkForPersistenceData(handlerInput);
 }
interactionModels/de-DE.json (1)

243-250: Add sample utterances for audio control intents

Consider adding German sample utterances for AMAZON.ResumeIntent and AMAZON.PauseIntent to improve voice interaction.

 {
   "name": "AMAZON.ResumeIntent",
-  "samples": []
+  "samples": [
+    "weiter",
+    "fortsetzen",
+    "weitermachen",
+    "fortfahren"
+  ]
 },
 {
   "name": "AMAZON.PauseIntent",
-  "samples": []
+  "samples": [
+    "pause",
+    "pausieren",
+    "anhalten",
+    "unterbrechen"
+  ]
 }
interactionModels/en-US.json (1)

293-298: Add sample utterances for audio control intents

Consider adding sample utterances for AMAZON.PauseIntent and AMAZON.ResumeIntent to improve voice interaction.

 {
   "name": "AMAZON.PauseIntent",
-  "samples": []
+  "samples": [
+    "pause",
+    "pause the audio",
+    "stop playing",
+    "pause playback"
+  ]
 },
 {
   "name": "AMAZON.ResumeIntent",
-  "samples": []
+  "samples": [
+    "resume",
+    "continue",
+    "continue playing",
+    "resume playback"
+  ]
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c57d03a and e806039.

📒 Files selected for processing (20)
  • interactionModels/de-DE.json (4 hunks)
  • interactionModels/en-AU.json (0 hunks)
  • interactionModels/en-CA.json (0 hunks)
  • interactionModels/en-GB.json (0 hunks)
  • interactionModels/en-IN.json (0 hunks)
  • interactionModels/en-US.json (6 hunks)
  • interactionModels/fr-CA.json (0 hunks)
  • interactionModels/fr-FR.json (17 hunks)
  • lambda/aplDocuments/mosqueListApl.json (1 hunks)
  • lambda/datasources.js (3 hunks)
  • lambda/handlers/audioPlayerHandler.js (1 hunks)
  • lambda/handlers/intentHandler.js (4 hunks)
  • lambda/handlers/touchHandler.js (3 hunks)
  • lambda/helperFunctions.js (3 hunks)
  • lambda/index.js (3 hunks)
  • lambda/interceptors.js (6 hunks)
  • lambda/languageStrings.js (2 hunks)
  • lambda/prompts/de_DE.js (1 hunks)
  • lambda/prompts/en_US.js (1 hunks)
  • lambda/prompts/fr_FR.js (1 hunks)
💤 Files with no reviewable changes (5)
  • interactionModels/en-CA.json
  • interactionModels/en-IN.json
  • interactionModels/fr-CA.json
  • interactionModels/en-AU.json
  • interactionModels/en-GB.json
🧰 Additional context used
🪛 Biome (1.9.4)
lambda/handlers/intentHandler.js

[error] 319-319: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

lambda/interceptors.js

[error] 40-40: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (13)
lambda/interceptors.js (1)

30-31: Approve addition of async and response check in 'AddDirectiveResponseInterceptor'

The change to make the process method asynchronous and to add a check for undefined response improves the robustness of the code by preventing potential runtime errors.

lambda/languageStrings.js (2)

3-3: Addition of German language support

The import statement for de_DE is correctly added, enabling German language prompts.


13-13: Exporting 'de-DE' mapping

The mapping for 'de-DE' is correctly added to the exports, enabling language support for German users.

lambda/aplDocuments/mosqueListApl.json (1)

32-32: Addition of title to 'SendEvent' arguments

Including "${payload.imageListData.title}" in the arguments array provides additional context to the event handler, which can enhance user interaction handling.

lambda/prompts/en_US.js (1)

48-48: LGTM!

The formatting change maintains consistency with other prompts.

lambda/index.js (3)

24-36: LGTM: Import statements are properly structured

The new imports for audio-related handlers and favorite adhaan reciter functionality are well-organized and align with the Version 2 feature requirements.


Line range hint 192-208: LGTM: Handler chain is properly ordered

The new audio and adhaan reciter handlers are correctly positioned in the chain, with audio handlers having appropriate precedence.


216-219: LGTM: Interceptors are properly ordered

The interceptor chain is well-organized with logging, localization, and persistence interceptors in the correct order.

interactionModels/de-DE.json (1)

281-283: LGTM: Prayer name formatting is consistent

The apostrophe usage in prayer names has been standardized correctly.

Also applies to: 292-294

interactionModels/en-US.json (1)

162-165: LGTM: Sample utterances are well-defined

The new sample utterances for NextPrayerTimeIntent provide good coverage of natural language variations.

interactionModels/fr-FR.json (2)

323-328: LGTM: Built-in Alexa intents

The addition of AMAZON.ResumeIntent and AMAZON.PauseIntent with empty samples is correct as these are built-in Alexa intents that handle standard pause/resume commands.


390-390: Verify apostrophe handling in "isha'a"

While adding this synonym improves voice recognition, verify that the apostrophe in "isha'a" is properly handled by Alexa's speech recognition system.

✅ Verification successful

Apostrophe in "isha'a" is safe to use

The search results show that apostrophes are already successfully used throughout the interaction models:

  • In French (fr-FR) for contractions like "l'heure", "d'aujourd'hui"
  • In English (en-US) for contractions like "I'm", "don't" and prayer name "Jumu'ah"
  • In German (de-DE) for prayer names including "Isha'a" itself

The apostrophe in "isha'a" follows the same pattern as other prayer names and contractions that are already working in the interaction models, making it a safe addition.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if other intents in the model use apostrophes successfully
rg -l "'" interactionModels/

Length of output: 116


Script:

#!/bin/bash
# Check actual usage of apostrophes in interaction models
rg -A 2 -B 2 "'" interactionModels/*.json

Length of output: 10494

lambda/helperFunctions.js (1)

85-87: Verify impact of removing welcome prompt

The removal of the welcome prompt parameter might affect the user experience. Ensure this change aligns with the intended interaction flow.

✅ Verification successful

Removal of welcome prompt parameter is safe

The welcome message is still properly handled through the main index.js using callDirectiveService with the localized welcome prompt. The removal of the welcome prompt parameter from getPrayerTimingsForMosque and getListOfMosque functions doesn't impact the user experience as the welcome message is delivered separately through the directive service.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check usage of welcome prompts across the codebase
rg "welcomePrompt|welcome_prompt" --type js

Length of output: 332


Script:

#!/bin/bash
# Check the implementation of getPrayerTimingsForMosque and getListOfMosque functions
ast-grep --pattern 'function getPrayerTimingsForMosque($_,$_,$_) { $$$ }'
ast-grep --pattern 'function getListOfMosque($_,$_) { $$$ }'

# Check for any other welcome message handling
rg "welcomePrompt" -B 2 -A 2 --type js

Length of output: 2035

lambda/interceptors.js Outdated Show resolved Hide resolved
lambda/interceptors.js Outdated Show resolved Hide resolved
lambda/handlers/intentHandler.js Show resolved Hide resolved
lambda/handlers/intentHandler.js Outdated Show resolved Hide resolved
lambda/handlers/audioPlayerHandler.js Show resolved Hide resolved
interactionModels/en-US.json Outdated Show resolved Hide resolved
interactionModels/fr-FR.json Outdated Show resolved Hide resolved
interactionModels/fr-FR.json Outdated Show resolved Hide resolved
lambda/helperFunctions.js Outdated Show resolved Hide resolved
lambda/helperFunctions.js Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (2)
lambda/handlers/audioPlayerHandler.js (1)

6-9: Add logging to AudioPlayerEventHandler for better debugging

Currently, the AudioPlayerEventHandler returns a response without any logging. Adding logging statements can help in debugging audio player events.

Consider adding a console log in the handle method:

async handle(handlerInput) {
+  const audioPlayerEvent = Alexa.getRequestType(handlerInput.requestEnvelope);
+  console.log("Audio Player Event:", audioPlayerEvent);
   return handlerInput.responseBuilder.getResponse();
},
lambda/handlers/intentHandler.js (1)

562-640: Handle potential errors in translation service

In FavoriteAdhaanReciterStartedHandler, the translation of adhaan.primaryText may fail if the translation service encounters an error. This could break the skill's flow.

Consider adding error handling for the translation calls:

try {
  adhaan.primaryText = await helperFunctions.translateText(
    adhaan.primaryText,
    locale
  );
} catch (translationError) {
  console.log("Translation error:", translationError);
  // Fallback to original text if translation fails
  adhaan.primaryText = adhaan.primaryText;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e806039 and 697f5a8.

📒 Files selected for processing (8)
  • interactionModels/en-US.json (6 hunks)
  • interactionModels/fr-FR.json (17 hunks)
  • lambda/handlers/audioPlayerHandler.js (1 hunks)
  • lambda/handlers/intentHandler.js (4 hunks)
  • lambda/helperFunctions.js (3 hunks)
  • lambda/interceptors.js (6 hunks)
  • lambda/prompts/de_DE.js (1 hunks)
  • lambda/prompts/fr_FR.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lambda/prompts/de_DE.js
🔇 Additional comments (16)
lambda/handlers/audioPlayerHandler.js (3)

47-55: Add handling for AMAZON.PauseIntent

The PauseIntent currently falls through to the default case. Consider adding specific handling to properly manage the pause action.

As previously suggested, apply this diff:

switch (intent) {
  case "AMAZON.ResumeIntent":
    return await intentHandler.PlayAdhanIntentHandler.handle(handlerInput);
+ case "AMAZON.PauseIntent":
+   return handlerInput.responseBuilder
+     .addAudioPlayerStopDirective()
+     .withShouldEndSession(false)  // Allow resuming later
+     .getResponse();
  default:
    return handlerInput.responseBuilder
      .addAudioPlayerStopDirective()
      .withShouldEndSession(true)
      .getResponse();
}

21-32: 🛠️ Refactor suggestion

Add error handling for PlayAdhanIntentHandler

In PlaybackCommandHandler, the playback commands delegate to PlayAdhanIntentHandler without error handling. Wrapping the call in a try-catch block can handle unexpected errors gracefully.

Apply this diff to add error handling:

switch (playback) {
  case "PlaybackController.PlayCommandIssued":        
  case "PlaybackController.NextCommandIssued":
  case "PlaybackController.PreviousCommandIssued":
-    return await intentHandler.PlayAdhanIntentHandler.handle(handlerInput);
+    try {
+      return await intentHandler.PlayAdhanIntentHandler.handle(handlerInput);
+    } catch (error) {
+      console.error("Error in PlayAdhanIntentHandler:", error);
+      return handlerInput.responseBuilder
+        .speak("Sorry, there was an error playing the adhaan.")
+        .withShouldEndSession(true)
+        .getResponse();
+    }
  default:
    return handlerInput.responseBuilder
      .addAudioPlayerStopDirective()
      .withShouldEndSession(true)
      .getResponse();
}

38-42: ⚠️ Potential issue

Fix logical operator precedence in canHandle method

In AudioIntentHandler, the condition in the canHandle method may produce unexpected results due to operator precedence. Enclosing the || conditions within parentheses ensures correct evaluation.

Apply this diff to fix the logical operator precedence:

return (
  Alexa.getRequestType(handlerInput.requestEnvelope) === "IntentRequest" &&
- Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.ResumeIntent" ||
-  Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.PauseIntent"
+ (Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.ResumeIntent" ||
+  Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.PauseIntent")
);
lambda/handlers/intentHandler.js (2)

666-668: ⚠️ Potential issue

Initialize persistentAttributes before assignment

Ensure that sessionAttributes.persistentAttributes is initialized before assigning favouriteAdhaan to prevent potential runtime errors.

Apply this diff to initialize persistentAttributes if undefined:

+ if (!sessionAttributes.persistentAttributes) {
+   sessionAttributes.persistentAttributes = {};
+ }
sessionAttributes.persistentAttributes.favouriteAdhaan = adhaanReciter;

314-336: ⚠️ Potential issue

Ensure persistentAttributes is defined before use

In PlayAdhanIntentHandler, persistentAttributes may be undefined if not previously set. Accessing properties on an undefined object can cause runtime errors.

Modify the code to check if persistentAttributes and persistentAttributes.favouriteAdhaan are defined:

const { persistentAttributes } = sessionAttributes;    
let audioName = "Adhaan";
let audioUrl = prayerName === "0" ? adhaanRecitation[0].fajrUrl : adhaanRecitation[0].otherUrl;

- if(persistentAttributes?.favouriteAdhaan){
+ if (persistentAttributes && persistentAttributes.favouriteAdhaan) {
    const { primaryText } = persistentAttributes.favouriteAdhaan;
    audioName = primaryText;
    audioUrl = prayerName === "0" ? persistentAttributes.favouriteAdhaan.fajrUrl : persistentAttributes.favouriteAdhaan.otherUrl;
}

Likely invalid or redundant comment.

lambda/prompts/fr_FR.js (1)

52-57: Verify the accuracy and naturalness of French translations

Please ensure that the French translations for the new prompts accurately reflect the intended meanings and are idiomatic.

Consider consulting a native French speaker or a professional translator to review the following prompts:

  • adhanReciterPrompt
  • adhanReciterErrorPrompt
  • adhanReciterSuccessPrompt
  • chooseAdhaanByTouchPrompt
lambda/interceptors.js (1)

189-193: ⚠️ Potential issue

Correct typo in function name SetApiKeysAsEnvironmentVaraibleFromAwsSsm

The function name contains a typo: "Varaible" should be "Variable". Ensure all references are updated accordingly.

Apply this diff to fix the typo:

- const SetApiKeysAsEnvironmentVaraibleFromAwsSsm = {
+ const SetApiKeysAsEnvironmentVariableFromAwsSsm = {

And update the export statement:

module.exports = {
  LogResponseInterceptor,
  LogRequestInterceptor,
  LocalizationInterceptor,
  SavePersistenceAttributesToSession,
  AddDirectiveResponseInterceptor,
- SetApiKeysAsEnvironmentVaraibleFromAwsSsm
+ SetApiKeysAsEnvironmentVariableFromAwsSsm
};
interactionModels/en-US.json (4)

Line range hint 162-177: LGTM! Good variety of sample utterances

The sample utterances provide comprehensive coverage of different ways users might ask about prayer times.


451-459: LGTM! Clear elicitation prompt

The prompt is clear and appropriate for number input.


292-298: Verify audio player implementation

The addition of AMAZON.PauseIntent and AMAZON.ResumeIntent suggests audio playback functionality.

Let's verify the audio player implementation:

✅ Verification successful

Audio player implementation is properly implemented

The codebase has a complete audio player implementation with:

  • Dedicated AudioPlayerEventHandler for handling audio player events
  • AudioIntentHandler specifically handling AMAZON.PauseIntent and AMAZON.ResumeIntent
  • Proper audio playback directives (.addAudioPlayerPlayDirective and .addAudioPlayerStopDirective)
  • Integration with the skill's main functionality for playing Adhan (call to prayer)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for audio player handler implementation
ast-grep --pattern 'class $_ {
  $$$
  handle$_(handlerInput) {
    $$$
    AMAZON.$_Intent
    $$$
  }
  $$$
}'

Length of output: 114


Script:

#!/bin/bash
# Search for audio player related handlers and implementations
rg -i "pause|resume|audioplayer" -A 5 -B 5

# Also check for audio player interface declaration
rg -i "audioPlayer" -A 2 -B 2

Length of output: 11014


38-54: 🛠️ Refactor suggestion

Add input validation for reciter selection

The favouriteReciter slot uses AMAZON.NUMBER without bounds checking, which could allow invalid selections.

Let's verify the available reciter options:

Consider adding validation in the handler to ensure the selected number corresponds to a valid reciter option.

interactionModels/fr-FR.json (2)

331-343: LGTM! Well-localized French utterances

The French sample utterances are properly localized and provide good coverage.


522-525: LGTM! Properly translated prompt

The elicitation prompt is correctly translated to French.

lambda/helperFunctions.js (3)

466-489: LGTM! Well-implemented progressive response handling

The implementation includes proper error handling and follows best practices.


491-493: LGTM! Correct Promise implementation

The sleep function is properly implemented using Promise and setTimeout.


85-87: Consider user experience impact

Removing the welcome prompt might affect the user experience for first-time users.

Let's check if the welcome prompt is handled elsewhere:

lambda/handlers/intentHandler.js Outdated Show resolved Hide resolved
lambda/interceptors.js Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
lambda/handlers/intentHandler.js (1)

317-323: Add fallback handling for audio URL selection

The logic for selecting the audio URL is correct but could be more robust with default values and destructuring.

Consider this refactor:

-let audioName = "Adhaan";
-let audioUrl = prayerName === "0"? adhaanRecitation[0].fajrUrl : adhaanRecitation[0].otherUrl;
-if(persistentAttributes?.favouriteAdhaan){
-  const { primaryText } = persistentAttributes.favouriteAdhaan;
-  audioName = primaryText;
-  audioUrl = prayerName === "0"?  persistentAttributes.favouriteAdhaan.fajrUrl : persistentAttributes.favouriteAdhaan.otherUrl;
-} 
+const defaultReciter = adhaanRecitation[0];
+const favoriteReciter = persistentAttributes?.favouriteAdhaan;
+const selectedReciter = favoriteReciter || defaultReciter;
+const audioName = selectedReciter.primaryText || "Adhaan";
+const audioUrl = prayerName === "0" ? selectedReciter.fajrUrl : selectedReciter.otherUrl;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 697f5a8 and e258c7d.

📒 Files selected for processing (1)
  • lambda/handlers/intentHandler.js (4 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
lambda/handlers/intentHandler.js

[error] 660-660: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.

(lint/suspicious/noGlobalIsNan)

🔇 Additional comments (1)
lambda/handlers/intentHandler.js (1)

671-673: ⚠️ Potential issue

Initialize persistentAttributes before assignment

This is a duplicate of a previously identified issue where persistentAttributes needs to be initialized before use.

lambda/handlers/intentHandler.js Outdated Show resolved Hide resolved
lambda/handlers/intentHandler.js Show resolved Hide resolved
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (4)
lambda/handlers/intentHandler.js (1)

658-658: Specify radix parameter in parseInt

When using parseInt, it's recommended to specify the radix to avoid unexpected results due to different number formats.

Suggested fix:

-        const reciterIndex = parseInt(favouriteReciter) - 1;
+        const reciterIndex = parseInt(favouriteReciter, 10) - 1;
lambda/handlers/apiHandler.js (1)

73-90: LGTM with suggestions for error handling enhancement.

The implementation follows the established pattern in the codebase for API calls. However, consider enhancing the error handling to provide more specific error messages for different failure scenarios.

 const getRandomHadith = async (lang = "ar") => {
   const config = getConfig("get", `/hadith/random?lang=${lang}`, "2.0");
   console.log("Config: ", JSON.stringify(config, null, 2).replace(/Bearer \w+/g, "Bearer ****"));
   return await axios
     .request(config)
     .then((response) => {
       console.log("Hadith: ", JSON.stringify(response.data));
       if (!response || !response.data || !response.data.text) {
-        throw "Received Empty Response";
+        throw new Error("No hadith text found in response");
       }
 
       return response.data.text;
     })
     .catch((error) => {
       console.log("Error while fetching Hadith: ", error);
+      if (error.response) {
+        switch (error.response.status) {
+          case 404:
+            throw new Error("No hadith found for the specified language");
+          case 429:
+            throw new Error("Rate limit exceeded");
+          default:
+            throw new Error(`API error: ${error.response.status}`);
+        }
+      }
       throw error;
     });
 }
lambda/helperFunctions.js (1)

466-489: Consider enhancing error handling with specific error types.

While the implementation is good, error handling could be more specific.

Consider this enhancement:

 async function callDirectiveService(handlerInput, speakOutput) {
   console.log("Call Directive Service");
   try {
     const requestEnvelope = handlerInput.requestEnvelope;
     const directiveServiceClient = handlerInput.serviceClientFactory.getDirectiveServiceClient();
 
     const requestId = requestEnvelope.request.requestId;
     const directive = {
       header: {
         requestId,
       },
       directive: {
         type: 'VoicePlayer.Speak',
         speech: speakOutput,
       },
     };
 
     return await directiveServiceClient.enqueue(directive);
   } catch (error) {
-    console.error('Error calling directive service:', error);
+    if (error.name === 'ServiceError') {
+      console.error('Service error in directive service:', error.message);
+    } else if (error.name === 'DirectiveServiceError') {
+      console.error('Directive service error:', error.message);
+    } else {
+      console.error('Unexpected error in directive service:', error);
+    }
     // Continue skill flow without progressive response
     return Promise.resolve();
   }
 }
lambda/index.js (1)

218-221: Consider the order of request interceptors

The sequence of request interceptors can affect their functionality. It might be beneficial to place SetApiKeysAsEnvironmentVariableFromAwsSsm before LocalizationInterceptor if localization depends on environment variables set by it.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e258c7d and 4142c42.

📒 Files selected for processing (12)
  • interactionModels/de-DE.json (4 hunks)
  • interactionModels/en-US.json (6 hunks)
  • interactionModels/fr-FR.json (17 hunks)
  • lambda/handlers/apiHandler.js (3 hunks)
  • lambda/handlers/audioPlayerHandler.js (1 hunks)
  • lambda/handlers/intentHandler.js (4 hunks)
  • lambda/helperFunctions.js (4 hunks)
  • lambda/index.js (3 hunks)
  • lambda/interceptors.js (5 hunks)
  • lambda/prompts/de_DE.js (1 hunks)
  • lambda/prompts/en_US.js (1 hunks)
  • lambda/prompts/fr_FR.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lambda/prompts/en_US.js
  • interactionModels/de-DE.json
🧰 Additional context used
📓 Learnings (1)
lambda/handlers/audioPlayerHandler.js (1)
Learnt from: ijaz26
PR: mawaqit/alexa#4
File: lambda/handlers/audioPlayerHandler.js:22-27
Timestamp: 2024-12-12T13:46:45.984Z
Learning: In the file `lambda/handlers/audioPlayerHandler.js`, the `PlaybackCommandHandler` delegates to `PlayAdhanIntentHandler` without additional error handling, and this is acceptable.
🪛 Biome (1.9.4)
lambda/handlers/intentHandler.js

[error] 695-698: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.
Safe fix: Remove redundant block.

(lint/complexity/noUselessLoneBlockStatements)

🔇 Additional comments (19)
lambda/prompts/de_DE.js (1)

54-54: ⚠️ Potential issue

Translate 'hadithErrorPrompt' to German

The prompt for 'hadithErrorPrompt' is in English. Please translate it to German to maintain consistency and provide a seamless user experience.

Suggested fix:

-          hadithErrorPrompt: `Sorry, I couldn't find any hadiths. Please try again.`,
+          hadithErrorPrompt: `Entschuldigung, ich konnte keine Hadithe finden. Bitte versuchen Sie es erneut.`,
lambda/handlers/intentHandler.js (1)

670-672: ⚠️ Potential issue

Initialize 'persistentAttributes' before assignment

Ensure that sessionAttributes.persistentAttributes is initialized before assigning favouriteAdhaan to prevent potential runtime errors.

Suggested fix:

+        sessionAttributes.persistentAttributes = sessionAttributes.persistentAttributes || {};
         sessionAttributes.persistentAttributes.favouriteAdhaan = adhaanReciter;
lambda/handlers/audioPlayerHandler.js (1)

40-44: ⚠️ Potential issue

Fix logical operator precedence in canHandle method

The current condition may not behave as intended due to operator precedence. To correctly check if the request is an IntentRequest and the intent name is either AMAZON.ResumeIntent or AMAZON.PauseIntent, we should adjust the parentheses.

Suggested fix:

      return (
        Alexa.getRequestType(handlerInput.requestEnvelope) === "IntentRequest" &&
-       Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.ResumeIntent" ||
-        Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.PauseIntent"
+       (
+         Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.ResumeIntent" ||
+         Alexa.getIntentName(handlerInput.requestEnvelope) === "AMAZON.PauseIntent"
+       )
      );
lambda/interceptors.js (2)

30-31: LGTM! Improved code robustness.

Good improvements:

  • Added null check for response
  • Updated to use optional chaining for safer property access

Also applies to: 40-40


190-192: LGTM! Good function extraction.

The isValidRequestType function effectively consolidates the request type validation logic.

interactionModels/en-US.json (3)

109-111: LGTM! Natural language samples.

The fallback samples are well-chosen and follow natural conversation patterns.


162-165: LGTM! Comprehensive prayer time query samples.

The new samples provide good coverage for different ways users might ask about prayer times.


292-299: LGTM! Proper implementation of media control intents.

The AMAZON.PauseIntent and AMAZON.ResumeIntent are correctly implemented as built-in intents.

interactionModels/fr-FR.json (2)

73-78: LGTM! Natural French translations.

The French samples are well-translated and maintain natural language patterns.

Also applies to: 97-101


331-344: LGTM! Well-localized reciter selection intent.

The French implementation provides good coverage with natural language samples.

lambda/helperFunctions.js (2)

85-87: LGTM! Simplified persistence check flow.

The changes streamline the function by removing unnecessary parameters.


Line range hint 452-465: LGTM! Improved language handling.

The function now properly handles language codes with better error management.

lambda/index.js (7)

193-195: Ensure correct ordering of audio handlers

The AudioPlayerEventHandler, PlaybackCommandHandler, and AudioIntentHandler have been added. Verify that these handlers are ordered correctly in the handler chain to prioritize specific intent handling and prevent conflicts.


202-202: Verify the placement of HadithIntentHandler

Confirm that the HadithIntentHandler is correctly placed in the request handler chain to ensure it processes HadithIntent without interference from other handlers.


210-210: Ensure AdhaanRecitationTouchEventHandler is correctly implemented

The AdhaanRecitationTouchEventHandler has been added to handle touch events. Verify that it is properly implemented and integrated with the skill's touch interface.


42-44: Verify the necessity of handling "LaunchIntent"

In the LaunchRequestHandler, you are checking for an IntentRequest with the intent name "LaunchIntent". Typically, the skill launch is handled by "LaunchRequest". Ensure that "LaunchIntent" is defined in your interaction model and that this check is required.

Run the following script to confirm if "LaunchIntent" exists in your interaction models:

✅ Verification successful

Let me check the interaction model files to understand how this LaunchIntent is defined and used.


The handling of "LaunchIntent" is correctly implemented

The LaunchIntent is properly defined in all interaction models with appropriate utterances for launching the skill in different languages (e.g., "open mawaqit", "launch mawaqit", etc.). The code's dual handling of both LaunchRequest and LaunchIntent is intentional and correct, allowing users to start the skill either through the default launch phrase or through these custom launch utterances.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for "LaunchIntent" in the interaction model files.

# Test: Check for the definition of "LaunchIntent".
# Expect: Find intent definitions if it exists.
rg '"name":\s*"LaunchIntent"' interactionModels/

Length of output: 680


Script:

#!/bin/bash
# Get a sample of the LaunchIntent definition from one of the interaction models
cat interactionModels/en-US.json | jq '.interactionModel.languageModel.intents[] | select(.name == "LaunchIntent")'

# Check if there are any sample utterances or other handlers using LaunchIntent
rg -A 5 '"LaunchIntent"' interactionModels/

Length of output: 3880


47-54: Unnecessary await with checkForPersistenceData

You're using await with helperFunctions.checkForPersistenceData(handlerInput);. If checkForPersistenceData is not an asynchronous function returning a promise, the await keyword is unnecessary and should be removed to avoid potential delays.

Run the following script to verify if checkForPersistenceData is asynchronous:


205-207: Confirm the addition of new intent handlers

The handlers SelectMosqueIntentAfterSelectingMosqueHandler, FavoriteAdhaanReciterStartedHandler, and FavoriteAdhaanReciterIntentHandler have been added. Ensure these handlers are properly implemented and their corresponding intents are defined in the interaction model.

Run the following script to check for the intents:

✅ Verification successful

Let me verify the implementation of these handlers.


Let me check if these handlers are properly registered in the skill builder.


Let me check the rest of the skill builder registration to see if our new handlers are included.


All handlers are properly implemented and registered

Based on the verification results:

  • All three handlers (SelectMosqueIntentAfterSelectingMosqueHandler, FavoriteAdhaanReciterStartedHandler, and FavoriteAdhaanReciterIntentHandler) are fully implemented in lambda/handlers/intentHandler.js
  • The handlers are properly registered in the skill builder
  • The FavoriteAdhaanReciterIntent is defined in both en-US and fr-FR interaction models
  • While SelectMosqueIntentAfterSelectingMosque intent is not found in interaction models, it's because it reuses the existing SelectMosqueIntent with a specific slot value condition in its canHandle method
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the new intents are defined.

# Test: Search for intent definitions.
# Expect: Find definitions of the intents.
rg '"name":\s*"SelectMosqueIntentAfterSelectingMosque"' interactionModels/
rg '"name":\s*"FavoriteAdhaanReciterStartedIntent"' interactionModels/
rg '"name":\s*"FavoriteAdhaanReciterIntent"' interactionModels/

Length of output: 527


Script:

#!/bin/bash
# Check for handler implementations
ast-grep --pattern 'const SelectMosqueIntentAfterSelectingMosqueHandler = {
  $$$
}'

ast-grep --pattern 'const FavoriteAdhaanReciterStartedHandler = {
  $$$
}'

ast-grep --pattern 'const FavoriteAdhaanReciterIntentHandler = {
  $$$
}'

# Also check if these handlers are properly registered
rg -A 5 "exports.handler = Alexa.SkillBuilders" lambda/

Length of output: 14602


Script:

#!/bin/bash
# Check if the new handlers are registered in the skill builder
rg -B 5 -A 15 'exports.handler = Alexa.SkillBuilders' lambda/index.js

Length of output: 830


Script:

#!/bin/bash
# Get more lines of the skill builder registration
rg -B 5 -A 30 'exports.handler = Alexa.SkillBuilders' lambda/index.js

Length of output: 1304


10-10: Verify the correct import of SetApiKeysAsEnvironmentVariableFromAwsSsm

Ensure that SetApiKeysAsEnvironmentVariableFromAwsSsm is correctly exported and spelled consistently across the codebase.

Run the following script to check its export:

✅ Verification successful

SetApiKeysAsEnvironmentVariableFromAwsSsm is correctly defined and used

The interceptor is properly defined in lambda/interceptors.js as an object and is correctly imported and used in lambda/index.js. The naming is consistent across all occurrences in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that `SetApiKeysAsEnvironmentVariableFromAwsSsm` is exported from 'interceptors.js'.

# Test: Search for the export statement. Expect: Find the export of the interceptor.
rg 'exports\.SetApiKeysAsEnvironmentVariableFromAwsSsm' lambda/interceptors.js

Length of output: 80


Script:

#!/bin/bash
# Let's try different search patterns to find this function/class

# Search for the exact name in all files
rg "SetApiKeysAsEnvironmentVariableFromAwsSsm" -A 3

# Search for similar names (in case of typos)
rg -i "set.*api.*keys.*environment.*ssm"

# Look for exports containing similar patterns
rg "exports\.(Set|set).*SSM"

# Use ast-grep to find function/class declarations with similar name
ast-grep --pattern 'function SetApiKeysAsEnvironmentVariableFromAwsSsm($_) { $$$ }'
ast-grep --pattern 'class SetApiKeysAsEnvironmentVariableFromAwsSsm { $$$ }'

Length of output: 1696

Comment on lines 695 to 698
const hadith = await getRandomHadith(locale).catch((error) => {{
console.log("Error in fetching hadith: ", error);
return requestAttributes.t("hadithErrorPrompt");
}});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove redundant block statement

There is an unnecessary block statement in the catch block that can be safely removed to simplify the code.

Suggested fix:

-        const hadith = await getRandomHadith(locale).catch((error) => {{
+        const hadith = await getRandomHadith(locale).catch((error) => {
           console.log("Error in fetching hadith: ", error);
           return requestAttributes.t("hadithErrorPrompt");
-        }});
+        });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hadith = await getRandomHadith(locale).catch((error) => {{
console.log("Error in fetching hadith: ", error);
return requestAttributes.t("hadithErrorPrompt");
}});
const hadith = await getRandomHadith(locale).catch((error) => {
console.log("Error in fetching hadith: ", error);
return requestAttributes.t("hadithErrorPrompt");
});
🧰 Tools
🪛 Biome (1.9.4)

[error] 695-698: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.
Safe fix: Remove redundant block.

(lint/complexity/noUselessLoneBlockStatements)

@@ -1,4 +1,5 @@
const axios = require("axios");
const { lang } = require("moment");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused import.

The lang import from moment is not used in the code.

-const { lang } = require("moment");

lambda/prompts/fr_FR.js Outdated Show resolved Hide resolved
lambda/interceptors.js Outdated Show resolved Hide resolved
Comment on lines +38 to +54
},
{
"slots": [
{
"name": "favouriteReciter",
"elicitationRequired": true,
"type": "AMAZON.NUMBER",
"confirmationRequired": false,
"prompts": {
"elicitation": "Elicit.Slot.102046521153.828952134948"
}
}
],
"name": "FavoriteAdhaanReciterIntent",
"delegationStrategy": "SKILL_RESPONSE",
"confirmationRequired": false,
"prompts": {}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Slot elicitation prompt is missing variations

The elicitation prompt ID "Elicit.Slot.102046521153.828952134948" is referenced in the intent but lacks corresponding prompt variations in the prompts section. This will cause the slot elicitation to fail.

  • Add prompt variations for ID "Elicit.Slot.102046521153.828952134948" in the prompts section with appropriate messages for asking users to select their favorite reciter number.
🔗 Analysis chain

LGTM! Verify slot elicitation behavior.

The intent structure follows best practices with proper slot configuration and elicitation setup.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify elicitation prompt ID exists in prompts section
rg -A 5 "Elicit.Slot.102046521153.828952134948" interactionModels/

Length of output: 675


Script:

#!/bin/bash
# Description: Check if the elicitation prompt ID has associated variations/content
rg -B 2 -A 5 '"id": "Elicit.Slot.102046521153.828952134948"' interactionModels/en-US.json

Length of output: 188


Script:

#!/bin/bash
# Description: Get more context around the prompts section to check for variations
rg -B 10 -A 10 '"prompts": {' interactionModels/en-US.json

Length of output: 148


Script:

#!/bin/bash
# Description: Get more context around the prompts section to check for variations
rg -B 10 -A 10 '"prompts"' interactionModels/en-US.json

Length of output: 2349

lambda/helperFunctions.js Show resolved Hide resolved
lambda/index.js Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (7)
lambda/prompts/fr_FR.js (1)

51-51: Use non-breaking space before question mark

In French typography, a non-breaking space should be used before question marks. Consider using \u00A0 (non-breaking space) instead of a regular space.

-    doYouNeedAnythingElsePrompt: " Voulez-vous autre chose ?",    
+    doYouNeedAnythingElsePrompt: " Voulez-vous autre chose\u00A0?",    
lambda/handlers/apiHandler.js (1)

72-89: Enhance error handling for specific HTTP status codes.

While the implementation is solid, consider adding specific error handling for common HTTP status codes (e.g., 404, 429) to provide more informative error messages.

 const getRandomHadith = async (lang = "ar") => {
   const config = getConfig("get", `/hadith/random?lang=${lang}`, "2.0");
   console.log("Config: ", JSON.stringify(config, null, 2).replace(/Bearer \w+/g, "Bearer ****"));
   return await axios
     .request(config)
     .then((response) => {
       console.log("Hadith: ", JSON.stringify(response.data));
       if (!response || !response.data || !response.data.text) {
         throw "Received Empty Response";
       }

       return response.data.text;
     })
     .catch((error) => {
       console.log("Error while fetching Hadith: ", error);
+      if (error.response) {
+        switch (error.response.status) {
+          case 404:
+            throw "Hadith not found";
+          case 429:
+            throw "Rate limit exceeded";
+          default:
+            throw error;
+        }
+      }
       throw error;
     });
 }
lambda/helperFunctions.js (2)

Line range hint 32-38: Consider type validation for createDirectivePayload parameters.

The function could benefit from basic type validation for its parameters.

 const createDirectivePayload = (aplDocument, dataSources = {}, type = "Alexa.Presentation.APL.RenderDocument") => {
+  if (!aplDocument || typeof aplDocument !== 'object') {
+    throw new Error('Invalid APL document');
+  }
+  if (typeof dataSources !== 'object') {
+    throw new Error('Invalid dataSources');
+  }
   return {
     type: type,
     token: uuidv4(),
     document: aplDocument,
     datasources: dataSources,
   };
 };

506-512: Consider adding validation for time parameter.

The function should validate the time parameter format.

 const createDataSourceForPrayerTiming = (time) => {
+  if (!/^\d{2}:\d{2}$/.test(time)) {
+    console.warn('Invalid time format:', time);
+    return { "data": { "text": "00:00" } };
+  }
   return {
     "data": {
         "text": time
     }
   }
 }
lambda/handlers/intentHandler.js (3)

317-339: Add error handling for audio URLs

While the implementation looks good, consider adding validation for audio URLs to handle potential undefined or invalid URLs gracefully.

 let audioUrl = prayerName === "0"? adhaanRecitation[0].fajrUrl : adhaanRecitation[0].otherUrl;
+if (!audioUrl) {
+  console.error("Audio URL is undefined");
+  return handlerInput.responseBuilder
+    .speak(requestAttributes.t("audioErrorPrompt"))
+    .withShouldEndSession(false)
+    .getResponse();
+}

565-643: Consider caching translated adhaan reciter names

The translation of adhaan reciter names is performed every time the handler is called. Consider caching these translations to improve performance.

Consider implementing a translation cache:

const translationCache = new Map();

const getTranslatedText = async (text, locale) => {
  const cacheKey = `${text}_${locale}`;
  if (translationCache.has(cacheKey)) {
    return translationCache.get(cacheKey);
  }
  const translated = await helperFunctions.translateText(text, locale);
  translationCache.set(cacheKey, translated);
  return translated;
};

645-686: Add persistence validation before saving

Consider adding validation to ensure the persistence layer is available before attempting to save.

-    await attributesManager.savePersistentAttributes();
+    try {
+      await attributesManager.savePersistentAttributes();
+    } catch (error) {
+      console.error("Failed to save persistent attributes:", error);
+      return responseBuilder
+        .speak(requestAttributes.t("saveErrorPrompt"))
+        .withShouldEndSession(false)
+        .getResponse();
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4142c42 and 9032b05.

📒 Files selected for processing (6)
  • lambda/aplDocuments/characterDisplayApl.json (1 hunks)
  • lambda/handlers/apiHandler.js (2 hunks)
  • lambda/handlers/intentHandler.js (8 hunks)
  • lambda/helperFunctions.js (9 hunks)
  • lambda/interceptors.js (5 hunks)
  • lambda/prompts/fr_FR.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lambda/interceptors.js
🧰 Additional context used
📓 Learnings (1)
lambda/helperFunctions.js (1)
Learnt from: ijaz26
PR: mawaqit/alexa#4
File: lambda/helperFunctions.js:491-493
Timestamp: 2024-12-14T15:39:02.019Z
Learning: In `lambda/helperFunctions.js`, the `locale` parameter in the `splitLanguage` function will never be null, so input validation for `locale` is unnecessary.
🔇 Additional comments (12)
lambda/prompts/fr_FR.js (2)

52-56: LGTM! Well-implemented French translations

The new adhan reciter prompts are properly translated and maintain consistency with the existing localization style. The translations are natural and preserve the required format strings.


57-57: Translation looks good

The hadith error prompt is now properly translated to French, addressing the previous review comment.

lambda/aplDocuments/characterDisplayApl.json (1)

1-15: LGTM! Well-structured APL document.

The APL document is correctly configured for character display using APLT, with proper parameterization and a clean, minimalist design.

lambda/handlers/apiHandler.js (1)

107-107: LGTM! Export added correctly.

The new function is properly exported alongside existing functions.

lambda/helperFunctions.js (5)

9-9: LGTM! Required import added.

The APL document import is correctly added for character display functionality.


299-305: LGTM! Well-implemented character display check.

The function correctly checks for APLT support and adds the directive when available.


477-500: LGTM! Robust directive service implementation.

The implementation includes proper error handling and follows the progressive response pattern.


502-504: LGTM! Simple and effective language code extraction.

Based on the learnings from previous reviews, input validation is not required as the locale parameter will never be null.


530-534: LGTM! New functions properly exported.

All new functions are correctly added to the exports object.

lambda/handlers/intentHandler.js (3)

3-3: LGTM: Import statements are properly structured

The new imports align well with the added functionality for adhaan recitation and hadith features.

Also applies to: 5-10


699-702: Remove redundant block statement in catch block

The catch block contains a redundant block statement that should be removed.


721-724: LGTM: Exports are properly updated

All new handlers are correctly included in the module exports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants