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

Resend Broadcast #1267

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

maheshsattala
Copy link
Contributor

@maheshsattala maheshsattala commented Jun 26, 2024

Added code related to Resend Broadcast.
Fixed and added test cases related to the same.

Summary by CodeRabbit

  • New Features

    • Introduced an endpoint to resend scheduled message broadcasts.
    • Added functionality for resending broadcasts via WhatsApp.
  • Enhancements

    • Improved handling of message broadcast settings and event logging.
    • Enhanced configuration retrieval for message broadcasts.
  • Bug Fixes

    • Refined methods to consider resend functionality and additional parameters.
  • Tests

    • Added test cases for initiating BSP onboarding, adding, resending, listing, and deleting broadcast messages.
    • Introduced tests for message broadcasting with static values.

Fixed and added test cases related to the same.
Copy link

coderabbitai bot commented Jun 26, 2024

Walkthrough

A new feature to resend scheduled message broadcasts has been integrated into the system. Changes include modifying multiple classes and methods across the code to accommodate the resend functionality. Key additions involve a new API endpoint, extended parameters in existing methods, and new constants to manage the broadcasting logic. Moreover, comprehensive tests have been added to ensure the reliability of the new feature.

Changes

Files & Paths Change Summaries
kairon/api/app/routers/bot/channels.py Added new endpoint resend_message_broadcast_event for resending scheduled message broadcasts.
kairon/events/definitions/message_broadcast.py Updated execute method and _retrieve_config method to handle is_resend parameter for resending message broadcasts.
kairon/events/definitions/scheduled_base.py Introduced _resend_broadcast method to handle EventRequestType.resend_broadcast.
kairon/shared/channels/broadcast/whatsapp.py Added resend functionality and relevant parameters to existing methods.
kairon/shared/chat/broadcast/constants.py Added new constants for MessageBroadcastLogType and MetaErrorCodes.
kairon/shared/chat/broadcast/processor.py Enhanced methods to support message broadcast settings, event logging, and extracting message IDs with new parameters.
kairon/shared/constants.py Introduced resend_broadcast to EventRequestType enum class.
Tests with integration_test/services_test.py and unit_test/events/events_test.py Added comprehensive test cases for broadcasting messages including adding, resending, listing, and deleting broadcast messages.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant Auth
    participant BroadcastProcessor
    participant BroadcastService

    Client->>API: POST /resend_broadcast
    API->>Auth: Validate user
    Auth-->>API: User validated
    API->>BroadcastProcessor: Fetch broadcast details
    BroadcastProcessor-->>API: Broadcast details
    API->>BroadcastService: Trigger resend (is_resend=True)
    BroadcastService-->>API: Resend initiated
    API-->>Client: Resend confirmation
Loading

Poem

In rabbit holes, the messages dance,
From WhatsApp shores, they take a chance.
Scheduled messages, a timely send,
Now with ease, we can resend.
Hopping through code with glee and fun,
Kairon’s broadcasts reach everyone! 🌟🐇📮

Tip

AI model upgrade

gpt-4o model for reviews and chat is now live

OpenAI claims that this model is better at understanding and generating code than the previous models. Please join our Discord Community to provide any feedback or to report any issues.


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 as 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration 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: 5

Outside diff range and nitpick comments (8)
kairon/events/definitions/scheduled_base.py (1)

Line range hint 11-11: Replace typing.Text with str and optimize dictionary key check

The use of typing.Text is deprecated, and using str is recommended. Also, checking for a key in a dictionary should be done directly without using .keys() for better performance.

- from typing import Text, Dict
+ from typing import Dict

- def enqueue(self, event_request_type: Text, **kwargs):
+ def enqueue(self, event_request_type: str, **kwargs):

- def _resend_broadcast(self, msg_broadcast_id: Text, config: Dict):
+ def _resend_broadcast(self, msg_broadcast_id: str, config: Dict):

- if event_request_type not in request_implementation.keys():
+ if event_request_type not in request_implementation:

Also applies to: 21-21, 35-35, 39-39, 43-43

Tools
Ruff

21-21: Use key not in dict instead of key not in dict.keys() (SIM118)

Remove .keys()

tests/unit_test/events/events_test.py (7)

Line range hint 11-11: Replace deprecated mock import with unittest.mock.

The mock library is now part of the unittest module in the standard library. Update the import statement to reflect this change.

- import mock
+ from unittest.mock import patch, MagicMock
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 21-21: Remove unused import.

The import kairon.shared.channels.broadcast.whatsapp.WhatsappBroadcast is not used in this file.

- from kairon.shared.channels.broadcast.whatsapp import WhatsappBroadcast
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 26-44: Reorganize imports to the top of the file.

Python convention dictates that all imports should be at the top of the file unless there is a specific reason for a delayed import.

+ from kairon.shared.chat.broadcast.processor import MessageBroadcastProcessor
+ from kairon.events.definitions.data_importer import TrainingDataImporterEvent
+ from kairon.events.definitions.faq_importer import FaqDataImporterEvent
+ from kairon.events.definitions.history_delete import DeleteHistoryEvent
+ from kairon.events.definitions.message_broadcast import MessageBroadcastEvent
+ from kairon.events.definitions.model_testing import ModelTestingEvent
+ from kairon.events.definitions.model_training import ModelTrainingEvent
+ from kairon.events.definitions.scheduled_base import ScheduledEventsBase
+ from kairon.exceptions import AppException
+ from kairon.shared.chat.broadcast.processor import MessageBroadcastProcessor
+ from kairon.shared.constants import EventClass, EventRequestType, ChannelTypes
+ from kairon.shared.data.constant import EVENT_STATUS, REQUIREMENTS
+ from kairon.shared.data.data_objects import Configs, BotSettings
+ from kairon.shared.data.history_log_processor import HistoryDeletionLogProcessor
+ from kairon.shared.data.processor import MongoProcessor
+ from kairon.shared.importer.processor import DataImporterLogProcessor
+ from kairon.shared.test.processor import ModelTestingLogProcessor
+ from kairon.shared.utils import Utility
+ from kairon.test.test_models import ModelTester
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 53-53: Use capitalized environment variable name.

It's a common convention to use uppercase for environment variable names.

- os.environ["system_file"] = "./tests/testing_data/system.yaml"
+ os.environ["SYSTEM_FILE"] = "./tests/testing_data/system.yaml"
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 853-853: Rewrite as bytes literal.

The use of the encode method here is unnecessary. You can directly define the data as a bytes literal.

- faq = "Questions,Answer,\nWhat is Digite?, IT Company,\nHow are you?, I am good,\nWhat day is it?, It is Thursday,\nWhat day is it?, It is Thursday,\n".encode()
+ faq = b"Questions,Answer,\nWhat is Digite?, IT Company,\nHow are you?, I am good,\nWhat day is it?, It is Thursday,\nWhat day is it?, It is Thursday,\n"
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 1398-1398: Use direct boolean checks.

In Python, it's more idiomatic to use direct boolean checks rather than comparing to False.

- if settings[0]["status"] == False:
+ if not settings[0]["status"]:
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


Line range hint 1851-1851: Remove unnecessary f prefix.

The f-string here does not contain any placeholders, making the f prefix unnecessary.

- f"/api/events/execute/{EventClass.data_importer}"
+ "/api/events/execute/{EventClass.data_importer}"
Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 18dd402 and 30c1027.

Files selected for processing (9)
  • kairon/api/app/routers/bot/channels.py (1 hunks)
  • kairon/events/definitions/message_broadcast.py (3 hunks)
  • kairon/events/definitions/scheduled_base.py (2 hunks)
  • kairon/shared/channels/broadcast/whatsapp.py (6 hunks)
  • kairon/shared/chat/broadcast/constants.py (1 hunks)
  • kairon/shared/chat/broadcast/processor.py (4 hunks)
  • kairon/shared/constants.py (1 hunks)
  • tests/integration_test/services_test.py (1 hunks)
  • tests/unit_test/events/events_test.py (2 hunks)
Additional context used
Ruff
kairon/events/definitions/scheduled_base.py

11-11: typing.Text is deprecated, use str (UP019)

Replace with str


21-21: Use key not in dict instead of key not in dict.keys() (SIM118)

Remove .keys()


35-35: typing.Text is deprecated, use str (UP019)

Replace with str


39-39: typing.Text is deprecated, use str (UP019)

Replace with str


43-43: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/events/definitions/message_broadcast.py

25-25: typing.Text is deprecated, use str (UP019)

Replace with str


25-25: typing.Text is deprecated, use str (UP019)

Replace with str


29-29: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


45-45: typing.Text is deprecated, use str (UP019)

Replace with str


105-105: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


107-107: typing.Text is deprecated, use str (UP019)

Replace with str


117-117: typing.Text is deprecated, use str (UP019)

Replace with str


137-137: typing.Text is deprecated, use str (UP019)

Replace with str


148-148: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/shared/channels/broadcast/whatsapp.py

36-36: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


65-65: typing.Text is deprecated, use str (UP019)

Replace with str


65-65: typing.Text is deprecated, use str (UP019)

Replace with str


65-65: typing.Text is deprecated, use str (UP019)

Replace with str


172-172: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


172-172: f-string without any placeholders (F541)

Remove extraneous f prefix


174-174: typing.Text is deprecated, use str (UP019)

Replace with str


174-174: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/shared/chat/broadcast/processor.py

21-21: typing.Text is deprecated, use str (UP019)

Replace with str


21-21: typing.Text is deprecated, use str (UP019)

Replace with str


23-23: Use not ... instead of False if ... else True (SIM211)

Replace with not ...


29-29: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


32-32: typing.Text is deprecated, use str (UP019)

Replace with str


40-40: typing.Text is deprecated, use str (UP019)

Replace with str


40-40: typing.Text is deprecated, use str (UP019)

Replace with str


51-51: typing.Text is deprecated, use str (UP019)

Replace with str


51-51: typing.Text is deprecated, use str (UP019)

Replace with str


51-51: typing.Text is deprecated, use str (UP019)

Replace with str


68-68: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


71-71: typing.Text is deprecated, use str (UP019)

Replace with str


71-71: typing.Text is deprecated, use str (UP019)

Replace with str


81-81: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


84-84: typing.Text is deprecated, use str (UP019)

Replace with str


84-84: typing.Text is deprecated, use str (UP019)

Replace with str


84-84: typing.Text is deprecated, use str (UP019)

Replace with str


84-84: typing.Text is deprecated, use str (UP019)

Replace with str


105-105: typing.Text is deprecated, use str (UP019)

Replace with str


121-121: typing.Text is deprecated, use str (UP019)

Replace with str


136-136: typing.Text is deprecated, use str (UP019)

Replace with str


149-149: typing.Text is deprecated, use str (UP019)

Replace with str


160-160: typing.Text is deprecated, use str (UP019)

Replace with str


160-160: typing.Text is deprecated, use str (UP019)

Replace with str


160-160: typing.Text is deprecated, use str (UP019)

Replace with str


182-182: typing.Text is deprecated, use str (UP019)

Replace with str


182-182: typing.Text is deprecated, use str (UP019)

Replace with str


190-190: typing.Text is deprecated, use str (UP019)

Replace with str


190-190: typing.Text is deprecated, use str (UP019)

Replace with str


200-200: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/api/app/routers/bot/channels.py

25-25: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


38-38: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


48-48: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


60-60: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


71-71: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


83-83: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


98-98: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


113-113: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


128-128: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


142-142: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


156-156: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


170-170: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


188-188: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


202-202: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


214-214: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


226-226: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


239-239: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)


252-252: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)

tests/unit_test/events/events_test.py

11-11: mock is deprecated, use unittest.mock (UP026)

Import from unittest.mock instead


21-21: kairon.shared.channels.broadcast.whatsapp.WhatsappBroadcast imported but unused (F401)

Remove unused import: kairon.shared.channels.broadcast.whatsapp.WhatsappBroadcast


24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


26-26: Module level import not at top of file (E402)


27-27: Module level import not at top of file (E402)


28-28: Module level import not at top of file (E402)


29-29: Module level import not at top of file (E402)


30-30: Module level import not at top of file (E402)


31-31: Module level import not at top of file (E402)


32-32: Module level import not at top of file (E402)


33-33: Module level import not at top of file (E402)


34-34: Module level import not at top of file (E402)


35-35: Module level import not at top of file (E402)


35-35: Redefinition of unused MessageBroadcastProcessor from line 26 (F811)

Remove definition: MessageBroadcastProcessor


36-36: Module level import not at top of file (E402)


37-37: Module level import not at top of file (E402)


38-38: Module level import not at top of file (E402)


39-39: Module level import not at top of file (E402)


40-40: Module level import not at top of file (E402)


41-41: Module level import not at top of file (E402)


42-42: Module level import not at top of file (E402)


43-43: Module level import not at top of file (E402)


44-44: Module level import not at top of file (E402)


46-46: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


53-53: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


853-853: Unnecessary call to encode as UTF-8 (UP012)

Rewrite as bytes literal


883-883: Unnecessary call to encode as UTF-8 (UP012)

Rewrite as bytes literal


929-929: Unnecessary call to encode as UTF-8 (UP012)

Rewrite as bytes literal


1398-1398: Avoid equality comparisons to False; use if not settings[0]["status"]: for false checks (E712)

Replace with not settings[0]["status"]


1851-1851: f-string without any placeholders (F541)

Remove extraneous f prefix


1856-1856: pytest.raises(Exception) should be considered evil (B017)


2340-2340: Local variable reference_id is assigned to but never used (F841)

Remove assignment to unused variable reference_id

tests/integration_test/services_test.py

9-9: mock is deprecated, use unittest.mock (UP026)

Import from unittest.mock instead


13-13: mock is deprecated, use unittest.mock (UP026)

Import from unittest.mock instead


76-76: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


85-85: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE


233-237: Use a single with statement with multiple contexts instead of nested with statements (SIM117)


690-690: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


747-747: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


793-793: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


808-808: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


835-835: f-string without any placeholders (F541)

Remove extraneous f prefix


845-845: f-string without any placeholders (F541)

Remove extraneous f prefix


1181-1181: Use context handler for opening files (SIM115)


1257-1257: Use context handler for opening files (SIM115)


1261-1261: Use context handler for opening files (SIM115)


1265-1265: Use context handler for opening files (SIM115)


1269-1269: Use context handler for opening files (SIM115)


1275-1275: Use context handler for opening files (SIM115)


1282-1282: Use context handler for opening files (SIM115)


1360-1360: Use context handler for opening files (SIM115)


1364-1364: Use context handler for opening files (SIM115)


1368-1368: Use context handler for opening files (SIM115)


1372-1372: Use context handler for opening files (SIM115)


1378-1378: Use context handler for opening files (SIM115)


1385-1385: Use context handler for opening files (SIM115)


1470-1470: Use context handler for opening files (SIM115)


1474-1474: Use context handler for opening files (SIM115)


1478-1478: Use context handler for opening files (SIM115)


1482-1482: Use context handler for opening files (SIM115)


1488-1488: Use context handler for opening files (SIM115)


1495-1495: Use context handler for opening files (SIM115)


2584-2584: Local variable response_three is assigned to but never used (F841)

Remove assignment to unused variable response_three


2808-2808: Comparison to None should be cond is None (E711)

Replace with cond is None


4586-4586: Use context handler for opening files (SIM115)


4610-4610: Use context handler for opening files (SIM115)


4644-4644: Use context handler for opening files (SIM115)


4648-4648: Use context handler for opening files (SIM115)


4652-4652: Use context handler for opening files (SIM115)


4656-4656: Use context handler for opening files (SIM115)


4662-4662: Use context handler for opening files (SIM115)


4669-4669: Use context handler for opening files (SIM115)


4703-4703: Use context handler for opening files (SIM115)


4707-4707: Use context handler for opening files (SIM115)


4713-4713: Use context handler for opening files (SIM115)


4718-4718: Use context handler for opening files (SIM115)


4722-4722: Use context handler for opening files (SIM115)


4804-4804: Use context handler for opening files (SIM115)


4836-4836: Use context handler for opening files (SIM115)


4843-4843: Use context handler for opening files (SIM115)


4850-4850: Use context handler for opening files (SIM115)


4859-4859: Use context handler for opening files (SIM115)


4866-4866: Use context handler for opening files (SIM115)


4921-4921: Use context handler for opening files (SIM115)


4928-4928: Use context handler for opening files (SIM115)


4935-4935: Use context handler for opening files (SIM115)


4944-4944: Use context handler for opening files (SIM115)


4951-4951: Use context handler for opening files (SIM115)


5062-5063: Replace yield over for loop with yield from (UP028)

Replace with yield from


5209-5209: Use context handler for opening files (SIM115)


5267-5267: Use context handler for opening files (SIM115)


5271-5271: Use context handler for opening files (SIM115)


5275-5275: Use context handler for opening files (SIM115)


5279-5279: Use context handler for opening files (SIM115)


5285-5285: Use context handler for opening files (SIM115)


5319-5319: Use context handler for opening files (SIM115)


5323-5323: Use context handler for opening files (SIM115)


5327-5327: Use context handler for opening files (SIM115)


5331-5331: Use context handler for opening files (SIM115)


5633-5633: Avoid equality comparisons to True; use if actual["success"]: for truth checks (E712)

Replace with actual["success"]


5842-5842: Do not compare types, use isinstance() (E721)


8723-8723: f-string without any placeholders (F541)

Remove extraneous f prefix


8919-8919: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


9263-9263: Local variable response_one is assigned to but never used (F841)

Remove assignment to unused variable response_one


9267-9267: Local variable response_two is assigned to but never used (F841)

Remove assignment to unused variable response_two


9271-9271: Local variable response_three is assigned to but never used (F841)

Remove assignment to unused variable response_three


9288-9289: Replace yield over for loop with yield from (UP028)

Replace with yield from


9294-9294: f-string without any placeholders (F541)

Remove extraneous f prefix


9353-9353: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


9400-9400: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


9437-9437: f-string without any placeholders (F541)

Remove extraneous f prefix


9917-9917: Local variable response_delete_story_one is assigned to but never used (F841)

Remove assignment to unused variable response_delete_story_one


9922-9922: Local variable response_delete_story_two is assigned to but never used (F841)

Remove assignment to unused variable response_delete_story_two


10610-10610: Local variable payload_response is assigned to but never used (F841)

Remove assignment to unused variable payload_response


12399-12399: Use context handler for opening files (SIM115)


12423-12423: Use context handler for opening files (SIM115)


12444-12444: Use context handler for opening files (SIM115)


12708-12708: f-string without any placeholders (F541)

Remove extraneous f prefix


13179-13179: Use context handler for opening files (SIM115)


13186-13186: Use context handler for opening files (SIM115)


13193-13193: Use context handler for opening files (SIM115)


13227-13227: Use context handler for opening files (SIM115)


13231-13231: Use context handler for opening files (SIM115)


13235-13235: Use context handler for opening files (SIM115)


13260-13260: Use context handler for opening files (SIM115)


13303-13303: Use context handler for opening files (SIM115)


13310-13310: Use context handler for opening files (SIM115)


13383-13383: Use context handler for opening files (SIM115)


13390-13390: Use context handler for opening files (SIM115)


13397-13397: Use context handler for opening files (SIM115)


13404-13404: Use context handler for opening files (SIM115)


13411-13411: Use context handler for opening files (SIM115)


13418-13418: Use context handler for opening files (SIM115)


13427-13427: Use context handler for opening files (SIM115)


13434-13434: Use context handler for opening files (SIM115)


13699-13699: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


13722-13722: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


13836-13836: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


14188-14188: Use context handler for opening files (SIM115)


14230-14230: Comparison to None should be cond is None (E711)

Replace with cond is None


14230-14230: Yoda conditions are discouraged, use actual.get("data").get("whitelist") == None instead (SIM300)

Replace Yoda condition with actual.get("data").get("whitelist") == None


14276-14276: Comparison to None should be cond is None (E711)

Replace with cond is None


14276-14276: Yoda conditions are discouraged, use actual.get("data").get("whitelist") == None instead (SIM300)

Replace Yoda condition with actual.get("data").get("whitelist") == None


14723-14723: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


14756-14756: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


16837-16837: Yoda conditions are discouraged (SIM300)

Replace Yoda condition


16838-16838: Yoda conditions are discouraged (SIM300)

Replace Yoda condition


16870-16870: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


16904-16904: Yoda conditions are discouraged, use item["lookup"] == "case_insensitive_lookup" instead (SIM300)

Replace Yoda condition with item["lookup"] == "case_insensitive_lookup"


16912-16912: Yoda conditions are discouraged, use item["lookup"] == "case_insensitive_lookup" instead (SIM300)

Replace Yoda condition with item["lookup"] == "case_insensitive_lookup"


17093-17093: f-string without any placeholders (F541)

Remove extraneous f prefix


17104-17104: f-string without any placeholders (F541)

Remove extraneous f prefix


17115-17115: f-string without any placeholders (F541)

Remove extraneous f prefix


17128-17128: f-string without any placeholders (F541)

Remove extraneous f prefix


17138-17138: f-string without any placeholders (F541)

Remove extraneous f prefix


17147-17147: f-string without any placeholders (F541)

Remove extraneous f prefix


17164-17164: f-string without any placeholders (F541)

Remove extraneous f prefix


17170-17170: f-string without any placeholders (F541)

Remove extraneous f prefix


17176-17176: f-string without any placeholders (F541)

Remove extraneous f prefix


17196-17196: f-string without any placeholders (F541)

Remove extraneous f prefix


17200-17200: f-string without any placeholders (F541)

Remove extraneous f prefix


17206-17206: f-string without any placeholders (F541)

Remove extraneous f prefix


17217-17217: f-string without any placeholders (F541)

Remove extraneous f prefix


17234-17234: f-string without any placeholders (F541)

Remove extraneous f prefix


17247-17247: f-string without any placeholders (F541)

Remove extraneous f prefix


17252-17252: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


17260-17260: f-string without any placeholders (F541)

Remove extraneous f prefix


17266-17266: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


17274-17274: f-string without any placeholders (F541)

Remove extraneous f prefix


17280-17280: Use bool(...) instead of True if ... else False (SIM210)

Replace with `bool(...)


17306-17306: f-string without any placeholders (F541)

Remove extraneous f prefix


19125-19125: Comparison to None should be cond is None (E711)

Replace with cond is None


19166-19166: Comparison to None should be cond is None (E711)

Replace with cond is None


19180-19180: Comparison to None should be cond is None (E711)

Replace with cond is None


19721-19721: f-string without any placeholders (F541)

Remove extraneous f prefix


21018-21018: Local variable mock is assigned to but never used (F841)

Remove assignment to unused variable mock


21713-21713: Use context handler for opening files (SIM115)


21756-21756: Use context handler for opening files (SIM115)


21962-21962: Use context handler for opening files (SIM115)


22029-22029: Use context handler for opening files (SIM115)


22064-22064: Use context handler for opening files (SIM115)


22085-22085: Use context handler for opening files (SIM115)


22090-22090: Use context handler for opening files (SIM115)


22210-22210: Local variable payload is assigned to but never used (F841)

Remove assignment to unused variable payload


22311-22311: Loop control variable i not used within loop body (B007)

Rename unused i to _i


22394-22394: f-string without any placeholders (F541)

Remove extraneous f prefix


22429-22429: Comparison to None should be cond is None (E711)

Replace with cond is None


22429-22429: Yoda conditions are discouraged, use actual.get("data").get("whitelist") == None instead (SIM300)

Replace Yoda condition with actual.get("data").get("whitelist") == None


22484-22484: Use context handler for opening files (SIM115)


22518-22518: Comparison to None should be cond is None (E711)

Replace with cond is None


22518-22518: Yoda conditions are discouraged, use actual.get("data").get("whitelist") == None instead (SIM300)

Replace Yoda condition with actual.get("data").get("whitelist") == None


22544-22544: Comparison to None should be cond is None (E711)

Replace with cond is None


22544-22544: Yoda conditions are discouraged, use actual.get("data").get("whitelist") == None instead (SIM300)

Replace Yoda condition with actual.get("data").get("whitelist") == None


22549-22549: Use context handler for opening files (SIM115)


22784-22784: Avoid equality comparisons to False; use if not actual["data"]["logs"][1]["translate_responses"]: for false checks (E712)

Replace with not actual["data"]["logs"][1]["translate_responses"]


22785-22785: Avoid equality comparisons to False; use if not actual["data"]["logs"][1]["translate_actions"]: for false checks (E712)

Replace with not actual["data"]["logs"][1]["translate_actions"]


22801-22801: f-string without any placeholders (F541)

Remove extraneous f prefix


23047-23047: f-string without any placeholders (F541)

Remove extraneous f prefix


23099-23099: f-string without any placeholders (F541)

Remove extraneous f prefix


23492-23492: Unnecessary call to encode as UTF-8 (UP012)

Rewrite as bytes literal


23523-23523: Unnecessary call to encode as UTF-8 (UP012)

Rewrite as bytes literal


23634-23635: Replace yield over for loop with yield from (UP028)

Replace with yield from


23757-23757: f-string without any placeholders (F541)

Remove extraneous f prefix


23771-23771: f-string without any placeholders (F541)

Remove extraneous f prefix


23864-23864: Local variable passwrd_change_response is assigned to but never used (F841)

Remove assignment to unused variable passwrd_change_response


23944-23944: Local variable regsiter_response is assigned to but never used (F841)

Remove assignment to unused variable regsiter_response


23976-23976: Local variable regsiter_response is assigned to but never used (F841)

Remove assignment to unused variable regsiter_response


24181-24181: Avoid equality comparisons to False; use if not actual["success"]: for false checks (E712)

Replace with not actual["success"]


24185-24185: f-string without any placeholders (F541)

Remove extraneous f prefix

Gitleaks
kairon/shared/constants.py

51-52: Identified a HashiCorp Terraform password field, risking unauthorized infrastructure configuration and security breaches. (hashicorp-tf-password)

tests/integration_test/services_test.py

235-235: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


9054-9054: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)


9098-9098: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)


9753-9753: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)


10082-10082: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)


10099-10099: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)


17289-17289: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18635-18635: Identified a Slack Bot token, which may compromise bot integrations and communication channel security. (slack-bot-token)


18681-18681: Identified a Slack Bot token, which may compromise bot integrations and communication channel security. (slack-bot-token)


18703-18703: Identified a Slack Bot token, which may compromise bot integrations and communication channel security. (slack-bot-token)


18636-18636: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18638-18638: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18659-18659: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18704-18704: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18706-18706: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18854-18854: Identified a Slack Bot token, which may compromise bot integrations and communication channel security. (slack-bot-token)


18855-18855: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


18857-18857: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


19572-19572: Identified a Slack Bot token, which may compromise bot integrations and communication channel security. (slack-bot-token)


21851-21851: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


21879-21879: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


21930-21930: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


21958-21958: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


21996-21996: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


22023-22023: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


23252-23252: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key)


23898-23898: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (jwt)

Additional comments not posted (21)
kairon/shared/chat/broadcast/constants.py (2)

7-7: New enum value added: resend

The addition of resend to MessageBroadcastLogType aligns with the new functionality for resending broadcasts. This is a necessary update to support logging for the new feature.


17-20: New error codes added to MetaErrorCodes

The addition of specific error codes (message_undeliverable, recipient_sender_same, payment_error) is appropriate for handling distinct error scenarios in message broadcasting, particularly in the context of resending messages. These codes will facilitate more precise error handling and reporting.

kairon/events/definitions/scheduled_base.py (2)

18-19: Added handling for resend_broadcast event type

The addition of resend_broadcast to the dictionary of request implementations is necessary for the new feature to function correctly. This update ensures that the system can handle resend requests appropriately.


39-40: Abstract method _resend_broadcast added

This new abstract method is essential for subclasses to implement the resend functionality. It's a good practice to define such behaviors in the base class, ensuring consistency across different implementations.

Tools
Ruff

39-39: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/shared/constants.py (1)

85-85: New event request type added: resend_broadcast

The addition of resend_broadcast to EventRequestType is crucial for supporting the new resend functionality. This ensures that the application can correctly recognize and handle resend broadcast requests.

kairon/events/definitions/message_broadcast.py (5)

53-53: Added handling for is_resend parameter in execute method

The introduction of the is_resend parameter allows the method to differentiate between initial sends and resends, which is crucial for the new functionality. This change is well-implemented and necessary for the feature.


57-61: Conditional handling based on is_resend

This logic correctly handles the flow for resending broadcasts versus sending new ones. It's a good implementation that ensures the correct method is called based on the is_resend status.


68-69: Logging status after broadcasting

The insertion of the status into the webhook and logging the event are crucial for tracking the outcome of the broadcast, especially in the context of resends. This is a necessary update.


107-112: Implementing resend logic in _resend_broadcast

This method provides the necessary logic to handle resending of broadcasts. The use of Utility.request_event_server to trigger the resend is appropriate and aligns with existing patterns.

Tools
Ruff

107-107: typing.Text is deprecated, use str (UP019)

Replace with str


148-157: Retrieving configuration for resending

The method __retrieve_config has been updated to handle the resend scenario, which involves fetching specific configurations and logging the status. This is an essential part of the resend functionality.

Tools
Ruff

148-148: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/shared/channels/broadcast/whatsapp.py (2)

11-11: Updated imports to include MetaErrorCodes

The addition of MetaErrorCodes to the imports is necessary for handling specific error scenarios related to message broadcasting on WhatsApp. This change is relevant and well-placed.


46-48: Comprehensive updates to support resend functionality

The changes in methods like send, __send_using_pyscript, __send_using_configuration, and resend_broadcast are extensive and crucial for implementing the resend functionality on the WhatsApp channel. These updates ensure that messages can be resent under the appropriate conditions and that errors are handled correctly.

Also applies to: 50-63, 96-127, 136-161

kairon/shared/chat/broadcast/processor.py (3)

116-118: Method implementation is correct.

The method get_reference_id_from_broadcasting_logs correctly retrieves the reference ID from broadcasting logs based on the given event ID.


121-125: Update to consider is_resend is appropriate.

The updates to extract_message_ids_from_broadcast_logs to consider the is_resend flag for setting log_type are correctly implemented. This ensures that the method can handle different scenarios based on whether the message is being resent or not.

Tools
Ruff

121-121: typing.Text is deprecated, use str (UP019)

Replace with str


182-185: Correct implementation of is_resend handling in webhook status insertion.

The method insert_status_received_on_channel_webhook correctly uses the is_resend flag to process broadcast logs. This is an essential update for handling different broadcast scenarios.

Tools
Ruff

182-182: typing.Text is deprecated, use str (UP019)

Replace with str


182-182: typing.Text is deprecated, use str (UP019)

Replace with str

kairon/api/app/routers/bot/channels.py (1)

185-196: New endpoint for resending broadcasts is correctly implemented.

The new endpoint resend_message_broadcast_event correctly handles the resending of message broadcasts by enqueuing the appropriate event type. This is a crucial addition for the resend functionality.

Tools
Ruff

188-188: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)

tests/integration_test/services_test.py (5)

2033-2056: Function implementation looks good and is well-documented.


2059-2081: Resend functionality test is comprehensive and checks all necessary conditions.


2083-2107: Listing broadcast messages test is implemented correctly.


2110-2119: Deletion functionality test is thorough and correctly implemented.


2121-2121: Function to test client configuration retrieval based on IP is well-implemented.

Comment on lines 85 to 91
is_resend = kwargs.pop("is_resend", False)
event_completion_states = [] if is_resend else [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value,
MessageBroadcastLogType.resend.value,
MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
try:
if is_new_log:
if is_new_log and not is_resend:
Copy link

Choose a reason for hiding this comment

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

Refactor the event logging logic and improve exception handling.

The method can be simplified by directly using set operations and improving the clarity of exception handling:

- is_new_log = log_type in {MessageBroadcastLogType.send.value,
-                           MessageBroadcastLogType.resend.value,
-                           MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
+ is_new_log = log_type in {MessageBroadcastLogType.send.value, MessageBroadcastLogType.resend.value, MessageBroadcastLogType.self.value} or kwargs.get("is_new_log", False)

- if is_new_log and not is_resend:
-     raise DoesNotExist()
+ if not is_new_log or is_resend:
+     raise DoesNotExist() from None

This change clarifies the conditions under which the exception is raised and uses the correct form of raising exceptions with context.

Committable suggestion was skipped due to low confidence.

Comment on lines 21 to 24
def get_settings(notification_id: Text, bot: Text, **kwargs):
try:
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=True).get()
status = False if kwargs.get("is_resend", False) else True
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
Copy link

Choose a reason for hiding this comment

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

Optimize the condition check for is_resend.

Instead of using a ternary operation to set the status, use direct negation:

- status = False if kwargs.get("is_resend", False) else True
+ status = not kwargs.get("is_resend", False)

This simplifies the logic and improves readability.

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
def get_settings(notification_id: Text, bot: Text, **kwargs):
try:
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=True).get()
status = False if kwargs.get("is_resend", False) else True
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
def get_settings(notification_id: Text, bot: Text, **kwargs):
try:
status = not kwargs.get("is_resend", False)
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
Tools
Ruff

21-21: typing.Text is deprecated, use str (UP019)

Replace with str


21-21: typing.Text is deprecated, use str (UP019)

Replace with str


23-23: Use not ... instead of False if ... else True (SIM211)

Replace with not ...

logs = MessageBroadcastProcessor.get_broadcast_logs(bot)
assert len(logs[0]) == logs[1] == 3
logs[0][0].pop("timestamp")
reference_id = logs[0][0].get("reference_id")
Copy link

Choose a reason for hiding this comment

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

Remove unused variable.

The variable reference_id is assigned but never used. Consider removing it if it's not needed.

- reference_id = logs[0][0].get("reference_id")
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
reference_id = logs[0][0].get("reference_id")
Tools
Ruff

2340-2340: Local variable reference_id is assigned to but never used (F841)

Remove assignment to unused variable reference_id

@@ -23,8 +23,6 @@

os.environ["system_file"] = "./tests/testing_data/system.yaml"
Copy link

Choose a reason for hiding this comment

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

Use capitalized environment variable name.

It's a common convention to use uppercase for environment variable names.

- os.environ["system_file"] = "./tests/testing_data/system.yaml"
+ os.environ["SYSTEM_FILE"] = "./tests/testing2data/system.yaml"

Committable suggestion was skipped due to low confidence.

Tools
Ruff

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file (SIM112)

Replace system_file with SYSTEM_FILE

Comment on lines +2018 to +2019
response = client.post(
f"/api/bot/{pytest.bot}/channels/whatsapp/360dialog/onboarding?clientId=kairon&client=sdfgh5678&channels=['sdfghjk678']",
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

Correct the URL encoding for query parameters.

The channels query parameter in the URL is not correctly URL-encoded. Ensure that special characters like square brackets [ and ] are properly encoded.

  • Location:
    • tests/integration_test/services_test.py, lines around 2018-2019

Suggested Correction:

response = client.post(
    f"/api/bot/{pytest.bot}/channels/whatsapp/360dialog/onboarding?clientId=kairon&client=sdfgh5678&channels=%5B'sdfghjk678'%5D",
    headers={
        "Authorization": pytest.token_type + " " + pytest.access_token
    },
)
Analysis chain

Verify the correctness of the API endpoint and query parameters.

The URL in the POST request seems to have a typo or incorrect format. Ensure that the query parameters are correctly encoded and the URL is structured properly.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the correctness of the API endpoint and query parameters.

# Test: Search for the endpoint usage. Expect: Only occurances of the correct endpoint.
rg --type python $'http://kairon-api.digite.com/api/bot/whatsapp/{pytest.bot}/e'

Length of output: 271



Script:

#!/bin/bash
# Description: Verify the correctness of the API endpoint and query parameters.

# Test: Search for the endpoint usage. Expect: Only occurrences of the correct endpoint.
# Adjusting the search pattern to avoid regex interpretation issues.
rg --type python 'http://kairon-api.digite.com/api/bot/whatsapp/\{pytest.bot\}/e'

Length of output: 114



Script:

#!/bin/bash
# Description: Verify the correctness of the API endpoint and query parameters.

# Test: Search for the endpoint usage. Expect: Only occurrences of the correct endpoint.
# Adjusting the search pattern to avoid regex interpretation issues and correctly filter Python files.
rg 'http://kairon-api.digite.com/api/bot/whatsapp/\{pytest.bot\}/e' --glob '*.py'

Length of output: 419



Script:

#!/bin/bash
# Description: Verify the correctness of the API endpoint and query parameters.

# Display the specific lines containing the endpoint in the test file to verify the format.
rg 'http://kairon-api.digite.com/api/bot/whatsapp/\{pytest.bot\}/e' --glob '*.py' -A 5 -B 5

Length of output: 2560



Script:

#!/bin/bash
# Description: Verify the correctness of the API endpoint and query parameters.

# Search for the POST request in the test file to verify the URL and query parameters.
rg 'client.post' tests/integration_test/services_test.py -A 5 -B 5

Length of output: 201938

is_resend = kwargs.get('is_resend')
recipients = kwargs.get('recipients')

pattern = r"contacts = \[.*?\]"
Copy link
Collaborator

Choose a reason for hiding this comment

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

need to discuss

msg_id = log["message_id"]
broadcast_log = broadcast_logs[msg_id]
if log['errors']:
if log['errors'][0].get('code') in [MetaErrorCodes.message_undeliverable.value,
Copy link
Collaborator

Choose a reason for hiding this comment

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

need to discuss

numbers_sent.append(broadcast_log['recipient'])

numbers_to_exclude = numbers_sent + numbers_failed
numbers_to_send = [number for number in all_numbers if number not in numbers_to_exclude]
Copy link
Collaborator

Choose a reason for hiding this comment

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

check any better way to iterate

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: 9

Outside diff range and nitpick comments (1)
kairon/shared/chat/broadcast/processor.py (1)

Line range hint 168-192: Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def __add_broadcast_logs_status_and_errors(reference_id: Text, campaign_name: Text, broadcast_logs: Dict[Text, Document], resend_count: int = 0):
+    def __add_broadcast_logs_status_and_errors(reference_id: str, campaign_name: str, broadcast_logs: Dict[str, Document], resend_count: int = 0):
Tools
Ruff

195-195: typing.Text is deprecated, use str

Replace with str

(UP019)


195-195: typing.Text is deprecated, use str

Replace with str

(UP019)


202-202: typing.Text is deprecated, use str

Replace with str

(UP019)


202-202: typing.Text is deprecated, use str

Replace with str

(UP019)

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 30c1027 and bab1829.

Files selected for processing (9)
  • kairon/api/app/routers/bot/channels.py (1 hunks)
  • kairon/events/definitions/message_broadcast.py (3 hunks)
  • kairon/events/definitions/scheduled_base.py (2 hunks)
  • kairon/shared/channels/broadcast/whatsapp.py (3 hunks)
  • kairon/shared/chat/broadcast/constants.py (1 hunks)
  • kairon/shared/chat/broadcast/processor.py (5 hunks)
  • system.yaml (1 hunks)
  • tests/testing_data/system.yaml (1 hunks)
  • tests/unit_test/events/events_test.py (7 hunks)
Files not summarized due to errors (1)
  • tests/unit_test/events/events_test.py: Error: Message exceeds token limit
Files skipped from review due to trivial changes (2)
  • system.yaml
  • tests/testing_data/system.yaml
Files skipped from review as they are similar to previous changes (2)
  • kairon/shared/channels/broadcast/whatsapp.py
  • kairon/shared/chat/broadcast/constants.py
Additional context used
Ruff
kairon/events/definitions/scheduled_base.py

21-21: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


35-35: typing.Text is deprecated, use str

Replace with str

(UP019)


39-39: typing.Text is deprecated, use str

Replace with str

(UP019)


43-43: typing.Text is deprecated, use str

Replace with str

(UP019)

kairon/events/definitions/message_broadcast.py

104-104: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


106-106: typing.Text is deprecated, use str

Replace with str

(UP019)


116-116: typing.Text is deprecated, use str

Replace with str

(UP019)


147-147: typing.Text is deprecated, use str

Replace with str

(UP019)

kairon/shared/chat/broadcast/processor.py

21-21: typing.Text is deprecated, use str

Replace with str

(UP019)


21-21: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


129-129: typing.Text is deprecated, use str

Replace with str

(UP019)


144-144: typing.Text is deprecated, use str

Replace with str

(UP019)


168-168: typing.Text is deprecated, use str

Replace with str

(UP019)


168-168: typing.Text is deprecated, use str

Replace with str

(UP019)


169-169: typing.Text is deprecated, use str

Replace with str

(UP019)


195-195: typing.Text is deprecated, use str

Replace with str

(UP019)


195-195: typing.Text is deprecated, use str

Replace with str

(UP019)


202-202: typing.Text is deprecated, use str

Replace with str

(UP019)


202-202: typing.Text is deprecated, use str

Replace with str

(UP019)

kairon/api/app/routers/bot/channels.py

188-188: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

tests/unit_test/events/events_test.py

24-24: Use capitalized environment variable SYSTEM_FILE instead of system_file

Replace system_file with SYSTEM_FILE

(SIM112)

Additional comments not posted (6)
kairon/shared/chat/broadcast/processor.py (2)

130-141: Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def extract_message_ids_from_broadcast_logs(reference_id: Text):
+    def extract_message_ids_from_broadcast_logs(reference_id: str):

Likely invalid or redundant comment.


115-117: Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def get_reference_id_from_broadcasting_logs(event_id: Text):
+    def get_reference_id_from_broadcasting_logs(event_id: str):

Likely invalid or redundant comment.

tests/unit_test/events/events_test.py (4)

1282-1283: Ensure Consistency in Log Data

The log data for template_params and template_name should be consistent with the rest of the log structure. Consider verifying that all logs have these fields correctly populated.


2133-2400: Ensure Proper Handling of Resend Broadcast

The function test_execute_message_broadcast_with_resend_broadcast_with_static_values tests the resend broadcast functionality with static values. Ensure that the resend logic is correctly implemented and the logs are properly handled.


2401-2677: Ensure Proper Handling of Resend Broadcast

The function test_execute_message_broadcast_with_resend_broadcast_with_dynamic_values tests the resend broadcast functionality with dynamic values. Ensure that the resend logic is correctly implemented and the logs are properly handled.


Line range hint 2678-3030: Ensure Proper Handling of Resend Broadcast with Meta Error Codes

The function test_execute_message_broadcast_with_resend_broadcast_with_meta_error_codes_to_skip tests the resend broadcast functionality with meta error codes to skip. Ensure that the resend logic is correctly implemented and the logs are properly handled.

Comment on lines +39 to +40
def _resend_broadcast(self, msg_broadcast_id: Text):
raise NotImplementedError("Provider not implemented")
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def _resend_broadcast(self, msg_broadcast_id: Text):
+    def _resend_broadcast(self, msg_broadcast_id: str):
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
def _resend_broadcast(self, msg_broadcast_id: Text):
raise NotImplementedError("Provider not implemented")
def _resend_broadcast(self, msg_broadcast_id: str):
raise NotImplementedError("Provider not implemented")
Tools
Ruff

39-39: typing.Text is deprecated, use str

Replace with str

(UP019)

Comment on lines +18 to +19
EventRequestType.update_schedule.value: self._update_schedule,
EventRequestType.resend_broadcast.value: self._resend_broadcast
Copy link

Choose a reason for hiding this comment

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

Remove .keys() for dictionary lookup.

Use if event_request_type not in request_implementation instead of if event_request_type not in request_implementation.keys() for better performance.

-        if event_request_type not in request_implementation.keys():
+        if event_request_type not in request_implementation:
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
EventRequestType.update_schedule.value: self._update_schedule,
EventRequestType.resend_broadcast.value: self._resend_broadcast
EventRequestType.update_schedule.value: self._update_schedule,
EventRequestType.resend_broadcast.value: self._resend_broadcast
if event_request_type not in request_implementation:

Comment on lines +53 to +58
is_resend = kwargs.get('is_resend', False)
try:
config, reference_id = self.__retrieve_config(event_id)
config, reference_id = self.__retrieve_config(event_id, is_resend)
broadcast = MessageBroadcastFactory.get_instance(config["connector_type"]).from_config(config, event_id, reference_id)
recipients = broadcast.get_recipients()
broadcast.send(recipients)
if is_resend:
broadcast.resend_broadcast()
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str and approve changes.

typing.Text is deprecated. Use str instead.

-    def execute(self, event_id: Text, **kwargs):
+    def execute(self, event_id: str, **kwargs):

The addition of the is_resend parameter is consistent with the new functionality.

Committable suggestion was skipped due to low confidence.

Comment on lines +106 to +114
def _resend_broadcast(self, msg_broadcast_id: Text):
try:
payload = {'bot': self.bot, 'user': self.user,
"event_id": msg_broadcast_id, "is_resend": True}
Utility.request_event_server(EventClass.message_broadcast, payload)
return msg_broadcast_id
except Exception as e:
logger.error(e)
raise e
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def _resend_broadcast(self, msg_broadcast_id: Text):
+    def _resend_broadcast(self, msg_broadcast_id: str):
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
def _resend_broadcast(self, msg_broadcast_id: Text):
try:
payload = {'bot': self.bot, 'user': self.user,
"event_id": msg_broadcast_id, "is_resend": True}
Utility.request_event_server(EventClass.message_broadcast, payload)
return msg_broadcast_id
except Exception as e:
logger.error(e)
raise e
def _resend_broadcast(self, msg_broadcast_id: str):
try:
payload = {'bot': self.bot, 'user': self.user,
"event_id": msg_broadcast_id, "is_resend": True}
Utility.request_event_server(EventClass.message_broadcast, payload)
return msg_broadcast_id
except Exception as e:
logger.error(e)
raise e
Tools
Ruff

106-106: typing.Text is deprecated, use str

Replace with str

(UP019)

Comment on lines +147 to +156
def __retrieve_config(self, event_id: Text, is_resend: bool):

reference_id = MessageBroadcastProcessor.get_reference_id_from_broadcasting_logs(event_id) \
if is_resend else ObjectId().__str__()
config = MessageBroadcastProcessor.get_settings(event_id, self.bot, is_resend=is_resend)
bot_settings = MongoProcessor.get_bot_settings(self.bot, self.user)
config["pyscript_timeout"] = bot_settings["dynamic_broadcast_execution_timeout"]
MessageBroadcastProcessor.add_event_log(
self.bot, MessageBroadcastLogType.common.value, reference_id, user=self.user, config=config,
status=EVENT_STATUS.INPROGRESS.value, event_id=event_id, is_new_log=True
status=EVENT_STATUS.INPROGRESS.value, event_id=event_id, is_new_log=True, is_resend=is_resend
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str and approve changes.

typing.Text is deprecated. Use str instead.

-    def __retrieve_config(self, event_id: Text, is_resend: bool):
+    def __retrieve_config(self, event_id: str, is_resend: bool):

The addition of the is_resend parameter is consistent with the new functionality.

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
def __retrieve_config(self, event_id: Text, is_resend: bool):
reference_id = MessageBroadcastProcessor.get_reference_id_from_broadcasting_logs(event_id) \
if is_resend else ObjectId().__str__()
config = MessageBroadcastProcessor.get_settings(event_id, self.bot, is_resend=is_resend)
bot_settings = MongoProcessor.get_bot_settings(self.bot, self.user)
config["pyscript_timeout"] = bot_settings["dynamic_broadcast_execution_timeout"]
MessageBroadcastProcessor.add_event_log(
self.bot, MessageBroadcastLogType.common.value, reference_id, user=self.user, config=config,
status=EVENT_STATUS.INPROGRESS.value, event_id=event_id, is_new_log=True
status=EVENT_STATUS.INPROGRESS.value, event_id=event_id, is_new_log=True, is_resend=is_resend
def __retrieve_config(self, event_id: str, is_resend: bool):
reference_id = MessageBroadcastProcessor.get_reference_id_from_broadcasting_logs(event_id) \
if is_resend else ObjectId().__str__()
config = MessageBroadcastProcessor.get_settings(event_id, self.bot, is_resend=is_resend)
bot_settings = MongoProcessor.get_bot_settings(self.bot, self.user)
config["pyscript_timeout"] = bot_settings["dynamic_broadcast_execution_timeout"]
MessageBroadcastProcessor.add_event_log(
self.bot, MessageBroadcastLogType.common.value, reference_id, user=self.user, config=config,
status=EVENT_STATUS.INPROGRESS.value, event_id=event_id, is_new_log=True, is_resend=is_resend
Tools
Ruff

147-147: typing.Text is deprecated, use str

Replace with str

(UP019)

Comment on lines +196 to +199
broadcast_logs, resend_count = MessageBroadcastProcessor.extract_message_ids_from_broadcast_logs(reference_id)
if broadcast_logs:
MessageBroadcastProcessor.__add_broadcast_logs_status_and_errors(reference_id, broadcast_name, broadcast_logs)
MessageBroadcastProcessor.__add_broadcast_logs_status_and_errors(reference_id, broadcast_name,
broadcast_logs, resend_count)
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str.

typing.Text is deprecated. Use str instead.

-    def insert_status_received_on_channel_webhook(reference_id: Text, broadcast_name: Text):
+    def insert_status_received_on_channel_webhook(reference_id: str, broadcast_name: str):

Committable suggestion was skipped due to low confidence.

Comment on lines +21 to +24
def get_settings(notification_id: Text, bot: Text, **kwargs):
try:
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=True).get()
status = not kwargs.get("is_resend", False)
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str and approve changes.

typing.Text is deprecated. Use str instead.

-    def get_settings(notification_id: Text, bot: Text, **kwargs):
+    def get_settings(notification_id: str, bot: str, **kwargs):

The addition of the is_resend parameter is consistent with the new functionality.

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
def get_settings(notification_id: Text, bot: Text, **kwargs):
try:
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=True).get()
status = not kwargs.get("is_resend", False)
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
def get_settings(notification_id: str, bot: str, **kwargs):
try:
status = not kwargs.get("is_resend", False)
settings = MessageBroadcastSettings.objects(id=notification_id, bot=bot, status=status).get()
Tools
Ruff

21-21: typing.Text is deprecated, use str

Replace with str

(UP019)


21-21: typing.Text is deprecated, use str

Replace with str

(UP019)

Comment on lines 84 to +88
def add_event_log(bot: Text, log_type: Text, reference_id: Text = None, status: Text = None, **kwargs):
event_completion_states = [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value, MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
is_resend = kwargs.pop("is_resend", False)
event_completion_states = [] if is_resend else [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value,
MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
Copy link

Choose a reason for hiding this comment

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

Replace typing.Text with str and approve changes.

typing.Text is deprecated. Use str instead.

-    def add_event_log(bot: Text, log_type: Text, reference_id: Text = None, status: Text = None, **kwargs):
+    def add_event_log(bot: str, log_type: str, reference_id: str = None, status: str = None, **kwargs):

The addition of the is_resend parameter is consistent with the new functionality.

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
def add_event_log(bot: Text, log_type: Text, reference_id: Text = None, status: Text = None, **kwargs):
event_completion_states = [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value, MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
is_resend = kwargs.pop("is_resend", False)
event_completion_states = [] if is_resend else [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value,
MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
def add_event_log(bot: str, log_type: str, reference_id: str = None, status: str = None, **kwargs):
is_resend = kwargs.pop("is_resend", False)
event_completion_states = [] if is_resend else [EVENT_STATUS.FAIL.value, EVENT_STATUS.COMPLETED.value]
is_new_log = log_type in {MessageBroadcastLogType.send.value,
MessageBroadcastLogType.self.value} or kwargs.pop("is_new_log", None)
Tools
Ruff

84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)


84-84: typing.Text is deprecated, use str

Replace with str

(UP019)

@router.post("/broadcast/message/resend/{msg_broadcast_id}", response_model=Response)
async def resend_message_broadcast_event(
msg_broadcast_id: str,
current_user: User = Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS)
Copy link

Choose a reason for hiding this comment

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

Avoid function call Security in argument defaults.

Move the Security function call inside the function.

-        current_user: User = Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS)
+        current_user: User = Depends(lambda: Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS))
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
current_user: User = Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS)
current_user: User = Depends(lambda: Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS))
Tools
Ruff

188-188: Do not perform function call Security in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

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.

None yet

2 participants