querying.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. from logging import Logger
  2. import random
  3. import asyncio
  4. from bs4 import BeautifulSoup
  5. from rollbot import as_command, RollbotFailure, Attachment
  6. from rollbot.injection import Request, Args, Arg, Config
  7. @as_command
  8. async def inspire(req: Request, logger: Logger):
  9. """
  10. Using the command !inspire will request an inspiration image from http://inspirobot.me/
  11. """
  12. try:
  13. async with req.get("http://inspirobot.me/api?generate=true") as res:
  14. return await res.text()
  15. except:
  16. logger.exception("Failed !inspire")
  17. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Could not reach inspirobot")
  18. @as_command
  19. async def shield(req: Request, blazon: Args, logger: Logger):
  20. try:
  21. async with req.post(
  22. "https://drawshield.net/include/drawshield.php",
  23. headers={
  24. "Content-Type": "multipart/form-data; boundary=----RollbotBoundary",
  25. "Cache-Control": "no-cache",
  26. },
  27. data={
  28. "blazon": blazon,
  29. "asfile": 1,
  30. "palette": "wappenwiki",
  31. "effect": "flat",
  32. "size": 500,
  33. },
  34. ) as res:
  35. res.raise_for_status()
  36. return Attachment("image", await res.read())
  37. except:
  38. logger.exception("Failed !shield")
  39. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Could not reach DrawShield")
  40. @as_command
  41. async def scp(
  42. number: Arg(0, convert=int, fail_msg="Could not parse argument {} into integer"), req: Request
  43. ):
  44. page_url = f"http://www.scp-wiki.net/scp-{number:03d}"
  45. series_url = "http://www.scp-wiki.net/scp-series"
  46. series = (number // 1000) + 1
  47. if series != 1:
  48. series_url += "-" + str(series)
  49. async def get_obj_class():
  50. async with req.get(page_url) as page:
  51. page_html = BeautifulSoup(await page.text(), "html.parser")
  52. for p in page_html.find_all("p"):
  53. if "Object Class" in p.text:
  54. return p.text
  55. return "Error retrieving object class!"
  56. query = f"SCP-{number:03d}"
  57. async def get_title():
  58. async with req.get(series_url) as series:
  59. series_html = BeautifulSoup(await series.text(), "html.parser")
  60. for li in series_html.find_all("li"):
  61. if query in li.text:
  62. return li.text.split("-", 2)[-1].strip()
  63. return "Error retrieving title!"
  64. obj_class, title = await asyncio.gather(get_obj_class(), get_title())
  65. return f"Item # {number}\n{obj_class}\n{title}\n{page_url}"
  66. @as_command
  67. async def riddle(args: Args, req: Request, logger: Logger, sleep: Config("riddle.sleep")):
  68. if args.lower() != "me piss":
  69. RollbotFailure.INVALID_ARGUMENTS.raise_exc()
  70. rnum = None
  71. riddle = None
  72. for n in range(20):
  73. rnum = random.randint(2, 10050)
  74. async with req.get(f"https://www.riddles.com/{rnum}") as res:
  75. riddle_page = BeautifulSoup(await res.text(), "html.parser")
  76. riddle_panel = riddle_page.find("div", class_="panel-body")
  77. if riddle_panel is not None:
  78. parts = [p.text for p in riddle_panel.find_all("p")]
  79. if (
  80. len(parts) == 2
  81. and not parts[0].startswith("Riddle Status: User Rejected")
  82. and not parts[0].startswith("Riddle Status: User Moderated")
  83. ):
  84. riddle = parts[0]
  85. answer = parts[1]
  86. break
  87. logger.info(f"Failed to parse riddle #{rnum}, attempt #{n}")
  88. else:
  89. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to find a riddle fast enough")
  90. yield "\n\n".join(
  91. (
  92. f"Riddle #{rnum}",
  93. riddle,
  94. f"I'll post the response in about {sleep} seconds!",
  95. )
  96. )
  97. # TODO need to confirm this works without blocking in a proper task deploying system
  98. await asyncio.sleep(sleep)
  99. yield "\n\n".join(("Here's the riddle answer from before!", riddle, answer))
  100. @as_command
  101. async def selfie(req: Request, logger: Logger):
  102. try:
  103. async with req.get(
  104. "https://cdn.star.nesdis.noaa.gov/GOES16/ABI/SECTOR/ne/GEOCOLOR/latest.jpg"
  105. ) as res:
  106. res.raise_for_status()
  107. return Attachment("image", await res.read())
  108. except:
  109. logger.exception("Failed to call GOES16")
  110. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call GOES16")
  111. @as_command
  112. async def cat(req: Request, logger: Logger):
  113. """
  114. The !cat command grabs a cat from https://thiscatdoesnotexist.com/
  115. """
  116. try:
  117. async with req.get(
  118. "https://thiscatdoesnotexist.com/", headers={"User-Agent": "Rollbot"}
  119. ) as res:
  120. res.raise_for_status()
  121. return Attachment("image", await res.read())
  122. except:
  123. logger.exception("Failed to call cat generator")
  124. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call cat generator")
  125. @as_command
  126. async def horse(req: Request, logger: Logger):
  127. """
  128. The !horse command grabs a horse from https://thishorsedoesnotexist.com/
  129. """
  130. try:
  131. async with req.get(
  132. "https://thishorsedoesnotexist.com/", headers={"User-Agent": "Rollbot"}
  133. ) as res:
  134. res.raise_for_status()
  135. return Attachment("image", await res.read())
  136. except:
  137. logger.exception("Failed to call horse generator")
  138. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call horse generator")
  139. @as_command
  140. async def npc(req: Request, logger: Logger):
  141. """
  142. The !horse command grabs a person from https://thispersondoesnotexist.com/
  143. """
  144. try:
  145. async with req.get(
  146. "https://thispersondoesnotexist.com/", headers={"User-Agent": "Rollbot"}
  147. ) as res:
  148. res.raise_for_status()
  149. return Attachment("image", await res.read())
  150. except:
  151. logger.exception("Failed to call person generator")
  152. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call person generator")
  153. art_number = 0
  154. @as_command
  155. async def art(req: Request, logger: Logger):
  156. """
  157. The !art command uses the 9gans gallery at https://9gans.com/ which generates 9 images every hour.
  158. This command will cycle through those 9 images, so if you fire it 10 times in quick succession, the tenth
  159. piece of art might be the same as the first.
  160. """
  161. global art_number
  162. art_number += 1
  163. art_number %= 9
  164. try:
  165. async with req.get(
  166. f"https://storage.googleapis.com/9gans/mini/{art_number + 1}.jpg"
  167. ) as res:
  168. res.raise_for_status()
  169. return Attachment("image", await res.read())
  170. except:
  171. logger.exception("Failed to call art generator")
  172. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call art generator")
  173. @as_command
  174. async def imagine(args: Args, api_key: Config("text2img.api_key"), req: Request, logger: Logger):
  175. """
  176. The !imagine command uses the text2img API at https://deepai.org/machine-learning-model/text2img
  177. """
  178. args = args.strip()
  179. if len(args) == 0:
  180. RollbotFailure.INVALID_ARGUMENTS.raise_exc(
  181. detail="The !imagine command needs text to imagine!"
  182. )
  183. try:
  184. async with req.post(
  185. "https://api.deepai.org/api/text2img", data={"text": args}, headers={"api-key": api_key}
  186. ) as res:
  187. res.raise_for_status()
  188. print(await res.text())
  189. js = await res.json()
  190. return js.get("output_url", None)
  191. except:
  192. logger.exception("Failed to call text2img service")
  193. RollbotFailure.SERVICE_DOWN.raise_exc(detail="Failed to call text2img service")