discord_bot.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import asyncio
  2. import aiohttp
  3. import os
  4. import threading
  5. from configparser import ConfigParser
  6. import discord
  7. import zwift_offline
  8. class DiscordBot(discord.Client):
  9. def __init__(self, intents, channel, welcome_msg, help_msg):
  10. discord.Client.__init__(self, intents=intents)
  11. self.channel_id = channel
  12. self.welcome_msg = welcome_msg
  13. self.help_msg = help_msg
  14. async def on_ready(self):
  15. self.channel = self.get_channel(self.channel_id)
  16. async def on_member_join(self, member):
  17. if self.welcome_msg:
  18. await self.channel.send('%s\n%s' % (member.mention, self.welcome_msg))
  19. async def on_message(self, message):
  20. if message.author.id == self.user.id:
  21. return
  22. if message.content == '!online':
  23. await message.channel.send('%s riders online' % len(zwift_offline.online))
  24. elif message.content == '!help' and self.help_msg:
  25. await message.channel.send(self.help_msg)
  26. elif message.content == '!ping':
  27. await message.channel.send('pong')
  28. elif message.channel == self.channel and not message.author.bot and not message.content.startswith('!'):
  29. zwift_offline.send_message(message.content, message.author.name)
  30. class DiscordThread(threading.Thread):
  31. def __init__(self, config_file):
  32. threading.Thread.__init__(self)
  33. if not os.path.isfile(config_file):
  34. raise Exception("DiscordThread invoked without a configuration file")
  35. self.CONFIG = ConfigParser()
  36. SECTION = 'discord'
  37. self.CONFIG.read(config_file)
  38. self.token = self.CONFIG.get(SECTION, 'token')
  39. self.webhook = self.CONFIG.get(SECTION, 'webhook')
  40. self.channel = self.CONFIG.getint(SECTION, 'channel')
  41. self.welcome_msg = self.CONFIG.get(SECTION, 'welcome_message')
  42. self.help_msg = self.CONFIG.get(SECTION, 'help_message')
  43. self.intents = discord.Intents.default()
  44. self.intents.members = True
  45. self.intents.message_content = True
  46. self.loop = asyncio.get_event_loop()
  47. self.start()
  48. async def starter(self):
  49. self.discord_bot = DiscordBot(self.intents, self.channel, self.welcome_msg, self.help_msg)
  50. await self.discord_bot.start(self.token)
  51. def run(self):
  52. try:
  53. self.loop.run_until_complete(self.starter())
  54. except Exception as exc:
  55. print('DiscordThread exception: %s' % repr(exc))
  56. async def webhook_send(self, message, sender):
  57. async with aiohttp.ClientSession() as session:
  58. await discord.Webhook.from_url(self.webhook, session=session).send(message, username=sender)
  59. def send_message(self, message, sender_id=None):
  60. if sender_id is not None:
  61. profile = zwift_offline.get_partial_profile(sender_id)
  62. sender = profile.first_name + ' ' + profile.last_name
  63. else:
  64. sender = 'Server'
  65. asyncio.run_coroutine_threadsafe(self.webhook_send(message, sender), self.loop)
  66. def change_presence(self, n):
  67. if n > 0:
  68. activity = discord.Game(name=f"{n} rider{'s'[:n>1]} online")
  69. else:
  70. activity = None
  71. asyncio.run_coroutine_threadsafe(self.discord_bot.change_presence(activity=activity), self.loop)