PageRenderTime 66ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/messengerbot/services/internet_services/KitMensaService.py

https://gitlab.com/namboy94/messengerbot
Python | 230 lines | 189 code | 7 blank | 34 comment | 0 complexity | 87437c2033e7a68d7524c302ea925895 MD5 | raw file
  1. # coding=utf-8
  2. """
  3. Copyright 2015,2016 Hermann Krumrey
  4. This file is part of messengerbot.
  5. messengerbot makes use of various third-party python modules to serve
  6. information via the online chat services.
  7. messengerbot is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11. messengerbot is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with messengerbot. If not, see <http://www.gnu.org/licenses/>.
  17. """
  18. # imports
  19. import re
  20. import requests
  21. from bs4 import BeautifulSoup
  22. from typing import Tuple
  23. from messengerbot.servicehandlers.Service import Service
  24. from messengerbot.connection.generic.Message import Message
  25. class KitMensaService(Service):
  26. """
  27. The KitMensaService Class that extends the generic Service class.
  28. The service fetches the current Mensa plan for the Mensa at the Karlsruhe
  29. Institute of Technology (KIT)
  30. """
  31. identifier = "kit_mensa"
  32. """
  33. The identifier for this service
  34. """
  35. help_description = {"en": "/mensa\tSends the Mensa Plan\n"
  36. "syntax: /mensa [<line>] [tomorrow]",
  37. "de": "/mensa\tSchickt den Mensa Plan\n"
  38. "syntax: /mensa [<linie>] [morgen]"}
  39. """
  40. Help description for this service.
  41. """
  42. mensa_line = {"1": "",
  43. "2": "",
  44. "3": "",
  45. "4": "",
  46. "5": "",
  47. "6": "",
  48. "schnitzelbar": "",
  49. "curry queen": "",
  50. "abend": "",
  51. "cafeteria vormittag": "",
  52. "cafeteria nachmittag": ""}
  53. line_order = {0: "1",
  54. 1: "2",
  55. 2: "3",
  56. 3: "4",
  57. 4: "5",
  58. 5: "6",
  59. 6: "schnitzelbar",
  60. 7: "curry queen",
  61. 8: "abend",
  62. 9: "cafeteria vormittag",
  63. 10: "cafeteria nachmittag"}
  64. """
  65. Dictionary that keeps track of the offering at every line
  66. """
  67. line_key = {"line": "en",
  68. "linie": "de"}
  69. """
  70. The phrase for line in different languages
  71. """
  72. tomorrow_key = {"tomorrow": "en",
  73. "morgen": "de"}
  74. """
  75. The phrase for tomorrow in different languages
  76. """
  77. closed = False
  78. """
  79. Set to True if the mensa is closed for the day
  80. """
  81. closed_message = {"en": "The mensa is closed today",
  82. "de": "Die Mensa ist heute geschlossen"}
  83. """
  84. Message to be sent if the Mensa is closed
  85. """
  86. def process_message(self, message: Message) -> None:
  87. """
  88. Process a message according to the service's functionality
  89. :param message: the message to process
  90. :return: None
  91. """
  92. language, line, tomorrow = self.parse_user_input(message.message_body.lower())
  93. self.get_current_info(tomorrow)
  94. if self.closed:
  95. reply = self.closed_message[language]
  96. elif line == "all":
  97. reply = ""
  98. first = False
  99. for line_no in range(0, len(self.mensa_line)):
  100. if first:
  101. reply += self.mensa_line[self.line_order[line_no]]
  102. first = False
  103. else:
  104. reply += "\n" + self.mensa_line[self.line_order[line_no]]
  105. else:
  106. reply = self.mensa_line[line]
  107. reply_message = self.generate_reply_message(message, "KIT Mensa", reply)
  108. self.send_text_message(reply_message)
  109. @staticmethod
  110. def regex_check(message: Message) -> bool:
  111. """
  112. Checks if the user input is valid for this service to continue
  113. :return: True if input is valid, False otherwise
  114. """
  115. regex = "^/(mensa)( )?(" + Service.regex_string_from_dictionary_keys([KitMensaService.line_key])
  116. regex += " (1|2|3|4|5|6)|schnitzelbar|curry queen|abend|cafeteria vormittag|cafeteria nachmittag)?( "
  117. regex += Service.regex_string_from_dictionary_keys([KitMensaService.tomorrow_key])
  118. regex += ")?$"
  119. return re.search(re.compile(regex), message.message_body.lower())
  120. def get_current_info(self, tomorrow: bool = False) -> None:
  121. """
  122. Fetches the current info either for today or tomorrow and stores them in a local dictionary
  123. :param tomorrow: can be set to True to get the information for tomorrow
  124. :return: None
  125. """
  126. try:
  127. if tomorrow:
  128. url = "http://mensa.akk.uni-karlsruhe.de/?DATUM=morgen&uni=1"
  129. else:
  130. url = "http://mensa.akk.uni-karlsruhe.de/?DATUM=heute&uni=1"
  131. html = requests.get(url).text
  132. soup = BeautifulSoup(html, "html.parser")
  133. resource = soup.select('body')
  134. body = resource[0].text
  135. self.mensa_line["1"] = "Linie 1\n" + body.split("Linie 1:\n", 1)[1].split("Linie 2:", 1)[0]
  136. self.mensa_line["2"] = "Linie 2\n" + body.split("Linie 2:\n", 1)[1].split("Linie 3:", 1)[0]
  137. self.mensa_line["3"] = "Linie 3\n" + body.split("Linie 3:\n", 1)[1].split("Linie 4/5:", 1)[0]
  138. self.mensa_line["4"] = "Linie 4/5\n" + body.split("Linie 4/5:\n", 1)[1].split("Schnitzelbar:", 1)[0]
  139. self.mensa_line["5"] = self.mensa_line["4"]
  140. self.mensa_line["6"] = "L6 Update\n" + body.split("L6 Update:\n", 1)[1].split("Abend:", 1)[0]
  141. self.mensa_line["abend"] = "Abend\n" + body.split("Abend:\n", 1)[1].split("Curry Queen:", 1)[0]
  142. self.mensa_line["schnitzelbar"] = \
  143. "Schnitzelbar\n" + body.split("Schnitzelbar:\n", 1)[1].split("L6 Update:", 1)[0]
  144. self.mensa_line["curry queen"] = \
  145. "Curry Queen\n" + body.split("Curry Queen:\n", 1)[1].split("Cafeteria Heiße Theke:", 1)[0]
  146. self.mensa_line["cafeteria vormittag"] = \
  147. "Cafeteria Heiße Theke\n" + \
  148. body.split("Cafeteria Heiße Theke:\n", 1)[1].split("Cafeteria ab 14:30:", 1)[0]
  149. self.mensa_line["cafeteria nachmittag"] = \
  150. "Cafeteria ab 14:30\n" + body.split("Cafeteria ab 14:30:\n", 1)[1].split("Stand:", 1)[0]
  151. except IndexError:
  152. self.closed = True
  153. def parse_user_input(self, user_input: str) -> Tuple[str, str, bool]:
  154. """
  155. Parses the user's input
  156. :param user_input: the input to be parsed
  157. :return: the language, the selected line, if today's or tomorrow's plan should be fetched
  158. """
  159. language = self.connection.last_used_language
  160. # Check if only /mensa is entered, if not, strip away /mensa_
  161. try:
  162. user_input = user_input.split("/mensa ")[1]
  163. except IndexError:
  164. return language, "all", False
  165. options = user_input.split(" ") # Split up all words into seperate strings
  166. # Check if the plan for tomorrow should be fetched
  167. tomorrow = False
  168. for key in self.tomorrow_key:
  169. if key in options:
  170. tomorrow = True
  171. # If tomorrow is the only option, select all lines
  172. if options[0] in self.tomorrow_key:
  173. language = self.tomorrow_key[options[0]]
  174. return language, "all", True
  175. # Otherwise check which line
  176. else:
  177. if tomorrow:
  178. options.pop() # Remove the tomorrow keyword
  179. line = ""
  180. for option in options:
  181. line += option + " "
  182. line = line.rstrip()
  183. for key in self.line_key:
  184. if key in line:
  185. language = self.line_key[key]
  186. line = line.replace(key + " ", "")
  187. return language, line, tomorrow