| import frappe |
| import requests |
| from frappe import _ |
| from frappe.utils import sanitize_html |
| from frappe.utils.global_search import search |
| from html2text import html2text |
| from jinja2 import utils |
| |
| |
| def get_context(context): |
| context.no_cache = 1 |
| if frappe.form_dict.q: |
| query = str(utils.escape(sanitize_html(frappe.form_dict.q))) |
| context.title = _("Help Results for") |
| context.query = query |
| |
| context.route = "/search_help" |
| d = frappe._dict() |
| d.results_sections = get_help_results_sections(query) |
| context.update(d) |
| else: |
| context.title = _("Docs Search") |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_help_results_sections(text): |
| out = [] |
| settings = frappe.get_doc("Support Settings", "Support Settings") |
| |
| for api in settings.search_apis: |
| results = [] |
| if api.source_type == "API": |
| response_json = get_response(api, text) |
| topics_data = get_topics_data(api, response_json) |
| results = prepare_api_results(api, topics_data) |
| else: |
| # Source type is Doctype |
| doctype = api.source_doctype |
| raw = search(text, 0, 20, doctype) |
| results = prepare_doctype_results(api, raw) |
| |
| if results: |
| # Add section |
| out.append({"title": api.source_name, "results": results}) |
| |
| return out |
| |
| |
| def get_response(api, text): |
| response = requests.get( |
| api.base_url + "/" + api.query_route, data={api.search_term_param_name: text} |
| ) |
| |
| response.raise_for_status() |
| return response.json() |
| |
| |
| def get_topics_data(api, response_json): |
| if not response_json: |
| response_json = {} |
| topics_data = {} # it will actually be an array |
| key_list = api.response_result_key_path.split(",") |
| |
| for key in key_list: |
| topics_data = response_json.get(key) if not topics_data else topics_data.get(key) |
| |
| return topics_data or [] |
| |
| |
| def prepare_api_results(api, topics_data): |
| if not topics_data: |
| topics_data = [] |
| |
| results = [] |
| for topic in topics_data: |
| route = api.base_url + "/" + (api.post_route + "/" if api.post_route else "") |
| for key in api.post_route_key_list.split(","): |
| route += str(topic[key]) |
| |
| results.append( |
| frappe._dict( |
| { |
| "title": topic[api.post_title_key], |
| "preview": html2text(topic[api.post_description_key]), |
| "route": route, |
| } |
| ) |
| ) |
| return results[:5] |
| |
| |
| def prepare_doctype_results(api, raw): |
| results = [] |
| for r in raw: |
| prepared_result = {} |
| parts = r["content"].split(" ||| ") |
| |
| for part in parts: |
| pair = part.split(" : ", 1) |
| prepared_result[pair[0]] = pair[1] |
| |
| results.append( |
| frappe._dict( |
| { |
| "title": prepared_result[api.result_title_field], |
| "preview": prepared_result[api.result_preview_field], |
| "route": prepared_result[api.result_route_field], |
| } |
| ) |
| ) |
| |
| return results |