querying.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import random
  2. import threading
  3. import time
  4. import requests
  5. from requests_html import HTMLSession
  6. from rollbot import RollbotResponse, RollbotFailure, as_plugin, pop_arg
  7. from config import get_config, get_secret
  8. from .util import upload_image
  9. @as_plugin
  10. def inspire(message):
  11. argstr = message.raw_args
  12. if argstr is not None and "explain" in argstr:
  13. return "Using the command !inspire will request an inspiration image from http://inspirobot.me/"
  14. try:
  15. url = requests.get("http://inspirobot.me/api?generate=true").text
  16. return RollbotResponse(message, img=url)
  17. except ConnectionError as e:
  18. return RollbotResponse(
  19. message,
  20. failure=RollbotFailure.SERVICE_DOWN,
  21. debugging={
  22. "explain": "Could not reach inspirobot.",
  23. "exception": e
  24. }
  25. )
  26. @as_plugin
  27. def shield(message):
  28. data = """\
  29. ------RollbotBoundary\r\n\
  30. Content-Disposition: form-data; name=\"blazon\"\r\n\
  31. \r\n\
  32. %s\r\n\
  33. ------RollbotBoundary\r\n\
  34. Content-Disposition: form-data; name=\"asfile\"\r\n\
  35. \r\n\
  36. 1\r\n\
  37. ------RollbotBoundary\r\n\
  38. Content-Disposition: form-data; name=\"palette\"\r\n\
  39. \r\n\
  40. wappenwiki\r\n\
  41. ------RollbotBoundary\r\n\
  42. Content-Disposition: form-data; name=\"effect\"\r\n\
  43. \r\n\
  44. flat\r\n\
  45. ------RollbotBoundary\r\n\
  46. Content-Disposition: form-data; name=\"size\"\r\n\
  47. \r\n\
  48. 500\r\n\
  49. ------RollbotBoundary
  50. """ % message.raw_args
  51. # TODO - this should probably have a random number as part of the boundary
  52. try:
  53. r = requests.post(
  54. "https://drawshield.net/include/drawshield.php",
  55. headers={
  56. 'Content-Type': "multipart/form-data; boundary=----RollbotBoundary",
  57. 'Cache-Control': "no-cache",
  58. },
  59. data=data
  60. )
  61. except ConnectionError as e:
  62. return RollbotResponse(
  63. message,
  64. failure=RollbotFailure.SERVICE_DOWN,
  65. debugging={
  66. "explain": "Could not reach DrawShield.",
  67. "exception": e,
  68. }
  69. )
  70. success, result = upload_image(get_secret("imgur_client_id"), r.content)
  71. if success:
  72. return RollbotResponse(message, img=result)
  73. else:
  74. return RollbotResponse(
  75. message,
  76. failure=RollbotFailure.SERVICE_DOWN,
  77. debugging=result
  78. )
  79. @as_plugin
  80. def scp(message):
  81. number, _ = pop_arg(message.raw_args)
  82. try:
  83. number = int(number.strip())
  84. except ValueError as e:
  85. return RollbotResponse(
  86. message,
  87. failure=RollbotFailure.INVALID_ARGUMENTS,
  88. debugging={
  89. "explain": "Could not parse argument %s into integer." % number,
  90. "exception": e,
  91. }
  92. )
  93. page_url = "http://www.scp-wiki.net/scp-%03d" % number
  94. series_url = "http://www.scp-wiki.net/scp-series"
  95. series = (number // 1000) + 1
  96. if series != 1:
  97. series_url += "-" + str(series)
  98. sesh = HTMLSession()
  99. r = sesh.get(page_url)
  100. r2 = sesh.get(series_url)
  101. ps = r.html.find("p")
  102. lis = r2.html.find("li")
  103. object_class = "Error retrieving object class!"
  104. for p in ps:
  105. if "Object Class" in p.text:
  106. object_class = p.text
  107. break
  108. query = "SCP-%03d" % number
  109. flavortext = "Error retrieving title!"
  110. for li in lis:
  111. if query in li.text:
  112. flavortext = li.text.split("-", 2)[-1].strip()
  113. break
  114. response = "Item # %d\n" % number
  115. response += object_class + "\n"
  116. response += flavortext + "\n"
  117. response += page_url
  118. return response
  119. def get_riddle(sesh, logger):
  120. n = random.randint(2, 7545)
  121. r = sesh.get(f"https://www.riddles.com/{n:d}")
  122. divs = r.html.find("div")
  123. panel_bodies = [d.text for d in divs if "class" in d.attrs and "panel-body" in d.attrs["class"]]
  124. if len(panel_bodies) <= 1:
  125. logger.info(f"Failed on {n:d} - invalid page")
  126. return n, None
  127. riddle = panel_bodies[0]
  128. if riddle.startswith("Riddle Status: User Rejected") or riddle.startswith("Riddle Status: User Moderated"):
  129. logger.info(f"Failed on {n:d} - rejected")
  130. return n, None
  131. parts = riddle.split("\n")
  132. logger.info(f"Returning riddle {n:d}")
  133. return n, (parts[1], parts[3])
  134. def get_answer_cb(bot, message, riddle):
  135. gid = message.group_id
  136. txt = "\n\n".join(("Here's the riddle answer from before!", *riddle))
  137. def cb():
  138. time.sleep(get_config("riddle.sleep_time"))
  139. bot.manually_post_message(txt, gid)
  140. return cb
  141. @as_plugin
  142. def riddle(bot, message, log):
  143. if message.raw_args is None or message.raw_args != "me piss":
  144. return RollbotResponse(message, failure=RollbotFailure.INVALID_ARGUMENTS)
  145. sesh = HTMLSession()
  146. n = 0
  147. riddle = None
  148. while riddle is None:
  149. rnum, riddle = get_riddle(sesh, log)
  150. n += 1
  151. if n > 20:
  152. return RollbotResponse(message, failure=RollbotFailure.SERVICE_DOWN)
  153. threading.Thread(target=get_answer_cb(bot, message, riddle)).start()
  154. return "\n\n".join((
  155. f"Riddle #{rnum}",
  156. riddle[0],
  157. f"I'll post the response in about {get_config('riddle.sleep_time')} seconds!",
  158. ))
  159. @as_plugin
  160. def fortune():
  161. sesh = HTMLSession()
  162. r = sesh.get("http://www.fortunecookiemessage.com/")
  163. quote = r.html.xpath("//div[contains(@class, 'quote')]/a")[0].text
  164. learn, lotto = [x.split(":", 1)[-1].strip() for x in r.html.xpath("//div[contains(@class, 'bottom-message')]")[0].text.split("\n")[:2]]
  165. return f"'{quote}'\nLucky Numbers: {lotto}\nLearn Chinese: {learn}"
  166. def run_upload(message, img_data):
  167. success, result = upload_image(get_secret("imgur_client_id"), img_data)
  168. if success:
  169. return RollbotResponse(message, img=result)
  170. else:
  171. return RollbotFailure.SERVICE_DOWN.with_reason(result["explain"]).with_exception(result["exception"])
  172. @as_plugin
  173. def selfie(message):
  174. try:
  175. r = requests.get("https://cdn.star.nesdis.noaa.gov/GOES16/ABI/SECTOR/ne/GEOCOLOR/latest.jpg")
  176. except ConnectionError as e:
  177. return RollbotFailure.SERVICE_DOWN.with_reason("Could not reach GOES16.").with_exception(e)
  178. return run_upload(message, r.content)
  179. @as_plugin
  180. def cat(message):
  181. try:
  182. r = requests.get("https://thiscatdoesnotexist.com/", headers={ "User-Agent": "Rollbot" })
  183. except ConnectionError as e:
  184. return RollbotFailure.SERVICE_DOWN.with_reason("Could not reach cat generator.").with_exception(e)
  185. return run_upload(message, r.content)