Skip to content

Commit

Permalink
Implement Cwwhatsapp connector
Browse files Browse the repository at this point in the history
  • Loading branch information
sysang committed Sep 9, 2022
1 parent 8967008 commit 7c9f36d
Show file tree
Hide file tree
Showing 12 changed files with 570 additions and 37 deletions.
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ install_ssl_certificate:
# touch file2

patch_chatwoot:
sudo docker cp incoming_message_service.rb rasachatbot-sidekiq-1:/app/app/services/telegram/incoming_message_service.rb
sudo docker cp telegram.rb rasachatbot-sidekiq-1:/app/app/models/channel/telegram.rb
docker cp incoming_message_service.rb rasachatbot-sidekiq-1:/app/app/services/telegram/incoming_message_service.rb
docker cp telegram.rb rasachatbot-sidekiq-1:/app/app/models/channel/telegram.rb
docker cp incoming_message_base_service.rb rasachatbot-sidekiq-1:/app/app/services/whatsapp/incoming_message_base_service.rb
docker cp whatsapp_cloud_service.rb rasachatbot-sidekiq-1:/app/app/services/whatsapp/providers/whatsapp_cloud_service.rb

sidekig:
make patch_chatwoot
sudo docker restart rasachatbot-sidekiq-1
sudo docker logs --tail=100 -f rasachatbot-sidekiq-1
docker restart rasachatbot-sidekiq-1
docker logs --tail=100 -f rasachatbot-sidekiq-1
51 changes: 36 additions & 15 deletions botserver-action/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,24 @@ def name(self) -> Text:
return "botacts_utter_inform_searching_inprogress"

def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
dispatcher.utter_message(response='utter_inform_searching_inprogress')
slots = tracker.slots
query_payload = slots.get('search_result_query', '')
if not query_payload:
botmemo_booking_progress = FSMBotmemeBookingProgress(slots)
bkinfo = botmemo_booking_progress.form
data = {
'destination': bkinfo.get('bkinfo_area'),
'checkin': bkinfo.get('bkinfo_checkin_time'),
'staying': bkinfo.get('bkinfo_duration') if bkinfo.get('bkinfo_checkin_time') != bkinfo.get('bkinfo_duration') else '',
'bed_type': bkinfo.get('bkinfo_bed_type'),
'max_price': bkinfo.get('bkinfo_price'),
}
message = """
I'm going to search for hotel room based on your information, destination: {destination}, check-in: {checkin}, staying: {staying}, bed type: {bed_type}, max price: {max_price}. It takes for a while, hold on!
""".format(**data)

dispatcher.utter_message(text=message)
# dispatcher.utter_message(response='utter_inform_searching_inprogress')

return [FollowupAction(name='botacts_search_hotel_rooms')]

Expand Down Expand Up @@ -218,8 +235,10 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:

web_channels = ['socketio', 'rasa', 'cwwebsite']
telegram_channels = ['telegram', 'cwtelegram']
fb_channels = ['facebook', 'cwfacebook']
whatsapp_channels = ['whatsapp', 'cwwhatsapp']

limit_num = 5 if channel == 'facebook' else 2 if channel in web_channels else 1
limit_num = 5 if channel in fb_channels else 2 if channel in web_channels else 1


if bkinfo_orderby:
Expand Down Expand Up @@ -287,12 +306,14 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
total_rooms = reduce(lambda x, y: x+y, hotels.values())
room_num = len(total_rooms)

if SortbyDictionary.SORTBY_REVIEW_SCORE == bkinfo_orderby:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_review_score", room_num=room_num)
elif SortbyDictionary.SORTBY_PRICE == bkinfo_orderby:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_price", room_num=room_num)
else:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_popularity", room_num=room_num)
# do not repeat if user keep exploring the same filter
if page_number == 1:
if SortbyDictionary.SORTBY_REVIEW_SCORE == bkinfo_orderby:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_review_score", room_num=room_num)
elif SortbyDictionary.SORTBY_PRICE == bkinfo_orderby:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_price", room_num=room_num)
else:
dispatcher.utter_message(response="utter_about_to_show_hotel_list_by_popularity", room_num=room_num)

start, end, remains = paginate(index=page_number, limit=limit_num, total=room_num)
logger.info('[INFO] paginating search result by index=%s, limit=%s, total=%s -> (%s, %s, %s)', page_number, limit_num, room_num, start, end, remains)
Expand Down Expand Up @@ -341,7 +362,7 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
fb_buttons = []
teleg_buttons = []

if channel == 'facebook':
if channel in fb_channels:

if photos_presentation_url:
fb_buttons.append({
Expand Down Expand Up @@ -369,7 +390,7 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
elif channel in web_channels:
room_description = "⚑ {room_display_index}: {room_name}, {room_bed_type}, ☝ {room_min_price:.2f} {room_price_currency}." . format(**data)
room_photos = "To view room photos: \n{photos_url}" . format(**data)
hotel_description = "❖ More information: {hotel_name} ★★★ Score: {review_score} ★★★ Address: {address}, {city}, {country}, {nearest_beach_name}" . format(**data)
hotel_description = "❖ Hotel information: {hotel_name} ★★★ Score: {review_score} ★★★ Address: {address}, {city}, {country}, {nearest_beach_name}" . format(**data)
# button = { "title": 'Pick Room ⚑ {room_display_index}'.format(**data), "payload": btn_payload}
button = { "title": room_description, "payload": btn_payload}

Expand All @@ -380,8 +401,8 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:

logger.info("[INFO] send message to web channel, hotel_description: %s", hotel_description)

elif channel in telegram_channels:
hotel_description = "❖ More information: {hotel_name} ★★★ Score: {review_score} ★★★ Address: {address}, {city}, {country}, {nearest_beach_name}" . format(**data)
elif channel in telegram_channels or channel in whatsapp_channels:
hotel_description = "❖ Hotel information: {hotel_name} ★★★ Score: {review_score} ★★★ Address: {address}, {city}, {country}, {nearest_beach_name}" . format(**data)

button = { "title": 'Pick Room ⚑ {room_display_index}'.format(**data), "payload": btn_payload}
teleg_buttons.append(button)
Expand All @@ -400,7 +421,7 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
else:
dispatcher.utter_message(text=hotel_description)

logger.info("[INFO] send message to telegram channel, room_description: ", room_description)
logger.info("[INFO] send message to telegram/whatsapp channel, room_description: %s", room_description)

# End of `for room in total_rooms[start:end]:`

Expand All @@ -418,7 +439,7 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
next_button_title = '❯❯ next {remains} room(s)'.format(**query)
next_button_payload = '/{intent}{next}'.format(**query)

if channel == 'facebook':
if channel in fb_channels:
fb_buttons = []

if query.get('prev'):
Expand All @@ -435,7 +456,7 @@ async def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain:
buttons.append({'title': next_button_title, 'payload': next_button_payload})
dispatcher.utter_message(response="utter_instruct_to_choose_room", buttons=buttons)

elif channel in telegram_channels:
elif channel in telegram_channels or channel in whatsapp_channels:
if query.get('prev'):
teleg_buttons.append({'title': prev_button_title, 'payload': prev_button_payload})
if query.get('next'):
Expand Down
39 changes: 26 additions & 13 deletions botserver-app/addons/channels/chatwoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from .cwwebsite_output import CwwebsiteOutput
from .cwtelegram_output import CwteltegramOutput
from .cwwhatsapp_output import CwwhatsappOutput


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -62,24 +63,25 @@ def redis_check_cache(data):
def create_handler(message, chatwoot_url, cfg, on_new_message) -> Callable:

def select_output_channel(channel, chatwoot_url, cfg, **kwargs):
out_channel = None
if channel == 'cwwebsite':
out_channel = CwwebsiteOutput(
chatwoot_url=chatwoot_url,
bot_token=cfg.get("bot_token"),
botagent_account_id=cfg.get("botagent_account_id"),
conversation_id=kwargs.get("conversation_id"),
)
output_channel_cls = None

if channel == 'cwwebsite':
output_channel_cls = CwwebsiteOutput
elif channel == 'cwtelegram':
out_channel = CwteltegramOutput(
output_channel_cls = CwteltegramOutput
elif channel == 'cwwhatsapp':
output_channel_cls = CwwhatsappOutput

if output_channel_cls:
return output_channel_cls(
chatwoot_url=chatwoot_url,
bot_token=cfg.get("bot_token"),
botagent_account_id=cfg.get("botagent_account_id"),
conversation_id=kwargs.get("conversation_id"),
)

return out_channel

return None

async def process_message() -> None:
logger.info('[DEBUG] (process_message) message: %s', message)
Expand Down Expand Up @@ -141,21 +143,24 @@ def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> InputChanne
logger.info('[INFO] chatwoot connector (channel), from_credentials: %s', credentials)

return cls(
credentials.get("chatwoot_url"),
credentials.get("website"),
credentials.get("telegram"),
chatwoot_url=credentials.get("chatwoot_url"),
website=credentials.get("website"),
telegram=credentials.get("telegram"),
whatsapp=credentials.get("whatsapp"),
)

def __init__(
self,
chatwoot_url,
website: Dict[Text, Any],
telegram: Dict[Text, Any],
whatsapp: Dict[Text, Any],
) -> None:

self.chatwoot_url = chatwoot_url
self.website = website
self.telegram = telegram
self.whatsapp = whatsapp

def blueprint(
self, on_new_message: Callable[[UserMessage], Awaitable[None]]
Expand Down Expand Up @@ -235,6 +240,14 @@ async def webhook(request: Request) -> HTTPResponse:
ctx_cfg=json.dumps(self.telegram),
)

custom_webhook.add_route(
handler=webhook,
uri="/cwwhatsapp",
methods=["POST"],
ctx_chatwoot_url=self.chatwoot_url,
ctx_cfg=json.dumps(self.whatsapp),
)

return custom_webhook


2 changes: 2 additions & 0 deletions botserver-app/addons/channels/cwwebsite_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from typing import Text, Dict, Any, Optional, Callable, Awaitable, NoReturn, List, Iterable

from rasa.core.channels.channel import OutputChannel


logger = logging.getLogger(__name__)

Expand Down
Loading

0 comments on commit 7c9f36d

Please sign in to comment.