├── LICENSE ├── README.md ├── df_response_lib.py └── facebook_template_lib.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Satish Pandey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Dialogflow Fulfillment Webhook Response Library in Python 2 | 3 | This library simplifies the JSON response building in Python for Dialogflow fulfillment. 4 | 5 | Using this libray you can build the JSON objects with few line. 6 | 7 | **Supported Platforms** - Actions on Google, Facebook Messenger and Telegram 8 | 9 | **Update** - We have published a tutorial to create a basic webhook in Python + Django [Dialogflow Tutorial: Create Fulfillment Webhook Using Python + Django](https://www.pragnakalp.com/dialogflow-tutorial-create-fulfillment-webhook-using-python-django/) which will be useful to setup this library in Python + Django. We have also published a new [repo to showcase examples of creating different responses using this library](https://github.com/pragnakalp/dialogflow-response-library-implementation-python-django). 10 | 11 | ## How to use 12 | To get started just import all the functions from the library using the following statement 13 | 14 | ```python 15 | from df_response_lib import * 16 | ``` 17 | 18 | ## Supported Responses 19 | 20 | **Actions on Google** 21 | 22 | - Simple Response 23 | - Basic Card 24 | - Suggestion Chips 25 | - Link out suggestion 26 | - List Response 27 | - More will be added soon 28 | 29 | **Facebook** and **Telegram** 30 | 31 | - Text Response 32 | - Card Response 33 | - Image Response 34 | - Quick replies 35 | 36 | **DF-messenger Responses** 37 | 38 | - Simple response 39 | - Suggestion chips 40 | - Simple title card 41 | - Informative card 42 | - Image 43 | - Small button 44 | - Card with multiple options 45 | - Accordion small card 46 | 47 | **Dialogflow Fulfillment Responses** 48 | 49 | - Fulfillment Text 50 | - Fullfillment Messages 51 | - Followup Event Input 52 | - Output Contexts 53 | 54 | ## Actions on Google 55 | 56 | ### **Simple Response** 57 | ```python 58 | simple_response(responses) 59 | ``` 60 | 61 | ***responses*** - list of simple responses 62 | ```python 63 | ["Text to be displayed", "Text to be spoken", ssml=True|False] 64 | ``` 65 | 66 | ex. 67 | ```python 68 | aog_sr = aog.simple_response([ 69 | ["Hello", "Hi", False], 70 | ["Hey!!", "Hey", True] 71 | ]) 72 | ``` 73 | 74 | ### **Basic Card** 75 | 76 | ```python 77 | basic_card(title, subtitle="", formattedText="", image=None, buttons=None) 78 | ``` 79 | 80 | ***title*** is the title of card - string
81 | ***subtitle*** is the subtitle of the card - string
82 | ***formattedText*** is the description of the card - limited markdown
83 | ***image*** display image in the card - list 84 | ```python 85 | image = [imageUri, accessibilityText] 86 | ``` 87 | ***buttons*** add buttons to thr card 88 | ```python 89 | buttons = [ 90 | [button_title, url] 91 | ] 92 | ``` 93 | ex. 94 | ```python 95 | image = ['https://imagepath.com/path.png', 'sample image'] 96 | 97 | buttons = [ 98 | ['button_1', 'https://www.google.com/'], 99 | ['button 2', 'https://www.facebook.com/'] 100 | ] 101 | 102 | aog_card = aog.basic_card("card title", "card subtitle", "card *description*", image, buttons) 103 | ``` 104 | 105 | ### **Suggestion Chips** 106 | ```python 107 | suggestion_chips(suggestions) 108 | ``` 109 | ***suggestions*** - list of suggestions upto 8 items (one item length upto 25) 110 | ```python 111 | suggestions = ['chip1', 'chip2', 'chip3', 'chip4'] 112 | ``` 113 | 114 | ex. 115 | ```python 116 | aog_suggestions = aog.suggestion_chips(suggestions) 117 | ``` 118 | 119 | ### **Link out Suggestion** 120 | ```python 121 | link_out_suggestion(title, url) 122 | ``` 123 | ***title*** - Text to be shown in suggestion
124 | ***url*** - Link URL 125 | 126 | ex. 127 | ```python 128 | title = "Link to google" 129 | url = "https://www.google.com/" 130 | aog_los = aog.link_out_suggestion(title, url) 131 | ``` 132 | 133 | ### **List Select Response** 134 | 135 | ```python 136 | list_select(list_title, list_elements) 137 | ``` 138 | ***list_title*** - title of the list
139 | ***list_elements*** - list of items of the list select 140 | ```python 141 | [ 142 | ['item_title', 'item_description', item_info=['item_key', item_synonyms=['synonym1', 'synonym2'], ['imageURL', 'imageDescription']], 143 | ['item2_title', 'item2_description', item_info=['item_key', item_synonyms=['synonym1', 'synonym2'], ['imageURL', 'imageDescription']] 144 | ] 145 | ``` 146 | 147 | ex. 148 | ```python 149 | list_elements = [ 150 | ['item_title', 'item_description', ['item_key', ['synonym1', 'synonym2'], ['imageURL', 'imageDescription']], 151 | ['item2_title', 'item2_description', ['item2_key',['synonym1', 'synonym2'], ['imageURL', 'imageDescription']] 152 | ] 153 | 154 | aog_list = aog.list_select("this is a list', list_elements) 155 | ``` 156 | ## Facebook and Telegram 157 | 158 | ### **Text response** 159 | ```python 160 | text_response(texts) 161 | ``` 162 | ***texts*** - list of text 163 | ```python 164 | ['text1', 'text2', 'text3'] 165 | ``` 166 | ex. 167 | ```python 168 | texts = ['text1', 'text2', 'text3'] 169 | text_res = fb.text_response(texts) 170 | ``` 171 | 172 | ### **Quick Replies** 173 | ```python 174 | quick_replies(title, quick_replies_list) 175 | ``` 176 | ***quick_replies_list*** - list of quick replies text 177 | ```python 178 | ['reply1', 'reply2', 'reply3'] 179 | ``` 180 | ex. 181 | ```python 182 | title = "Choose something" 183 | replies= ['reply1', 'reply2', 'reply3'] 184 | fb_quick_replies = fb.quick_replies(title, replies) 185 | ``` 186 | ### **Image Response** 187 | ```python 188 | image_response(url) 189 | ``` 190 | ***url*** - image URL 191 | 192 | ex. 193 | ```python 194 | url = "https://www.xyz.com/image.png" 195 | fb_image = fb.image_response(url) 196 | ``` 197 | 198 | ### **Card Response** 199 | 200 | ```python 201 | card_response(title, buttons) 202 | ``` 203 | ***card title*** - title of the card
204 | ***buttons*** - list of buttons 205 | ```python 206 | [ 207 | ['button1', 'hello'], 208 | ['button2', 'hello again'] 209 | ] 210 | ``` 211 | 212 | ex. 213 | ```python 214 | title = "this is a card" 215 | buttons = [ 216 | ['button1', 'hello'], 217 | ['button2', 'hello again'] 218 | ] 219 | 220 | fb_card = fb.card_response(title, buttons) 221 | ``` 222 | 223 | ## Dialogflow messenger 224 | 225 | ### **Simple Response** 226 | ```python 227 | wb = web_response() 228 | ``` 229 | ***texts*** - list of text 230 | ```python 231 | ['simple response'] 232 | ``` 233 | ex. 234 | ```python 235 | texts = ['simple response'] 236 | text_res = wb.simple_response(texts) 237 | ``` 238 | 239 | ### **Suggestion Chips** 240 | ```python 241 | suggestion_chips(suggestion_chips_list) 242 | ``` 243 | ***suggestion_chips_list*** - list of suggestion chips text 244 | ```python 245 | ['reply1', 'reply2', 'reply3'] 246 | ``` 247 | ex. 248 | ```python 249 | replies= ['reply1', 'reply2', 'reply3'] 250 | wb_suggestion_chips = wb.suggestion_chips(replies) 251 | ``` 252 | ### **Image Response** 253 | ```python 254 | image_response(url, accessibility_text) 255 | ``` 256 | ***url*** - image URL 257 | 258 | ex. 259 | ```python 260 | accessibility_text = "This is an accessibility text" 261 | url = "https://www.xyz.com/image.png" 262 | wb_image = wb.image_response(url, accessibility_text) 263 | ``` 264 | 265 | ### **Card Response** 266 | 267 | ```python 268 | card_response(title, sub_title, raw_url, action_link) 269 | ``` 270 | ***title*** - title of the card
271 | ***sub_title*** - sub title of the card
272 | ***raw_url*** - URL of image for card
273 | ***action_link*** - redirect URL for card
274 | 275 | ex. 276 | ```python 277 | title = "title" 278 | sub_title = "subtitle" 279 | raw_url = "www.xyz.com" 280 | action_link = "www.abc.com" 281 | 282 | wb_card = wb.simple_title_card(title, sub_title, raw_url, action_link) 283 | ``` 284 | 285 | ### **Informative card** 286 | 287 | ```python 288 | informative_card(title, text_list) 289 | ``` 290 | ***title*** - title of the card
291 | ***text_list*** - list of text to be displayed in the card
292 | 293 | ex. 294 | ```python 295 | title = "title" 296 | text_list = ["Sample Text1","Sample Text2","Sample Text3"] 297 | 298 | informative_card = wb.informative_card(title, text_list) 299 | ``` 300 | 301 | ### **Small button** 302 | 303 | ```python 304 | small_button(text, url) 305 | ``` 306 | ***text*** - text for button
307 | ***url*** - URL for image to be displayed on the button
308 | 309 | ex. 310 | ```python 311 | text = "Sample text" 312 | url = "www.xyz.com" 313 | 314 | wb_card = wb.small_button(text, url) 315 | ``` 316 | 317 | ### **Card with multiple options** 318 | 319 | ```python 320 | card_with_multiple_options(data) 321 | ``` 322 | ***data*** - list of dictionary with title and subtitle for the card
323 | 324 | ex. 325 | ```python 326 | data = [ 327 | { 328 | "title": "title1", 329 | "subtitle": "subtitle1" 330 | }, 331 | { 332 | "title": "title2", 333 | "subtitle": "subtitle2" 334 | } 335 | ] 336 | 337 | wb_card = wb.card_with_multiple_options(data) 338 | ``` 339 | 340 | ### **Accordion card response** 341 | 342 | ```python 343 | accordion_small_card(title, sub_title, raw_url, text) 344 | ``` 345 | ***title*** - title of the card
346 | ***sub_title*** - sub title of the card
347 | ***raw_url*** - URL of image for the card
348 | ***text*** - text for the card
349 | 350 | ex. 351 | ```python 352 | title = "title" 353 | sub_title = "subtitle" 354 | raw_url = "www.xyz.com" 355 | text = "Sample Text" 356 | 357 | wb_card = wb.accordion_small_card(title, sub_title, raw_url, text) 358 | ``` 359 | 360 | ## **Dialogflow Fulfillment Responses** 361 | ### **Fulfillment Text** 362 | ```python 363 | fulfillment_text(fulfillmentText) 364 | ``` 365 | ***fulfillmentText*** - defult response text 366 | ex. 367 | ```python 368 | text = "This is a fulfillment text" 369 | df_fft = main_response.fulfillment_text(text) 370 | ``` 371 | ### **Fulfillment Messages** 372 | ```python 373 | fulfillment_messages(self, response_objects) 374 | ``` 375 | ***response_objects*** - list of supported response (any of the above) 376 | ```python 377 | [aog_sr, aog_list, aog_suggestions, fb_text, fb_card] 378 | ``` 379 | ex. 380 | ```python 381 | res_objects = [aog_sr, aog_list, aog_suggestions] 382 | ff_msgs = main_response.fulfillment_messages(res_objects) 383 | ``` 384 | ### **Output Contexts** 385 | ```python 386 | output_contexts(session, contexts) 387 | ``` 388 | ***session*** - session Id of the request
389 | ***contexts*** - list of contexts 390 | ```python 391 | [ 392 | ['context_name', 'lifespanCount', 393 | { 394 | 'paramter_name': 'value' 395 | } 396 | ] 397 | ] 398 | ``` 399 | ### **Followup Event Input** 400 | ```python 401 | followup_event_input(name, parameters) 402 | ``` 403 | ***name*** - event name
404 | ***paramters*** - event parameters 405 | ```python 406 | { 407 | 'parameter_name': 'values', 408 | 'another_parameter_name': 'values', 409 | } 410 | ``` 411 | ### **Main Response** 412 | ```python 413 | main_response(fulfillment_text, fulfillment_messages=None, output_contexts=None, followup_event_input=None): 414 | ``` 415 | ***fulfillment_text*** - Fulfillment text object
416 | ***fulfillment_messages*** - Fulfillment messages object
417 | ***output_contextstext*** - Output contexts object
418 | ***followup_event_input*** - Followup event input object
419 | 420 | Return this as your main fulfillment response. 421 | 422 | --- 423 | 424 | We are working to add more responses in the future. Please give your feedback and do contribute if you like. 425 | 426 | > Developed by [Pragnakalp Techlabs - Artificial Intelligence, Machine Learning, Deep Learning, Chatbots Development](https://www.pragnakalp.com/) 427 | -------------------------------------------------------------------------------- /df_response_lib.py: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # title : df_response_lib.py 3 | # description : This library simplifies the JSON response building in Python for Dialogflow fulfillment. Using it you can build the JSON objects with few line. 4 | # author : Pragnakalp Techlabs 5 | # email : letstalk@pragnakalp.com 6 | # website : https://www.pragnakalp.com 7 | #============================================================================== 8 | 9 | # Responses for Actions On Google 10 | class actions_on_google_response(): 11 | 12 | # class variable initializer initializer 13 | def __init__(self): 14 | self.platform = "ACTIONS_ON_GOOGLE" 15 | 16 | """ 17 | Actions on Google Simple Response Builder 18 | @param name=display_text, type=list 19 | Sample example of display_text ex. [["Text to be displayed", "Text to be spoken", True]] 20 | """ 21 | def simple_response(self, responses): 22 | 23 | if len(responses) > 2: 24 | raise Exception( 25 | "Responses argument in simple response should have at most two elements only.") 26 | else: 27 | # a list to store the responses 28 | responses_json = [] 29 | # iterate through the list of responses given by the user 30 | for response in responses: 31 | # if SSML = True, build the ssml response, else build textToSpeech 32 | # response[2] = SSML boolean 33 | if response[2]: 34 | # response dictionary 35 | response_dict = { 36 | # text to be diplayed 37 | "displayText": str(response[0]), 38 | # ssml response to be spoken 39 | "ssml": str(response[1]) 40 | } 41 | else: 42 | response_dict = { 43 | # text to be displayed 44 | "displayText": str(response[0]), 45 | # text to speech text 46 | "textToSpeech": str(response[1]) 47 | } 48 | 49 | # add the response dict to the responses list 50 | responses_json.append(response_dict) 51 | 52 | # return the simple response JSON 53 | return { 54 | "platform": self.platform, 55 | "simpleResponses": { 56 | "simpleResponses": responses_json 57 | } 58 | } 59 | 60 | """" 61 | Actions on Google Basic Card Builder 62 | @param title = string 63 | @param subtitle = string 64 | @param formattedText = string 65 | @param image = list [image_url, accessibility_text] 66 | @param buttons = list of [button_title, url_link] 67 | """ 68 | def basic_card(self, title, subtitle="", formattedText="", image=None, buttons=None): 69 | # list to store buttons responses 70 | buttons_json = [] 71 | if buttons is not None: 72 | # iterate through the buttons list 73 | for button in buttons: 74 | # add the buttons response to the buttons list 75 | buttons_json.append( 76 | { 77 | # title of the button 78 | "title": button[0], 79 | # url to be opened by the button 80 | "openUriAction": { 81 | "uri": button[1] 82 | } 83 | } 84 | ) 85 | 86 | # return basic card JSON 87 | response = { 88 | "platform": self.platform, 89 | "basicCard": { 90 | "title": title, 91 | "subtitle": subtitle, 92 | "formattedText": formattedText, 93 | "buttons": buttons_json, 94 | "image": { 95 | "imageUri": image[0], 96 | "accessibilityText": image[1] 97 | } 98 | } 99 | } 100 | 101 | else: 102 | # return basic card JSON 103 | response = { 104 | "platform": self.platform, 105 | "basicCard": { 106 | "title": title, 107 | "subtitle": subtitle, 108 | "formattedText": formattedText, 109 | "image": { 110 | "imageUri": image[0], 111 | "accessibilityText": image[1] 112 | } 113 | } 114 | } 115 | 116 | return response 117 | 118 | """ 119 | Actions on Google List response 120 | @param list_title = string 121 | @param list_elements = list of list response items 122 | """ 123 | def list_select(self, list_title, list_elements): 124 | # as per the actions on google response list items must be between 2 and 30 125 | if len(list_elements) > 30 or len(list_elements) < 2: 126 | raise Exception("List items must be two or less than 30.") 127 | else: 128 | # items list to store list elements 129 | items_list = [] 130 | # iterate through the list elements list 131 | for list_element in list_elements: 132 | # append the items to the items_list 133 | items_list.append( 134 | { 135 | # title of the list item 136 | "title": list_element[0], 137 | # description of the list item 138 | "description": list_element[1], 139 | # info aabout the list item 140 | "info": { 141 | # key of the list items, key is used as user say string 142 | "key": list_element[2][0], 143 | # synonyms are the words that can be used as a value for the option when the user types instead of selecting from the list 144 | "synonyms": list_element[2][1] 145 | }, 146 | # list image 147 | "image": { 148 | # URL 149 | "imageUri": list_element[3][0], 150 | # accessibility text to be spoken 151 | "accessibilityText": list_element[3][1] 152 | } 153 | } 154 | ) 155 | 156 | # return the list response 157 | return { 158 | "platform": self.platform, 159 | "listSelect": { 160 | "title": list_title, 161 | "items": items_list 162 | } 163 | } 164 | 165 | """ 166 | Actions on Google Suggestions chips resoponse 167 | @param suggestions = list of strings 168 | """ 169 | def suggestion_chips(self, suggestions): 170 | # suggestions_json to store the suggestions JSON 171 | suggestions_json = [] 172 | # iterate through the suggestions list 173 | for suggestion in suggestions: 174 | # append the suggestion to the suggestions_json list 175 | suggestions_json.append( 176 | { 177 | # title text to be displayed in the chip 178 | "title": str(suggestion) 179 | } 180 | ) 181 | 182 | # return the suggestion chips response JSON 183 | return { 184 | "platform": self.platform, 185 | "suggestions": { 186 | "suggestions": suggestions_json 187 | } 188 | } 189 | 190 | """ 191 | Actions on Google Linkout suggestions 192 | @param title = string 193 | @param url = string (a valid URL) 194 | """ 195 | def link_out_suggestion(self, title, url): 196 | # title should not be null 197 | if title == "" or url == "": 198 | raise Exception( 199 | "Provide the title and URL for link out suggestion response.") 200 | else: 201 | # return the link out suggestion response 202 | return { 203 | "platform": self.platform, 204 | "linkOutSuggestion": { 205 | "destinationName": str(title), 206 | "uri": str(url) 207 | } 208 | } 209 | 210 | # Responses for Facebook 211 | class facebook_response(): 212 | 213 | # class variable initializer initializer 214 | def __init__(self): 215 | self.platform = "FACEBOOK" 216 | 217 | def text_response(self, texts): 218 | # text should contain at least one string 219 | if len(texts) <= 0: 220 | raise Exception("Provide the text for the text response") 221 | else: 222 | # text_obj list for storing the text variations 223 | text_obj = [] 224 | for text in texts: 225 | text_obj.append(str(text)) 226 | 227 | # return the text response 228 | return { 229 | "text": { 230 | "text": text_obj 231 | }, 232 | "platform": self.platform 233 | } 234 | 235 | def quick_replies(self, title, quick_replies_list): 236 | if title == "": 237 | raise Exception("Title is required for basic card in facebook.") 238 | # quick_replies_list must contains at least one string 239 | elif len(quick_replies_list) <= 0: 240 | raise Exception( 241 | "Quick replies response must contain at least on text string.") 242 | else: 243 | # quick replies list to store the quick replie text 244 | quick_replies = [] 245 | for quick_reply in quick_replies_list: 246 | # append to the list 247 | quick_replies.append( 248 | str(quick_reply) 249 | ) 250 | 251 | # return the response JSON 252 | return { 253 | "quickReplies": { 254 | "title": str(title), 255 | "quickReplies": quick_replies 256 | }, 257 | "platform": self.platform 258 | } 259 | 260 | def image_response(self, url): 261 | # check url 262 | if url == "": 263 | raise Exception("URL in the image response is required.") 264 | else: 265 | # return the JSON response 266 | return { 267 | "image": { 268 | "imageUri": str(url) 269 | }, 270 | "platform": self.platform 271 | } 272 | 273 | def card_response(self, title, buttons): 274 | buttons_json = [] 275 | for button in buttons: 276 | buttons_json.append( 277 | { 278 | "text": str(button[0]), 279 | "postback": str(button[1]) 280 | } 281 | ) 282 | 283 | # return the card 284 | return { 285 | "card": { 286 | "title": str(title), 287 | "buttons": buttons_json 288 | }, 289 | "platform": self.platform 290 | } 291 | 292 | def custom_payload(self, payload): 293 | 294 | # return custom payload 295 | return { 296 | "payload": payload, 297 | "platform": self.platform 298 | } 299 | 300 | # Responses for Telegram 301 | class telegram_response(): 302 | 303 | # class variable initializer initializer 304 | def __init__(self): 305 | self.platform = "TELEGRAM" 306 | 307 | def text_response(self, texts): 308 | # text should contain at least one string 309 | if len(texts) <= 0: 310 | raise Exception("Provide the text for the text response") 311 | else: 312 | # text_obj list for storing the text variations 313 | text_obj = [] 314 | for text in texts: 315 | text_obj.append(str(text)) 316 | 317 | # return the text response 318 | return { 319 | "text": { 320 | "text": text_obj 321 | }, 322 | "platform": self.platform 323 | } 324 | 325 | def quick_replies(self, title, quick_replies_list): 326 | if title == "": 327 | raise Exception("Title is required for basic card in facebook.") 328 | # quick_replies_list must contains at least one string 329 | elif len(quick_replies_list) <= 0: 330 | raise Exception( 331 | "Quick replies response must contain at least on text string.") 332 | else: 333 | # quick replies list to store the quick replie text 334 | quick_replies = [] 335 | for quick_reply in quick_replies_list: 336 | # append to the list 337 | quick_replies.append( 338 | str(quick_reply) 339 | ) 340 | 341 | # return the response JSON 342 | return { 343 | "quickReplies": { 344 | "title": str(title), 345 | "quickReplies": quick_replies 346 | }, 347 | "platform": self.platform 348 | } 349 | 350 | def image_response(self, url): 351 | # check url 352 | if url == "": 353 | raise Exception("URL in the image response is required.") 354 | else: 355 | # return the JSON response 356 | return { 357 | "image": { 358 | "imageUri": str(url) 359 | }, 360 | "platform": self.platform 361 | } 362 | 363 | def card_response(self, title, buttons): 364 | buttons_json = [] 365 | for button in buttons: 366 | buttons_json.append( 367 | { 368 | "text": str(button[0]), 369 | "postback": str(button[1]) 370 | } 371 | ) 372 | 373 | return { 374 | "card": { 375 | "title": str(title), 376 | "buttons": buttons_json 377 | }, 378 | "platform": self.platform 379 | } 380 | 381 | # Responses for dialogflow messenger 382 | class web_response(): 383 | 384 | def __init__(self): 385 | pass 386 | 387 | def suggestion_chips(self, chips:list): 388 | """ 389 | Dialogflow Messenger Suggestion chips Builder 390 | @param chips=list 391 | Sample example of display suggestion chips (["suggestion1", "suggestion2", "suggestion3"]) 392 | """ 393 | 394 | add_chip = [] 395 | for chip in chips: 396 | add_chip.append({ 397 | "text": chip, 398 | "image": { 399 | "src": { 400 | "rawUrl": "" 401 | } 402 | }, 403 | "link": "" 404 | }) 405 | 406 | return { 407 | "payload": 408 | { 409 | "richContent": 410 | [ 411 | [ 412 | { 413 | "type": "chips", 414 | "options": add_chip 415 | } 416 | ] 417 | ] 418 | 419 | } 420 | } 421 | 422 | 423 | def simple_response(self, simpletext:list): 424 | """ 425 | Dialogflow Messenger Simple Response Builder 426 | @param simpletext=list (Note: 2D list always) 427 | Sample example of display simple response (["Sample text response"]) 428 | """ 429 | 430 | return { 431 | "text": { 432 | "text": simpletext 433 | } 434 | } 435 | 436 | 437 | 438 | def simple_title_card(self, title, sub_title, raw_url, action_link): 439 | """ 440 | Dialogflow Messenger Simple Title Card Response Builder 441 | @param title=str, sub_title=str, rowUrl=str, action_link=str. 442 | Sample example of display_text ex. simple_title_card("Title","Subtitle","www.xyz.com","www.abc.com") 443 | """ 444 | 445 | simple_title_cards = [] 446 | simple_title_cards.append({ 447 | "type": "info", 448 | "title": title, 449 | "subtitle": sub_title, 450 | "image": { 451 | "src": { 452 | "rawUrl": raw_url 453 | } 454 | }, 455 | "actionLink": action_link 456 | }) 457 | return { 458 | "payload": 459 | { 460 | "richContent": [ 461 | simple_title_cards 462 | ] 463 | } 464 | } 465 | 466 | def informative_card(self, title, data: list): 467 | """ 468 | Dialogflow Messenger Informative Card Response Builder 469 | @param title=str, data=list. 470 | Sample example of display_text ex. informative_card("Title",["Sample Text1","Sample Text2","Sample Text3"]) 471 | """ 472 | 473 | return { 474 | "payload": 475 | { 476 | "richContent": [ 477 | [ 478 | { 479 | "type": "description", 480 | "title": title, 481 | "text": data 482 | } 483 | ] 484 | ] 485 | } 486 | } 487 | 488 | 489 | def image_response(self, raw_url, accessibility_text): 490 | """ 491 | Dialogflow Messenger Image Card Response Builder 492 | @param rowUrl=str, accessibility_text=str. 493 | Sample example of display_text ex. image_card("www.url.com","Sample Text") 494 | """ 495 | 496 | return{ 497 | "payload": 498 | { 499 | "richContent": 500 | [ 501 | [ 502 | { 503 | "type": "image", 504 | "rawUrl": raw_url, 505 | "accessibilityText": accessibility_text 506 | } 507 | ] 508 | ] 509 | 510 | } 511 | } 512 | 513 | def small_button(self, text, link): 514 | """ 515 | Dialogflow Messenger Small Button Response Builder 516 | @param text=str, link=str. 517 | Sample example of display_text ex. small_button("Sample Text","www.url.com") 518 | """ 519 | 520 | return{ 521 | "payload": 522 | { 523 | "richContent": 524 | [ 525 | [ 526 | { 527 | "type": "button", 528 | "icon": { 529 | "type": "chevron_right", 530 | "color": "#FF9800" 531 | }, 532 | "text": text, 533 | "link": link, 534 | "event": { 535 | "name": "", 536 | "languageCode": "", 537 | "parameters": {} 538 | } 539 | } 540 | ] 541 | ] 542 | } 543 | } 544 | 545 | 546 | def card_with_multiple_options(self, data:list): 547 | """ 548 | Dialogflow Messenger Card With Multiple Options Response Builder 549 | @param data=list of dict 550 | Sample example of display_text ex. card_with_multiple_options([{"title" : "title1", "subtitle" : "subtitle1"}, { "title" : "title2", "subtitle" : "subtitle2"}]) 551 | """ 552 | 553 | one_card_option = [] 554 | for i in range(len(data)): 555 | one_card_option.append({ 556 | "type": "list", 557 | "title": data[i]["title"], 558 | "subtitle": data[i]["subtitle"], 559 | "event": { 560 | "name": "", 561 | "languageCode": "", 562 | "parameters": {} 563 | } 564 | }) 565 | if i != len(data): 566 | one_card_option.append( 567 | { 568 | "type": "divider" 569 | }) 570 | 571 | return { 572 | "payload": { 573 | "richContent": 574 | [ 575 | one_card_option 576 | ] 577 | } 578 | } 579 | 580 | def accordion_small_card(self, title, sub_title, raw_url, text): 581 | """ 582 | Dialogflow Messenger Accordion Small Card Response Builder 583 | @param title=str, sub_title=str, rawUrl=str, text=str. 584 | Sample example of display_text ex. accordion_small_card("Title","Subtitle","www.xyz.com","Sample Text") 585 | """ 586 | 587 | return { 588 | "payload": { 589 | "richContent": [ 590 | [ 591 | { 592 | "type": "accordion", 593 | "title": title, 594 | "subtitle": sub_title, 595 | "image": { 596 | "src": { 597 | "rawUrl": raw_url 598 | } 599 | }, 600 | "text": text 601 | } 602 | ] 603 | ] 604 | } 605 | } 606 | 607 | # dialogflow fulfillment response 608 | class fulfillment_response(): 609 | 610 | def __init__(self): 611 | pass 612 | 613 | # fulfillment text builder 614 | # @param fulfillmentText = string 615 | def fulfillment_text(self, fulfillmentText): 616 | if fulfillmentText == "": 617 | raise Exception("Fulfillment text should not be empty.") 618 | else: 619 | return { 620 | "fulfillment_text": str(fulfillmentText) 621 | } 622 | 623 | # fulfillment messages builder 624 | # @param response_objects (AOG response, FB response, Telegram response) 625 | def fulfillment_messages(self, response_objects): 626 | if len(response_objects) <= 0: 627 | raise Exception( 628 | "Response objects must contain at least one response object.") 629 | else: 630 | return { 631 | "fulfillment_messages": response_objects 632 | } 633 | 634 | # dialogflow output contexts 635 | # @param session = dialogflow session id 636 | # @param contexts = context name (string) 637 | def output_contexts(self, session, contexts): 638 | contexts_json = [] 639 | for context in contexts: 640 | contexts_json.append({ 641 | "name": session + "/contexts/" + context[0], 642 | "lifespanCount": context[1], 643 | "parameters": context[2] 644 | }) 645 | 646 | # return the output context json 647 | return { 648 | "output_contexts": contexts_json 649 | } 650 | 651 | # dialogflow followup event JSON 652 | # @param name = event name 653 | # @param parameters = key value pair of parameters to be passed 654 | def followup_event_input(self, name, parameters): 655 | return { 656 | "followup_event_input": { 657 | "name": str(name), 658 | "parameters": parameters 659 | } 660 | } 661 | 662 | # main response with fulfillment text and fulfillment messages 663 | # @param fulfillment_text = fulfillment_text JSON 664 | # @param fulfillment_messages = fulfillment_messages JSON 665 | # @param output_contexts = output_contexts JSON 666 | # @param followup_event_input = followup_event_input JSON 667 | def main_response(self, fulfillment_text, fulfillment_messages=None, output_contexts=None, followup_event_input=None): 668 | if followup_event_input is not None: 669 | if output_contexts is not None: 670 | if fulfillment_messages is not None: 671 | response = { 672 | "fulfillmentText": fulfillment_text['fulfillment_text'], 673 | "fulfillmentMessages": fulfillment_messages['fulfillment_messages'], 674 | "outputContexts": output_contexts['output_contexts'], 675 | "followupEventInput": followup_event_input['followup_event_input'] 676 | } 677 | else: 678 | response = { 679 | "fulfillmentText": fulfillment_text['fulfillment_text'], 680 | "outputContexts": output_contexts['output_contexts'], 681 | "followupEventInput": followup_event_input['followup_event_input'] 682 | } 683 | else: 684 | if fulfillment_messages is not None: 685 | response = { 686 | "fulfillmentText": fulfillment_text['fulfillment_text'], 687 | "fulfillmentMessages": fulfillment_messages['fulfillment_messages'], 688 | "followupEventInput": followup_event_input['followup_event_input'] 689 | } 690 | else: 691 | response = { 692 | "fulfillmentText": fulfillment_text['fulfillment_text'], 693 | "followupEventInput": followup_event_input['followup_event_input'] 694 | } 695 | else: 696 | if output_contexts is not None: 697 | if fulfillment_messages is not None: 698 | response = { 699 | "fulfillmentText": fulfillment_text['fulfillment_text'], 700 | "fulfillmentMessages": fulfillment_messages['fulfillment_messages'], 701 | "outputContexts": output_contexts['output_contexts'] 702 | } 703 | else: 704 | response = { 705 | "fulfillmentText": fulfillment_text['fulfillment_text'], 706 | "outputContexts": output_contexts['output_contexts'] 707 | } 708 | else: 709 | if fulfillment_messages is not None: 710 | response = { 711 | "fulfillmentText": fulfillment_text['fulfillment_text'], 712 | "fulfillmentMessages": fulfillment_messages['fulfillment_messages'] 713 | } 714 | else: 715 | response = { 716 | "fulfillmentText": fulfillment_text['fulfillment_text'] 717 | } 718 | 719 | # return the main dialogflow response 720 | return response 721 | -------------------------------------------------------------------------------- /facebook_template_lib.py: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # title : facebook_template_lib.py 3 | # description : This library is used to prepare custom payload for Facebook Messenger generic template with elements like image, title, subtitle, URL button and postback button. It will automatically create carousel if more than 1 generic templates are passed. 4 | # author : Pragnakalp Techlabs 5 | # email : letstalk@pragnakalp.com 6 | # website : https://www.pragnakalp.com 7 | #============================================================================== 8 | 9 | class FacebookTemplate(): 10 | '''Create generic facebook messenger tempalte. ''' 11 | def __init__(self): 12 | self.payload = { 13 | "facebook": { 14 | "attachment": { 15 | "type": "template", 16 | "payload": { 17 | "template_type":"generic", 18 | "elements": [ 19 | 20 | ] 21 | } 22 | } 23 | } 24 | } 25 | 26 | def add_element(self, element_obj): 27 | self.payload['facebook']['attachment']['payload']['elements'].append(element_obj) 28 | 29 | def get_payload(self): 30 | return self.payload 31 | 32 | class TemplateElement(): 33 | ''' Add title, subtitle, image, buttons and action elements in generic template response.''' 34 | def __init__(self, title, subtitle): 35 | self.element = { 36 | "title": title, 37 | "subtitle": subtitle 38 | } 39 | 40 | def add_image_url(self, url): 41 | self.element['image_url'] = url 42 | 43 | def add_default_action(self, url, type, webview_height_ratio): 44 | self.element["default_action"]={ 45 | "url":url, 46 | "type": type, 47 | "webview_height_ratio": webview_height_ratio 48 | } 49 | 50 | def add_button(self, button_obj): 51 | self.element['buttons']=[button_obj] 52 | 53 | def get_element(self): 54 | return self.element 55 | 56 | class TemplateElementButton(): 57 | '''Types of buttons that can be added in response.''' 58 | def __init__(self, button_type, title): 59 | self.button = { 60 | "type": button_type, 61 | "title": title 62 | } 63 | 64 | def add_web_url(self, url): 65 | assert self.button['type']=='web_url', "Error: button type must be 'web_url'" 66 | self.button['url'] = url 67 | 68 | def add_payload(self, payload): 69 | assert self.button['type']=='postback', "Error:button type must be 'postback'" 70 | self.button['payload'] = payload 71 | 72 | def get_button(self): 73 | return self.button --------------------------------------------------------------------------------