app.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import logging
  2. import os
  3. import discord
  4. import dotenv
  5. import requests
  6. dotenv.load_dotenv(".env")
  7. intents = discord.Intents.default()
  8. intents.message_content = True
  9. client = discord.Client(intents=intents)
  10. discord_bot_name = os.environ["DISCORD_BOT_NAME"]
  11. logger = logging.getLogger(__name__)
  12. class NextJSBot:
  13. def __init__(self) -> None:
  14. logger.info("NextJS Bot powered with embedchain.")
  15. def add(self, _):
  16. raise ValueError("Add is not implemented yet")
  17. def query(self, message, citations: bool = False):
  18. url = os.environ["EC_APP_URL"] + "/query"
  19. payload = {
  20. "question": message,
  21. "citations": citations,
  22. }
  23. try:
  24. response = requests.request("POST", url, json=payload)
  25. try:
  26. response = response.json()
  27. except Exception:
  28. logger.error(f"Failed to parse response: {response}")
  29. response = {}
  30. return response
  31. except Exception:
  32. logger.exception(f"Failed to query {message}.")
  33. response = "An error occurred. Please try again!"
  34. return response
  35. def start(self):
  36. discord_token = os.environ["DISCORD_BOT_TOKEN"]
  37. client.run(discord_token)
  38. NEXTJS_BOT = NextJSBot()
  39. @client.event
  40. async def on_ready():
  41. logger.info(f"User {client.user.name} logged in with id: {client.user.id}!")
  42. def _get_question(message):
  43. user_ids = message.raw_mentions
  44. if len(user_ids) > 0:
  45. for user_id in user_ids:
  46. # remove mentions from message
  47. question = message.content.replace(f"<@{user_id}>", "").strip()
  48. return question
  49. async def answer_query(message):
  50. if (
  51. message.channel.type == discord.ChannelType.public_thread
  52. or message.channel.type == discord.ChannelType.private_thread
  53. ):
  54. await message.channel.send(
  55. "🧵 Currently, we don't support answering questions in threads. Could you please send your message in the channel for a swift response? Appreciate your understanding! 🚀" # noqa: E501
  56. )
  57. return
  58. question = _get_question(message)
  59. print("Answering question: ", question)
  60. thread = await message.create_thread(name=question)
  61. await thread.send("🎭 Putting on my thinking cap, brb with an epic response!")
  62. response = NEXTJS_BOT.query(question, citations=True)
  63. default_answer = "Sorry, I don't know the answer to that question. Please refer to the documentation.\nhttps://nextjs.org/docs" # noqa: E501
  64. answer = response.get("answer", default_answer)
  65. contexts = response.get("contexts", [])
  66. if contexts:
  67. sources = list(set(map(lambda x: x[1]["url"], contexts)))
  68. answer += "\n\n**Sources**:\n"
  69. for i, source in enumerate(sources):
  70. answer += f"- {source}\n"
  71. sent_message = await thread.send(answer)
  72. await sent_message.add_reaction("😮")
  73. await sent_message.add_reaction("👍")
  74. await sent_message.add_reaction("❤️")
  75. await sent_message.add_reaction("👎")
  76. @client.event
  77. async def on_message(message):
  78. mentions = message.mentions
  79. if len(mentions) > 0 and any([user.bot and user.name == discord_bot_name for user in mentions]):
  80. await answer_query(message)
  81. def start_bot():
  82. NEXTJS_BOT.start()
  83. if __name__ == "__main__":
  84. start_bot()