From 529ec5586fb24829f1854f90e4033ababf9bf0c3 Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Thu, 26 Sep 2024 13:44:30 +0530 Subject: [PATCH 1/7] ref:add custom feilds --- .../doctype/chatbot_flow/chatbot_flow.json | 8 ++++--- .../chatbot_party_type/chatbot_party_type.py | 21 ++++++++++++++----- .../doctype/chatbot_setup/chatbot_setup.json | 6 +++--- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json index 313b1a5..d7674ee 100644 --- a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json +++ b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json @@ -78,13 +78,15 @@ "fieldname": "associated_party_types", "fieldtype": "Table MultiSelect", "label": "Associated Party Types", - "options": "Chatbot Associated Party Types" + "options": "Chatbot Associated Party Types", + "reqd": 1 }, { "fieldname": "template", "fieldtype": "Link", "label": "Template", - "options": "Chatbot Message Template" + "options": "Chatbot Message Template", + "reqd": 1 }, { "fieldname": "type", @@ -97,7 +99,7 @@ "index_web_pages_for_search": 1, "is_tree": 1, "links": [], - "modified": "2024-09-25 12:55:43.551793", + "modified": "2024-09-26 13:37:39.673202", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Flow", diff --git a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py index 0ed2568..d05ebd4 100644 --- a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py +++ b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py @@ -12,28 +12,39 @@ def validate(self): def create_customer_custom_field(party_name): enable_telegram,enable_whatsapp,enable_slack=frappe.db.get_value("Chatbot Setup","Chatbot Setup",["enable_telegram","enable_whatsapp","enable_slack"]) + insert_afrter_fieldname= frappe.get_meta(party_name) + insert_afrter_fieldname=insert_afrter_fieldname.fields[-1].get("fieldname") + print(insert_afrter_fieldname) custom_fields = {} if enable_telegram: - custom_fields.update( { + custom_fields = { party_name: [ dict( fieldname="chatbot_details", label="Chatbot Details", fieldtype="Tab Break", + insert_afrter=insert_afrter_fieldname, ), dict( - fieldname="custom_telegram_username", + fieldname="sb_chb", + label="", + fieldtype="Section Break", + insert_afrter="chatbot_details" + ), + dict( + fieldname="telegram_username", label="Telegram Username", fieldtype="Data", - insert_after="chatbot_details", + insert_after="sb_chb", ), dict( fieldname="telegram_user_id", read_only=1, label="", fieldtype="Data", - insert_after="custom_telegram_username", + insert_after="telegram_username", ), ] - }) + } + print(custom_fields) create_custom_fields(custom_fields, update=True) \ No newline at end of file diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json index 6e36881..3886040 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json @@ -1,6 +1,5 @@ { "actions": [], - "allow_rename": 1, "creation": "2024-09-21 14:44:19.266520", "doctype": "DocType", "engine": "InnoDB", @@ -42,7 +41,8 @@ { "fieldname": "telegram_username", "fieldtype": "Data", - "label": "Bot Username" + "label": "Bot Username", + "read_only": 1 }, { "fieldname": "telegram_api_token", @@ -87,7 +87,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2024-09-26 11:46:39.605839", + "modified": "2024-09-26 13:35:42.977210", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Setup", From 3ba00cb80108d38c1ea12d8c04ef920bde896ef5 Mon Sep 17 00:00:00 2001 From: vimalraj27 Date: Thu, 26 Sep 2024 15:46:53 +0530 Subject: [PATCH 2/7] Some changes in chatbot doctypes --- .../doctype/chatbot_flow/chatbot_flow.json | 3 ++- .../chatbot_message_template.js | 16 +++++++++++----- .../chatbot_message_template.json | 14 +++++++++++--- .../chatbot_party_type/chatbot_party_type.json | 3 ++- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json index 313b1a5..3d3866d 100644 --- a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json +++ b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_import": 1, "allow_rename": 1, "autoname": "field:name1", "creation": "2024-09-22 11:22:36.891954", @@ -97,7 +98,7 @@ "index_web_pages_for_search": 1, "is_tree": 1, "links": [], - "modified": "2024-09-25 12:55:43.551793", + "modified": "2024-09-24 13:21:53.228666", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Flow", diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.js b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.js index c8eaeda..df25317 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.js +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.js @@ -1,8 +1,14 @@ // Copyright (c) 2024, Aerele and contributors // For license information, please see license.txt -// frappe.ui.form.on("Chatbot Message Template", { -// refresh(frm) { - -// }, -// }); +frappe.ui.form.on("Chatbot Message Template", { + refresh(frm) { + frm.set_query("print_format", function (doc) { + return { + filters: { + "doc_type": frm.doc.default_doctype + }, + }; + }); + }, +}); diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json index 9bc4a6c..e4adca5 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_import": 1, "allow_rename": 1, "autoname": "prompt", "creation": "2024-09-21 14:32:31.588744", @@ -10,6 +11,7 @@ "enable_dynamic_response", "response_type", "template", + "default_doctype", "print_format", "default_document", "report", @@ -52,9 +54,9 @@ }, { "fieldname": "default_document", - "fieldtype": "Link", + "fieldtype": "Dynamic Link", "label": "Default Document", - "options": "Print Format" + "options": "default_doctype" }, { "fieldname": "report", @@ -90,11 +92,17 @@ "fieldname": "html_yzlg", "fieldtype": "HTML", "options": "

Help

\n

Custom Function

\n

It contains the keyword arguments respective to the associated party names

\n

{Party Type} = {Party Name}

\n

Example: customer = \"customer_name\"

\n

So, make sure your custom function has **kwargs as a param to get values

\n
\n

Server Script

\n
\nres = {}\n\n#get the default arguments passed using form_dict.party_name\nif frappe.form_dict.customer: \n    customer = frappe.form_dict.customer\n    company = frappe.db.get_default('company')\n    res[\"customer_name\"] = customer\n    res[\"company\"] = company\n    res[\"phone\"] = \"9876543218\"\n    res[\"email\"] = \"kavin@aerele.in\"\n    res[\"website_url\"] = \"www.aerele.in\"\n    \n    #response should be passed in flags.response key : value dict\n    frappe.flags.response = res \n\n
" + }, + { + "fieldname": "default_doctype", + "fieldtype": "Link", + "label": "Default Doctype", + "options": "DocType" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-09-22 19:52:04.827393", + "modified": "2024-09-24 15:44:25.304492", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Message Template", diff --git a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json index efcae12..4cf01e6 100644 --- a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json +++ b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_import": 1, "allow_rename": 1, "autoname": "field:party_name", "creation": "2024-09-21 23:57:22.931228", @@ -19,7 +20,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-09-22 00:01:09.139990", + "modified": "2024-09-24 13:27:10.904021", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Party Type", From fed4d8d588940cca97907fc31e57869457a8530a Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Thu, 26 Sep 2024 15:58:13 +0530 Subject: [PATCH 3/7] ref:delete webhook before setting a new one --- .../chatbot/doctype/chatbot_setup/chatbot_setup.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py index b0976c3..e46fcc5 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py @@ -44,13 +44,24 @@ def set_webhook(self): """Set the Telegram webhook URL using Telegram's setWebhook API.""" if self.has_value_changed("telegram_webhook_url"): api_token = self.get_password("telegram_api_token") - + self.del_webhook() webhook_url = f"{self.telegram_webhook_url}/api/method/chatbot.webhook.telegram_webhook" url = f"https://api.telegram.org/bot{api_token}/setWebhook?url={webhook_url}" try: + response = requests.get(url) response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes except requests.exceptions.RequestException as e: frappe.throw(f"Failed to set Telegram webhook: {e}") + def del_webhook(self): + api_token = self.get_password("telegram_api_token") + url=f"https://api.telegram.org/bot{api_token}/deleteWebhook?drop_pending_updates=1" + try: + + response = requests.get(url) + response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes + + except requests.exceptions.RequestException as e: + frappe.throw(f"Failed to set Telegram webhook: {e}") From 38184739662316aee4e917edb14c46173037dc0a Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Thu, 26 Sep 2024 16:54:59 +0530 Subject: [PATCH 4/7] ref:add s_token reques --- chatbot/api/telegram_api.py | 30 ++++- .../doctype/chatbot_setup/chatbot_setup.json | 10 +- .../doctype/chatbot_setup/chatbot_setup.py | 106 ++++++++++-------- chatbot/webhook.py | 3 +- 4 files changed, 96 insertions(+), 53 deletions(-) diff --git a/chatbot/api/telegram_api.py b/chatbot/api/telegram_api.py index 6e9321f..6b3d8f6 100644 --- a/chatbot/api/telegram_api.py +++ b/chatbot/api/telegram_api.py @@ -3,17 +3,41 @@ import json from chatbot.chatbot.doctype.chatbot_log.chatbot_log import log_chatbot from chatbot.utils import validate_user, get_root_chatbot_flow, get_associated_party_types, fetch_all_children - +import hashlib +from passlib.context import CryptContext +passlibctx = CryptContext(schemes=["pbkdf2_sha256","argon2",], ) class TelegramAPI: - def __init__(self, update): + def __init__(self, update,headers): self.update = update + self.headers=headers + self.validate_token=False + secret_token_ft=self.headers.get("X-Telegram-Bot-Api-Secret-Token") + host=self.headers.get("X-Forwarded-Host") + proto=self.headers.get("X-Forwarded-Proto") + if proto !="https": + frappe.throw("Not an https Request", frappe.PermissionError) + if host !=frappe.db.get_value("Chatbot Setup","Chatbot Setup","telegram_webhook_url").strip()[8:]: + frappe.throw("Not an Host", frappe.PermissionError) + if secret_token_ft: + secret_token = frappe.get_doc("Chatbot Setup").get_password("secret_token") + if secret_token: + random_value=hashlib.sha256(secret_token_ft.encode()) + random_value=random_value.hexdigest() + if passlibctx.verify(random_value,secret_token): + self.validate_token =True + else: + frappe.throw("Verify Error", frappe.PermissionError) + else: + frappe.throw("StFxx0n0ecre Tnmx0naoke Error", frappe.PermissionError) + else: + frappe.throw("StFxx0n0ecre Tnmx0naoke Error FT", frappe.PermissionError) self.token = frappe.get_doc("Chatbot Setup").get_password('telegram_api_token') self.base_url = f"https://api.telegram.org/bot{self.token}/" self.reply_text = str() self.reply_markup = {} self.data = str() self.chat_id=str() - print("update",update) + if "callback_query" in update: self.callback_query =update.get('callback_query') self.message = self.callback_query.get('message') diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json index 3886040..9c62ee8 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json @@ -10,6 +10,7 @@ "telegram_username", "telegram_api_token", "telegram_webhook_url", + "secret_token", "whatsapp_tab", "enable_whatsapp", "whatsapp_title", @@ -82,12 +83,19 @@ "fieldname": "enable_slack", "fieldtype": "Check", "label": "Enable" + }, + { + "fieldname": "secret_token", + "fieldtype": "Password", + "hidden": 1, + "no_copy": 1, + "read_only": 1 } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2024-09-26 13:35:42.977210", + "modified": "2024-09-26 16:10:19.515181", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Setup", diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py index e46fcc5..5b5272c 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py @@ -4,64 +4,74 @@ import frappe from frappe.model.document import Document import requests - +import secrets +import hashlib +from passlib.context import CryptContext +passlibctx = CryptContext(schemes=["pbkdf2_sha256","argon2",], ) class ChatbotSetup(Document): - def autoname(self): - """Automatically set the name by replacing spaces with hyphens in the title.""" - self.name = self.title.replace(" ", "-") + def autoname(self): + """Automatically set the name by replacing spaces with hyphens in the title.""" + self.name = self.title.replace(" ", "-") - def validate(self): - """Validate the Telegram API token and set the webhook if needed.""" - self.validate_api_token() - self.set_webhook() + def validate(self): + """Validate the Telegram API token and set the webhook if needed.""" + self.validate_api_token() + self.set_webhook() - def validate_api_token(self): - """Validate the Telegram API token using Telegram's getMe API.""" - if not self.has_value_changed("telegram_api_token"): - return # Skip validation if token hasn't changed + def validate_api_token(self): + """Validate the Telegram API token using Telegram's getMe API.""" + if not self.has_value_changed("telegram_api_token"): + return # Skip validation if token hasn't changed - frappe.db.commit() #Commit current changes to get recent decrypted token - api_token = self.get_password("telegram_api_token") + frappe.db.commit() #Commit current changes to get recent decrypted token + api_token = self.get_password("telegram_api_token") - url = f"https://api.telegram.org/bot{api_token}/getMe" + url = f"https://api.telegram.org/bot{api_token}/getMe" - try: - response = requests.get(url) - response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes + try: + response = requests.get(url) + response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes - data = response.json() + data = response.json() - # Ensure that the API response contains valid bot information - if data.get("result", {}).get("is_bot"): - self.telegram_username = "@" + data["result"]["username"] - else: - frappe.throw("The Telegram user is not a bot.") + # Ensure that the API response contains valid bot information + if data.get("result", {}).get("is_bot"): + self.telegram_username = "@" + data["result"]["username"] + else: + frappe.throw("The Telegram user is not a bot.") - except requests.exceptions.RequestException as e: - frappe.throw(f"Failed to validate Telegram API token: {e}") + except requests.exceptions.RequestException as e: + frappe.throw(f"Failed to validate Telegram API token: {e}") - def set_webhook(self): - """Set the Telegram webhook URL using Telegram's setWebhook API.""" - if self.has_value_changed("telegram_webhook_url"): - api_token = self.get_password("telegram_api_token") - self.del_webhook() - webhook_url = f"{self.telegram_webhook_url}/api/method/chatbot.webhook.telegram_webhook" - url = f"https://api.telegram.org/bot{api_token}/setWebhook?url={webhook_url}" + def set_webhook(self): + """Set the Telegram webhook URL using Telegram's setWebhook API.""" + if self.has_value_changed("telegram_webhook_url"): + api_token = self.get_password("telegram_api_token") + self.del_webhook() + s_token=self.get_secret_token() + webhook_url = f"{self.telegram_webhook_url}/api/method/chatbot.webhook.telegram_webhook" + url = f"https://api.telegram.org/bot{api_token}/setWebhook?url={webhook_url}&secret_token={s_token}&drop_pending_updates=True" - try: - - response = requests.get(url) - response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes + try: + + response = requests.get(url) + response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes - except requests.exceptions.RequestException as e: - frappe.throw(f"Failed to set Telegram webhook: {e}") - def del_webhook(self): - api_token = self.get_password("telegram_api_token") - url=f"https://api.telegram.org/bot{api_token}/deleteWebhook?drop_pending_updates=1" - try: - - response = requests.get(url) - response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes + except requests.exceptions.RequestException as e: + frappe.throw(f"Failed to set Telegram webhook: {e}") + def del_webhook(self): + api_token = self.get_password("telegram_api_token") + url=f"https://api.telegram.org/bot{api_token}/deleteWebhook?drop_pending_updates=1" + try: + + response = requests.get(url) + response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes - except requests.exceptions.RequestException as e: - frappe.throw(f"Failed to set Telegram webhook: {e}") + except requests.exceptions.RequestException as e: + frappe.throw(f"Failed to set Telegram webhook: {e}") + def get_secret_token(self): + random_value_to_send =secrets.token_hex(32) + random_value=hashlib.sha256(random_value_to_send.encode()) + random_value=random_value.hexdigest() + self.secret_token=passlibctx.hash(random_value) + return random_value_to_send diff --git a/chatbot/webhook.py b/chatbot/webhook.py index ed13390..29b7118 100644 --- a/chatbot/webhook.py +++ b/chatbot/webhook.py @@ -8,7 +8,8 @@ def telegram_webhook(): """Webhook endpoint for Telegram.""" try: update = frappe.request.get_json() - api = TelegramAPI(update) + headers=frappe.request.headers + api = TelegramAPI(update,headers) try: api.process_update() From af457d99037653edbce71e1c37b83444db6fa787 Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Fri, 27 Sep 2024 11:40:36 +0530 Subject: [PATCH 5/7] ref:find current parent --- chatbot/api/telegram_api.py | 38 +++++++++++++------ .../chatbot_message_template.py | 7 +++- chatbot/utils.py | 5 ++- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/chatbot/api/telegram_api.py b/chatbot/api/telegram_api.py index 6b3d8f6..281ace3 100644 --- a/chatbot/api/telegram_api.py +++ b/chatbot/api/telegram_api.py @@ -8,6 +8,7 @@ passlibctx = CryptContext(schemes=["pbkdf2_sha256","argon2",], ) class TelegramAPI: def __init__(self, update,headers): + print(update) self.update = update self.headers=headers self.validate_token=False @@ -37,6 +38,7 @@ def __init__(self, update,headers): self.reply_markup = {} self.data = str() self.chat_id=str() + self.message_received=str() if "callback_query" in update: self.callback_query =update.get('callback_query') @@ -50,20 +52,20 @@ def __init__(self, update,headers): if self.message: self.chat_id = self.message.get("chat").get("id") self.user_name = "@"+self.message["chat"]["username"] + self.message_received=self.message.get("text") else: frappe.throw(msg="Message object not found") - def send_message(self, text:str): + def send_message(self, text:str =None): """Send a message to a Telegram chat, with optional inline buttons.""" url = f"{self.base_url}sendMessage" payload = { "chat_id": self.chat_id, - "text": text, - "ForceReply" + "text": self.reply_text, "reply_markup": self.reply_markup # Inline keyboard markup } - print("self.reply_markup",self.reply_markup) + print("payload",payload) response = requests.post(url, json=payload) log_chatbot( @@ -140,8 +142,14 @@ def process_update(self): def handle_message(self, party_type, party_name): """Handle incoming messages.""" # Determine chatbot flow and template + print("self.data",self.data) + self.data=self.data if frappe.db.exists("Chatbot Flow",self.data) else None pre_chatbot_flow_name=frappe.cache.get_value(self.chat_id) + pre_chatbot_flow_name=pre_chatbot_flow_name if frappe.db.exists("Chatbot Flow",pre_chatbot_flow_name) else None + print("pre_chatbot_flow_name",pre_chatbot_flow_name) + parent_flow=get_root_chatbot_flow(party_type) if self.data: + chatbot_flow = frappe.get_doc('Chatbot Flow', self.data) elif pre_chatbot_flow_name: chatbot_flow = frappe.get_doc('Chatbot Flow', pre_chatbot_flow_name) @@ -149,11 +157,11 @@ def handle_message(self, party_type, party_name): if children: chatbot_flow = frappe.get_doc('Chatbot Flow', children[0].get("name")) else: - chatbot_flow= get_root_chatbot_flow() + chatbot_flow= parent_flow else: - chatbot_flow= get_root_chatbot_flow() + chatbot_flow=parent_flow associated_parties = get_associated_party_types(chatbot_flow.get('name')) children = fetch_all_children(chatbot_flow.get('name')) @@ -161,19 +169,25 @@ def handle_message(self, party_type, party_name): # Build reply markup (inline keyboard) self.reply_markup = {"inline_keyboard": [], 'resize_keyboard': True} - + print("children",children) + print("chatbot_flow",chatbot_flow) + default_children=[] + if chatbot_flow.get('name') !=parent_flow.get("name"): + default_children=[{"name":parent_flow.get("name"),"button_text":"Main Menu"}] + children=children+default_children if children: - self.reply_markup["inline_keyboard"] = [ - [{"text": child.get('button_text'), "callback_data": child.get('name')}] - for child in children + self.reply_markup["inline_keyboard"]= [ + [{"text": child.get('button_text'), "callback_data": child.get('name')} for child in children if child.get('button_text') ] + ] # Check if party_type is in associated parties if party_type in associated_parties: chatbot_template = frappe.get_doc('Chatbot Message Template', template) - kwargs = {party_type.lower(): party_name} + kwargs = {party_type.lower(): party_name,"data":self.message_received} self.reply_text = chatbot_template.get_rendered_template(**kwargs) - self.send_message(self.reply_text) + print("reply_text",self.reply_text) + self.send_message() frappe.cache.set_value(self.chat_id,chatbot_flow.get('name')) def set_chat_id(self,party_type,party_name): chat_id =frappe.db.get_value(party_type,party_name,"telegram_user_id") diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py index 6ad835d..b4aed6e 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py @@ -8,17 +8,22 @@ class ChatbotMessageTemplate(Document): def get_rendered_template(self, **kwargs): + print("in get_rendered_template") if self.enable_dynamic_response and self.template: + print("in validae") if not self.is_custom_function and self.server_script: + print("in server_script") template_data = self.execute_server_script(**kwargs) return self.template.format(**template_data).strip() return self.template def execute_server_script(self, **kwargs): + print() api_method = frappe.db.get_value('Server Script', {'name':self.server_script, 'script_type':'API'}, 'api_method') - + print("api_method",api_method) + print("kwargs",kwargs) if api_method: response = run_script(self.server_script, **kwargs).get('response') diff --git a/chatbot/utils.py b/chatbot/utils.py index 491907a..4c87cfa 100644 --- a/chatbot/utils.py +++ b/chatbot/utils.py @@ -12,9 +12,10 @@ def validate_user(user_name:str, service_name:str): return None, None -def get_root_chatbot_flow(): +def get_root_chatbot_flow(party_type): + party_tree=frappe.db.get_all("Chatbot Associated Party Types",{"parent":["is","set"],"parenttype":"Chatbot Flow","party_name": party_type},["parent"],pluck="parent") root_doc = frappe.db.get_value('Chatbot Flow', - {'parent_chatbot_flow': ["is", "null"], 'button_text' : ["is", "null"]}, + {'parent_chatbot_flow': ["is", "null"], 'button_text' : ["is", "null"],"name":["in",party_tree]}, ['template', 'name'], as_dict=1) if root_doc: From 3c8ec2546c188ba87b10abb1e66dc222ff2206dd Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Tue, 24 Dec 2024 17:54:35 +0530 Subject: [PATCH 6/7] refactor: apply pre-commit formatting standards --- .gitignore | 2 +- .pre-commit-config.yaml | 7 + README.md | 2 +- chatbot/api/telegram_api.py | 166 ++++++++++-------- .../chatbot_associated_party_types.json | 2 +- .../doctype/chatbot_flow/chatbot_flow.json | 6 +- .../doctype/chatbot_log/chatbot_log.json | 2 +- .../chatbot_message_template.json | 31 +++- .../chatbot_message_template.py | 2 +- .../chatbot_party_type.json | 2 +- .../chatbot_party_type/chatbot_party_type.py | 2 +- .../doctype/chatbot_setup/chatbot_setup.json | 2 +- .../doctype/chatbot_setup/chatbot_setup.py | 4 +- chatbot/customization/after_migrate.py | 2 +- chatbot/hooks.py | 1 - chatbot/modules.txt | 2 +- chatbot/patches.txt | 2 +- chatbot/utils.py | 40 ++++- chatbot/webhook.py | 2 +- 19 files changed, 174 insertions(+), 105 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.gitignore b/.gitignore index ba04025..b1fde41 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ *.swp tags node_modules -__pycache__ \ No newline at end of file +__pycache__ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..81bf4f6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml diff --git a/README.md b/README.md index 1114aa4..82d3b09 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ Chatbot #### License -mit \ No newline at end of file +mit diff --git a/chatbot/api/telegram_api.py b/chatbot/api/telegram_api.py index 281ace3..16632aa 100644 --- a/chatbot/api/telegram_api.py +++ b/chatbot/api/telegram_api.py @@ -2,70 +2,33 @@ import requests import json from chatbot.chatbot.doctype.chatbot_log.chatbot_log import log_chatbot -from chatbot.utils import validate_user, get_root_chatbot_flow, get_associated_party_types, fetch_all_children +from chatbot.utils import validate_user, get_root_chatbot_flow, get_associated_party_types, fetch_all_children,send_document import hashlib from passlib.context import CryptContext passlibctx = CryptContext(schemes=["pbkdf2_sha256","argon2",], ) class TelegramAPI: def __init__(self, update,headers): - print(update) self.update = update self.headers=headers self.validate_token=False - secret_token_ft=self.headers.get("X-Telegram-Bot-Api-Secret-Token") - host=self.headers.get("X-Forwarded-Host") - proto=self.headers.get("X-Forwarded-Proto") - if proto !="https": - frappe.throw("Not an https Request", frappe.PermissionError) - if host !=frappe.db.get_value("Chatbot Setup","Chatbot Setup","telegram_webhook_url").strip()[8:]: - frappe.throw("Not an Host", frappe.PermissionError) - if secret_token_ft: - secret_token = frappe.get_doc("Chatbot Setup").get_password("secret_token") - if secret_token: - random_value=hashlib.sha256(secret_token_ft.encode()) - random_value=random_value.hexdigest() - if passlibctx.verify(random_value,secret_token): - self.validate_token =True - else: - frappe.throw("Verify Error", frappe.PermissionError) - else: - frappe.throw("StFxx0n0ecre Tnmx0naoke Error", frappe.PermissionError) - else: - frappe.throw("StFxx0n0ecre Tnmx0naoke Error FT", frappe.PermissionError) - self.token = frappe.get_doc("Chatbot Setup").get_password('telegram_api_token') - self.base_url = f"https://api.telegram.org/bot{self.token}/" - self.reply_text = str() - self.reply_markup = {} - self.data = str() - self.chat_id=str() - self.message_received=str() - - if "callback_query" in update: - self.callback_query =update.get('callback_query') - self.message = self.callback_query.get('message') - self.data =self.callback_query.get('data') - self.chat_id = self.message.get("chat").get("id") - self.user_name="@"+self.message.get("chat").get("username") - elif "message" in update: - self.message = update.get('message') + self._validate_token() + if self.validate_token: + self.set_default_values() - if self.message: - self.chat_id = self.message.get("chat").get("id") - self.user_name = "@"+self.message["chat"]["username"] - self.message_received=self.message.get("text") + def find_type_and_send(self): + if self.response_type == "Text": + self.send_message() else: - frappe.throw(msg="Message object not found") - + self.send_document(file_path=send_document(type=self.response_type)) def send_message(self, text:str =None): """Send a message to a Telegram chat, with optional inline buttons.""" url = f"{self.base_url}sendMessage" payload = { "chat_id": self.chat_id, "text": self.reply_text, - "reply_markup": self.reply_markup # Inline keyboard markup + "reply_markup":self.reply_markup# Inline keyboard markup } - print("payload",payload) response = requests.post(url, json=payload) log_chatbot( @@ -109,16 +72,16 @@ def send_photo(self, chat_id, photo_url): return response.json() - def send_document(self, chat_id, file_path): + def send_document(self, file_path): """Send a document (PDF or other file types) to a Telegram chat.""" url = f"{self.base_url}sendDocument" with open(file_path, 'rb') as file: files = {'document': file} payload = { - "chat_id": chat_id + "chat_id": self.chat_id } response = requests.post(url, files=files, data=payload) - + self.send_message() if response.status_code != 200: frappe.log_error(f"Error sending document: {response.text}", "Telegram API Error") return None @@ -138,58 +101,105 @@ def process_update(self): self.reply_text = "User not registered" self.send_message(self.reply_text) - + def _validate_token(self): + secret_token_ft=self.headers.get("X-Telegram-Bot-Api-Secret-Token") + host=self.headers.get("X-Forwarded-Host") + proto=self.headers.get("X-Forwarded-Proto") + if proto !="https": + frappe.throw("Not an https Request", frappe.PermissionError) + if host !=frappe.db.get_value("Chatbot Setup","Chatbot Setup","telegram_webhook_url").strip()[8:]: + frappe.throw("Not an Host", frappe.PermissionError) + if secret_token_ft: + secret_token = frappe.get_doc("Chatbot Setup").get_password("secret_token") + if secret_token: + random_value=hashlib.sha256(secret_token_ft.encode()) + random_value=random_value.hexdigest() + if passlibctx.verify(random_value,secret_token): + self.validate_token =True + else: + frappe.throw("Verify Error", frappe.PermissionError) + else: + frappe.throw("StFxx0n0ecre Tnmx0naoke Error", frappe.PermissionError) + else: + frappe.throw("StFxx0n0ecre Tnmx0naoke Error FT", frappe.PermissionError) def handle_message(self, party_type, party_name): """Handle incoming messages.""" # Determine chatbot flow and template - print("self.data",self.data) self.data=self.data if frappe.db.exists("Chatbot Flow",self.data) else None pre_chatbot_flow_name=frappe.cache.get_value(self.chat_id) pre_chatbot_flow_name=pre_chatbot_flow_name if frappe.db.exists("Chatbot Flow",pre_chatbot_flow_name) else None - print("pre_chatbot_flow_name",pre_chatbot_flow_name) parent_flow=get_root_chatbot_flow(party_type) if self.data: - - chatbot_flow = frappe.get_doc('Chatbot Flow', self.data) + + chatbot_flow = frappe.get_doc('Chatbot Flow', self.data) elif pre_chatbot_flow_name: chatbot_flow = frappe.get_doc('Chatbot Flow', pre_chatbot_flow_name) children = fetch_all_children(chatbot_flow.get('name')) - if children: + if children and self.received_reply_text and frappe.db.get_value("Chatbot Message Template",chatbot_flow.template,"is_get_value")==1: chatbot_flow = frappe.get_doc('Chatbot Flow', children[0].get("name")) else: chatbot_flow= parent_flow - - + + else: chatbot_flow=parent_flow - + associated_parties = get_associated_party_types(chatbot_flow.get('name')) children = fetch_all_children(chatbot_flow.get('name')) template = chatbot_flow.get('template') - - # Build reply markup (inline keyboard) - self.reply_markup = {"inline_keyboard": [], 'resize_keyboard': True} - print("children",children) - print("chatbot_flow",chatbot_flow) - default_children=[] - if chatbot_flow.get('name') !=parent_flow.get("name"): - default_children=[{"name":parent_flow.get("name"),"button_text":"Main Menu"}] - children=children+default_children - if children: - self.reply_markup["inline_keyboard"]= [ - [{"text": child.get('button_text'), "callback_data": child.get('name')} for child in children if child.get('button_text') ] - - ] - + chatbot_template = frappe.get_doc('Chatbot Message Template', template) + reply_markup=None + if chatbot_template.is_get_value==1: + reply_markup={"force_reply":True} + else: + inline_keyboard=[[]] + if children: + inline_keyboard= [ + [{"text": child.get('button_text'), "callback_data": child.get('name')} ] + for child in children if child.get('button_text') + ] + + if chatbot_flow.get('name') !=parent_flow.get("name"): + inline_keyboard[0].append({"text": "Main Menu", "callback_data":parent_flow.get("name") }) + reply_markup={"inline_keyboard": inline_keyboard, 'resize_keyboard': True} + self.reply_markup=reply_markup # Check if party_type is in associated parties if party_type in associated_parties: - chatbot_template = frappe.get_doc('Chatbot Message Template', template) kwargs = {party_type.lower(): party_name,"data":self.message_received} self.reply_text = chatbot_template.get_rendered_template(**kwargs) - print("reply_text",self.reply_text) - self.send_message() + self.response_type =chatbot_template.response_type + self.find_type_and_send() frappe.cache.set_value(self.chat_id,chatbot_flow.get('name')) def set_chat_id(self,party_type,party_name): - chat_id =frappe.db.get_value(party_type,party_name,"telegram_user_id") + chat_id = frappe.db.get_value(party_type,party_name,"telegram_user_id") if not chat_id or chat_id!=self.chat_id: - frappe.db.set_value(party_type,party_name,"telegram_user_id",self.chat_id) \ No newline at end of file + frappe.db.set_value(party_type,party_name,"telegram_user_id",self.chat_id) + def set_default_values(self): + self.token = frappe.get_doc("Chatbot Setup").get_password('telegram_api_token') + self.base_url = f"https://api.telegram.org/bot{self.token}/" + self.reply_text = str() + self.reply_markup = {} + self.data = str() + self.chat_id=str() + self.message_received=str() + self.received_reply_text=str() + + if "callback_query" in self.update: + self.callback_query =self.update.get('callback_query') + self.message = self.callback_query.get('message') + self.data =self.callback_query.get('data') + self.chat_id = self.message.get("chat").get("id") + self.user_name="@"+self.message.get("chat").get("username") + elif "message" in self.update: + self.message = self.update.get('message') + + if self.message: + + self.chat_id = self.message.get("chat").get("id") + self.user_name = "@"+self.message["chat"]["username"] + self.received_reply_text =self.message.get("reply_to_message") + if self.received_reply_text: + self.received_reply_text=self.received_reply_text.get("text") + self.message_received=self.message.get("text") + else: + frappe.throw(msg="Message object not found") diff --git a/chatbot/chatbot/doctype/chatbot_associated_party_types/chatbot_associated_party_types.json b/chatbot/chatbot/doctype/chatbot_associated_party_types/chatbot_associated_party_types.json index 086a8f2..5d9d11c 100644 --- a/chatbot/chatbot/doctype/chatbot_associated_party_types/chatbot_associated_party_types.json +++ b/chatbot/chatbot/doctype/chatbot_associated_party_types/chatbot_associated_party_types.json @@ -29,4 +29,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json index 8b5a92e..879bb0d 100644 --- a/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json +++ b/chatbot/chatbot/doctype/chatbot_flow/chatbot_flow.json @@ -93,14 +93,14 @@ "fieldname": "type", "fieldtype": "Select", "label": "Type", - "options": "\nButton\nText\nGet Value\nImage\nVideo\nDocument\nLocation", + "options": "\nButton\nText", "reqd": 1 } ], "index_web_pages_for_search": 1, "is_tree": 1, "links": [], - "modified": "2024-09-26 13:37:39.673202", + "modified": "2024-09-27 16:17:25.856464", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Flow", @@ -124,4 +124,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_log/chatbot_log.json b/chatbot/chatbot/doctype/chatbot_log/chatbot_log.json index eddd891..09c846d 100644 --- a/chatbot/chatbot/doctype/chatbot_log/chatbot_log.json +++ b/chatbot/chatbot/doctype/chatbot_log/chatbot_log.json @@ -125,4 +125,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json index e4adca5..65e0603 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.json @@ -8,14 +8,15 @@ "engine": "InnoDB", "field_order": [ "placeholder", - "enable_dynamic_response", "response_type", + "is_get_value", + "enable_dynamic_response", "template", + "attachment", "default_doctype", "print_format", "default_document", "report", - "attachment", "is_custom_function", "custom_function_path", "server_script", @@ -25,10 +26,11 @@ { "fieldname": "placeholder", "fieldtype": "Data", + "hidden": 1, "label": "Placeholder" }, { - "default": "0", + "default": "1", "fieldname": "enable_dynamic_response", "fieldtype": "Check", "label": "Enable Dynamic Response" @@ -36,9 +38,10 @@ { "fieldname": "response_type", "fieldtype": "Select", - "hidden": 1, + "in_list_view": 1, "label": "Response Type", - "options": "Text\nPrint format\nReport\nImage" + "options": "\nText\nPrint format\nReport\nImage", + "reqd": 1 }, { "depends_on": "eval:doc.enable_dynamic_response", @@ -47,6 +50,7 @@ "label": "Template" }, { + "depends_on": "eval:doc.response_type == \"Print format\"", "fieldname": "print_format", "fieldtype": "Link", "label": "Print format", @@ -55,10 +59,12 @@ { "fieldname": "default_document", "fieldtype": "Dynamic Link", + "hidden": 1, "label": "Default Document", "options": "default_doctype" }, { + "depends_on": "eval:doc.response_type == \"Report\"", "fieldname": "report", "fieldtype": "Link", "label": "Report", @@ -91,18 +97,27 @@ { "fieldname": "html_yzlg", "fieldtype": "HTML", - "options": "

Help

\n

Custom Function

\n

It contains the keyword arguments respective to the associated party names

\n

{Party Type} = {Party Name}

\n

Example: customer = \"customer_name\"

\n

So, make sure your custom function has **kwargs as a param to get values

\n
\n

Server Script

\n
\nres = {}\n\n#get the default arguments passed using form_dict.party_name\nif frappe.form_dict.customer: \n    customer = frappe.form_dict.customer\n    company = frappe.db.get_default('company')\n    res[\"customer_name\"] = customer\n    res[\"company\"] = company\n    res[\"phone\"] = \"9876543218\"\n    res[\"email\"] = \"kavin@aerele.in\"\n    res[\"website_url\"] = \"www.aerele.in\"\n    \n    #response should be passed in flags.response key : value dict\n    frappe.flags.response = res \n\n
" + "options": "

Help

\n

Custom Function

\n

It contains the keyword arguments respective to the associated party names

\n

{Party Type} = {Party Name}

\n

Example: customer = \"customer_name\"

\n

So, make sure your custom function has **kwargs as a param to get values

\n
\n

Server Script

\n
\nres = {}\n\n#get the default arguments passed using form_dict.party_name\nif frappe.form_dict.customer: \n    customer = frappe.form_dict.customer\n    company = frappe.db.get_default('company')\n    res[\"customer_name\"] = customer\n    res[\"company\"] = company\n    res[\"phone\"] = \"9876543218\"\n    res[\"email\"] = \"kavin@aerele.in\"\n    res[\"website_url\"] = \"www.aerele.in\"\n    \n    #response should be passed in flags.response key : value dict\n    frappe.flags.response = res \n\n
", + "read_only": 1 }, { + "depends_on": "eval:doc.response_type == \"Print format\"", "fieldname": "default_doctype", "fieldtype": "Link", "label": "Default Doctype", + "mandatory_depends_on": "eval:doc.response_type == \"Print format\"", "options": "DocType" + }, + { + "default": "1", + "fieldname": "is_get_value", + "fieldtype": "Check", + "label": "Requires Input" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-09-24 15:44:25.304492", + "modified": "2024-09-28 15:02:14.687617", "modified_by": "Administrator", "module": "Chatbot", "name": "Chatbot Message Template", @@ -125,4 +140,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py index b4aed6e..32ae497 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py @@ -27,4 +27,4 @@ def execute_server_script(self, **kwargs): if api_method: response = run_script(self.server_script, **kwargs).get('response') - return response \ No newline at end of file + return response diff --git a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json index 4cf01e6..2771b23 100644 --- a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json +++ b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.json @@ -43,4 +43,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py index d05ebd4..06d00ac 100644 --- a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py +++ b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py @@ -47,4 +47,4 @@ def create_customer_custom_field(party_name): ] } print(custom_fields) - create_custom_fields(custom_fields, update=True) \ No newline at end of file + create_custom_fields(custom_fields, update=True) diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json index 9c62ee8..0b05379 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.json @@ -115,4 +115,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py index 5b5272c..92bd7c6 100644 --- a/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py +++ b/chatbot/chatbot/doctype/chatbot_setup/chatbot_setup.py @@ -53,7 +53,7 @@ def set_webhook(self): url = f"https://api.telegram.org/bot{api_token}/setWebhook?url={webhook_url}&secret_token={s_token}&drop_pending_updates=True" try: - + response = requests.get(url) response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes @@ -63,7 +63,7 @@ def del_webhook(self): api_token = self.get_password("telegram_api_token") url=f"https://api.telegram.org/bot{api_token}/deleteWebhook?drop_pending_updates=1" try: - + response = requests.get(url) response.raise_for_status() # Raises an HTTPError for 4xx/5xx status codes diff --git a/chatbot/customization/after_migrate.py b/chatbot/customization/after_migrate.py index e585a3b..efccaaa 100644 --- a/chatbot/customization/after_migrate.py +++ b/chatbot/customization/after_migrate.py @@ -1,4 +1,4 @@ def after_migrate(): - pass \ No newline at end of file + pass diff --git a/chatbot/hooks.py b/chatbot/hooks.py index b4b8212..39bef44 100644 --- a/chatbot/hooks.py +++ b/chatbot/hooks.py @@ -243,4 +243,3 @@ # default_log_clearing_doctypes = { # "Logging DocType Name": 30 # days to retain logs # } - diff --git a/chatbot/modules.txt b/chatbot/modules.txt index 9f2bfd9..037aec8 100644 --- a/chatbot/modules.txt +++ b/chatbot/modules.txt @@ -1 +1 @@ -Chatbot \ No newline at end of file +Chatbot diff --git a/chatbot/patches.txt b/chatbot/patches.txt index f15c3a9..73efa6f 100644 --- a/chatbot/patches.txt +++ b/chatbot/patches.txt @@ -3,4 +3,4 @@ # Read docs to understand patches: https://frappeframework.com/docs/v14/user/en/database-migrations [post_model_sync] -# Patches added in this section will be executed after doctypes are migrated \ No newline at end of file +# Patches added in this section will be executed after doctypes are migrated diff --git a/chatbot/utils.py b/chatbot/utils.py index 4c87cfa..3178a3f 100644 --- a/chatbot/utils.py +++ b/chatbot/utils.py @@ -1,5 +1,9 @@ import frappe - +import os +import pdfkit +import json +from datetime import datetime +from frappe.www.printview import get_html_and_style def validate_user(user_name:str, service_name:str): party_list = frappe.db.get_all("Chatbot Party Type", pluck="name") @@ -40,3 +44,37 @@ def fetch_all_children(docname:str): ) return children +def send_document(base_html=None,name=None,options = {'orientation':'Portrait'},type = "pdf"): + if type == "Report": + path = os.getcwd()+frappe.utils.get_site_base_path()[1:]+"/public/files/General Ledger.pdf" + else: + path = os.getcwd()+frappe.utils.get_site_base_path()[1:]+"/public/files/SAL-ORD-2024-00006.pdf" + if type == "pdf_value": + now = datetime.now() + now = now.strftime("%d-%m-%Y") + statement_id =str(name)+"_"+str(now) + path = os.getcwd()+frappe.utils.get_site_base_path()[1:]+"/public/files/"+statement_id+".pdf" + pdfkit.from_string(base_html, path,options={'orientation':'Portrait'}) + return path +def send_file_contet(path): + with open(path, 'rb') as file: + return file +def get_prinformat_html(doctype,name): + base_html=get_html_and_style(doc=doctype,name=name) + base_html=""" """+base_html.get("style")+base_html.get("html")+" " + return base_html +def get_report_html(report,filters=None): + base_html="" + if not filters: + filters= '{"company":"A (Demo)","from_date":"2024-08-27","to_date":"2024-09-27","group_by":"Group by Voucher (Consolidated)","include_dimensions":1,"show_opening_entries":0,"include_default_book_entries":1,"show_cancelled_entries":0,"show_net_values_in_party_account":0,"add_values_in_transaction_currency":0,"show_remarks":0,"ignore_err":0,"ignore_cr_dr_notes":0}' + if report == "General Ledger": + report_get_htm_doc=frappe.new_doc("Auto Email Report") + report_get_htm_doc.report=report + report_get_htm_doc.filters =filters + report_get_htm_doc.report_type="Script Report" + report_get_htm_doc.user="Administrator" + report_get_htm_doc.name="General Ledger" + report_get_htm_doc.description="General Ledger" + report_get_htm_doc.format = "HTML" + base_html=report_get_htm_doc.get_report_content() + return base_html diff --git a/chatbot/webhook.py b/chatbot/webhook.py index 29b7118..c3d90dd 100644 --- a/chatbot/webhook.py +++ b/chatbot/webhook.py @@ -23,4 +23,4 @@ def telegram_webhook(): # Log the error and return an error response frappe.log_error(title="Error processing webhook" ,message=frappe.get_traceback(with_context=1)) - return {"status": "error", "message": "Failed to process update"}, 500 \ No newline at end of file + return {"status": "error", "message": "Failed to process update"}, 500 From fb5df4f13623a77a5a56c9b4881edf42c6728765 Mon Sep 17 00:00:00 2001 From: DHINESH00 <18csa09@karpagamtech.ac.in> Date: Tue, 24 Dec 2024 18:17:29 +0530 Subject: [PATCH 7/7] chore: remove test print statements --- .../chatbot_message_template/chatbot_message_template.py | 6 ------ .../doctype/chatbot_party_type/chatbot_party_type.py | 2 -- 2 files changed, 8 deletions(-) diff --git a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py index 32ae497..3195dd9 100644 --- a/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py +++ b/chatbot/chatbot/doctype/chatbot_message_template/chatbot_message_template.py @@ -8,22 +8,16 @@ class ChatbotMessageTemplate(Document): def get_rendered_template(self, **kwargs): - print("in get_rendered_template") if self.enable_dynamic_response and self.template: - print("in validae") if not self.is_custom_function and self.server_script: - print("in server_script") template_data = self.execute_server_script(**kwargs) return self.template.format(**template_data).strip() return self.template def execute_server_script(self, **kwargs): - print() api_method = frappe.db.get_value('Server Script', {'name':self.server_script, 'script_type':'API'}, 'api_method') - print("api_method",api_method) - print("kwargs",kwargs) if api_method: response = run_script(self.server_script, **kwargs).get('response') diff --git a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py index 06d00ac..27f2e00 100644 --- a/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py +++ b/chatbot/chatbot/doctype/chatbot_party_type/chatbot_party_type.py @@ -14,7 +14,6 @@ def create_customer_custom_field(party_name): enable_telegram,enable_whatsapp,enable_slack=frappe.db.get_value("Chatbot Setup","Chatbot Setup",["enable_telegram","enable_whatsapp","enable_slack"]) insert_afrter_fieldname= frappe.get_meta(party_name) insert_afrter_fieldname=insert_afrter_fieldname.fields[-1].get("fieldname") - print(insert_afrter_fieldname) custom_fields = {} if enable_telegram: custom_fields = { @@ -46,5 +45,4 @@ def create_customer_custom_field(party_name): ), ] } - print(custom_fields) create_custom_fields(custom_fields, update=True)