PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/__init__.py

https://bitbucket.org/khagesh93/search-skill
Python | 178 lines | 144 code | 8 blank | 26 comment | 0 complexity | 2f12d0f9205e6795c9aca65f898fa5b5 MD5 | raw file
Possible License(s): GPL-3.0
  1. # -*- coding: utf-8 -*-
  2. # TODO: Add an appropriate license to your skill before publishing. See
  3. # the LICENSE file for more information.
  4. # Below is the list of outside modules you'll be using in your skill.
  5. # They might be built-in to Python, from mycroft-core or from external
  6. # libraries. If you use an external library, be sure to include it
  7. # in the requirements.txt file so the library is installed properly
  8. # when the skill gets installed later by a user.
  9. from os.path import dirname, abspath, join
  10. from adapt.intent import IntentBuilder
  11. from mycroft.skills.core import MycroftSkill, intent_handler
  12. from mycroft.util.log import LOG
  13. from googletrans import Translator
  14. import os # for setting google credentials
  15. import urllib2 # for http requests
  16. from pprint import pprint # for pretty printing json
  17. import json # for parsing json
  18. import sys
  19. import paho.mqtt.client as mqtt
  20. from mycroft.skills.skill_data import load_regex
  21. from mycroft.configuration.Constants import *
  22. # Each skill is contained within its own class, which inherits base methods
  23. # from the MycroftSkill class. You extend this class as shown below.
  24. # TODO: Change "Template" to a unique name for your skill
  25. class Search(MycroftSkill):
  26. # Let's define the class objects here.
  27. ddg_topic_summaries_endpoint = "https://api.duckduckgo.com/?q={}&format=json&pretty=1"
  28. ddg_search_topic_details_endpoint = "{}?ia=about&format=json"
  29. limit = 3
  30. numbers = {0: "शून्य", 1: "एक", 2: "दो", 3: "तीन", 4: "चार", 5: "पाँच", 6: "छः", 7: "सात", 8: "आठ", 9: "नौ",
  31. 10: "दस"}
  32. search_results = []
  33. # The constructor of the skill, which calls MycroftSkill's constructor
  34. def __init__(self):
  35. super(Search, self).__init__(name="Search")
  36. # Initialize working variables used within the skill.
  37. self.count = 0
  38. self.translator = Translator()
  39. reload(sys)
  40. sys.setdefaultencoding('utf8')
  41. def initialize(self):
  42. #load_regex(self.regex_dir, self.emitter, self.skill_id)
  43. self.add_tag_handler("KnowMoreDuckDuckGo", self.handle_know_more_search)
  44. # The "handle_xxxx_intent" function is triggered by Mycroft when the
  45. # skill's intent is matched. The intent is defined by the IntentBuilder()
  46. # pieces, and is triggered when the user's utterance matches the pattern
  47. # defined by the keywords. In this case, the match occurs when one word
  48. # is found from each of the files:
  49. # vocab/en-us/Hello.voc
  50. # vocab/en-us/World.voc
  51. # In this example that means it would match on utterances like:
  52. # 'Hello world'
  53. # 'Howdy you great big world'
  54. # 'Greetings planet earth'
  55. @intent_handler(IntentBuilder("").require("Query"))
  56. def handle_search_intent(self, message):
  57. # In this case, respond by simply speaking a canned response.
  58. # Mycroft will randomly speak one of the lines from the file
  59. # dialogs/en-us/hello.world.dialog
  60. # if message.data.get('topic') is None and message.data.get('w_topic') is None:
  61. # LOG.info("===> Couldn't find topic")
  62. # LOG.info(message.data)
  63. # else:
  64. # LOG.info("===> found topic")
  65. # LOG.info(message.data.keys())
  66. # LOG.info(message.data)
  67. # LOG.info(message.data["w_topic"])
  68. LOG.info("Handle search called")
  69. translation = self.translator.translate(message.data.get("Query"), dest='en').text
  70. # LOG.info(translation['translatedText'])
  71. query = "+".join(translation.split(" "))
  72. endpoint = self.ddg_topic_summaries_endpoint.format(query)
  73. # #ctx = ssl._create_unverified_context()
  74. #
  75. contents = urllib2.urlopen(endpoint).read()
  76. data = json.loads(contents)
  77. LOG.info(data)
  78. #
  79. abstract = data["AbstractText"]
  80. if abstract:
  81. abstract_text_hindi = self.translator.translate(abstract, src='hi').text
  82. LOG.info(abstract_text_hindi)
  83. message.data["speak"] = abstract_text_hindi
  84. self.publish(message.data[MESSAGE_TOPIC], message.data)
  85. return
  86. else:
  87. array = []
  88. search_results = []
  89. message.data["context"] = {}
  90. for i, topic in enumerate(data["RelatedTopics"]):
  91. if not ("Text" in topic):
  92. continue
  93. text = topic["Text"]
  94. if text.find("...") != -1:
  95. text = text.split("...")[0]
  96. if text.find(".") != -1:
  97. text = text[:text.rfind(".")]
  98. elif text.find("!") != -1:
  99. text = text[:text.rfind("!")]
  100. elif text.find(";") != -1:
  101. text = text[:text.rfind(";")]
  102. elif text.find(",") != -1:
  103. text = text[:text.rfind(",")]
  104. else:
  105. text = text
  106. abstract_text_hindi = self.translator.translate(text, src='hi').text
  107. array.append(self.numbers[i + 1] + ", " + abstract_text_hindi + ", की बात कर रहे हैं?")
  108. search_results.append({"text": abstract_text_hindi, "url": topic["FirstURL"]})
  109. if i == self.limit - 1:
  110. break
  111. LOG.info("+==========+")
  112. message.data["context"]["options"] = search_results
  113. message.data["tags"] = ["KnowMoreDuckDuckGo"]
  114. message.data["speak"] = 'मुझे ' + message.data.get("Query") + 'के बारे में बहुतेरे रिजल्ट मिले हैं। क्या आप' + " या, ".join(array)
  115. self.publish(message.data[MESSAGE_TOPIC], message.data)
  116. # @intent_handler(IntentBuilder("").require('SelectSearch')
  117. # .require('KnowMoreContext').build())
  118. def handle_know_more_search(self, message):
  119. LOG.info("Know more called!!")
  120. LOG.info(self.local_regex)
  121. LOG.info("Know more called!!")
  122. regex_result = self.fill_message_using_regex(message.data.get("utterances")[0], "select.search")
  123. LOG.info("Know more called1!!")
  124. message.data["tags"] = []
  125. if "SelectSearch" not in regex_result:
  126. LOG.info("Not able to match regex")
  127. return
  128. LOG.info("Know more called!!")
  129. search_select = regex_result.get("SelectSearch")
  130. search_results = message.data["context"]["options"]
  131. # here we need to calculate the distance in sets of the query SelectSearch
  132. # and the variables we have stored in self.search_results. Whichever has the least
  133. # distance, we should output the DDG results from that link
  134. input_set = set(map(lambda x: x.lower(), search_select.split(" ")))
  135. count = sys.maxint
  136. select = -1
  137. for i, entry in enumerate(search_results):
  138. super_set = set(map(lambda x: x.lower(), entry["text"].split(" ")))
  139. if len(input_set - super_set) < count:
  140. count = len(input_set - super_set)
  141. select = i
  142. if select == -1:
  143. message.data["speak"] = "माफ कीजिएगा किसी परेशानी की वजह से हम बैकएंड से अपडेट नहीं ला पाए। कृपया दुबारा कोशिश करें"
  144. else:
  145. endpoint = self.ddg_search_topic_details_endpoint.format(search_results[select]["url"])
  146. contents = urllib2.urlopen(endpoint).read()
  147. data = json.loads(contents)
  148. abstract = data["AbstractText"]
  149. if abstract:
  150. abstract_text_hindi = self.translator.translate(abstract, src='hi').text
  151. message.data["speak"] = abstract_text_hindi
  152. else:
  153. message.data["speak"] = "माफ कीजिएगा किसी परेशानी की वजह से हम बैकएंड से अपडेट नहीं ला पाए। कृपया दुबारा कोशिश करें"
  154. self.publish(message.data[MESSAGE_TOPIC], message.data)
  155. # The "create_skill()" method is used to create an instance of the skill.
  156. # Note that it's outside the class itself.
  157. def create_skill():
  158. return Search()