Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d778c4afc | |||
| abbfed80ba | |||
| a212804b8d | |||
| cf610af441 | |||
| f2e412d5de | |||
| d1691f7a73 | |||
| fe3ac8ff6a | |||
| 7e15a5d4a8 | |||
| d9c2da55c1 | |||
| fdd2aed0b8 | |||
| 25bc1f21c0 | |||
| 3d5a0018de | |||
| 0d0d17e69e | |||
| 86d5f161e0 | |||
| 542ccee7af | |||
| c4e97476f3 | |||
| 6aead911da | |||
| 6ab971f16e |
@@ -1,21 +1,94 @@
|
|||||||
import requests
|
import requests
|
||||||
|
import discord
|
||||||
|
import json
|
||||||
|
import queue
|
||||||
|
from discord.ext import commands, tasks
|
||||||
from ovos_plugin_manager.phal import PHALPlugin
|
from ovos_plugin_manager.phal import PHALPlugin
|
||||||
from ovos_config.config import LocalConf
|
from ovos_config.config import LocalConf
|
||||||
|
from ovos_config.config import update_mycroft_config
|
||||||
from ovos_config.locations import get_webcache_location
|
from ovos_config.locations import get_webcache_location
|
||||||
from ovos_bus_client.util import get_mycroft_bus
|
from ovos_bus_client.util import get_mycroft_bus
|
||||||
from ovos_utils.messagebus import Message
|
from ovos_utils.messagebus import Message
|
||||||
from ovos_utils.log import LOG
|
from ovos_utils.log import LOG
|
||||||
from ovos_utils import classproperty
|
from ovos_utils import classproperty
|
||||||
from ovos_utils.process_utils import RuntimeRequirements
|
from ovos_utils.process_utils import RuntimeRequirements
|
||||||
|
from json_database import JsonConfigXDG
|
||||||
|
|
||||||
|
|
||||||
class DiscordBotPlugin(PHALPlugin):
|
class DiscordBotPlugin(PHALPlugin):
|
||||||
def __init__(self, bus=None, config=None):
|
def __init__(self, bus=None, config=None):
|
||||||
super().__init__(bus, "ovos-PHAL-plugin-discord-bot", config)
|
super().__init__(bus, "ovos-PHAL-plugin-discord-bot", config)
|
||||||
self.web_config = LocalConf(get_webcache_location())
|
#self.web_config = LocalConf(get_webcache_location())
|
||||||
|
|
||||||
|
# Initialize queue for Mycroft and user messages
|
||||||
|
self.message_queue = queue.Queue()
|
||||||
|
|
||||||
|
# Initialize Discord bot and intents
|
||||||
|
bot_intents = discord.Intents.all()
|
||||||
|
self.bot = commands.Bot(command_prefix='!', intents=bot_intents)
|
||||||
|
|
||||||
self.bus.on("mycroft.internet.connected", self.on_reset)
|
self.bus.on("mycroft.internet.connected", self.on_reset)
|
||||||
self.bus.on("recognizer_loop:utterance", self.on_utterance)
|
self.bus.on("recognizer_loop:utterance", self.on_utterance)
|
||||||
|
self.bus.on("configuration.updated", self.init_configuration)
|
||||||
|
reinstall_hint = "pip install --upgrade --no-deps --force-reinstall git+https://git.sebastianmaki.fi/sebastian/ovos-PHAL-plugin-discord-bot.git"
|
||||||
|
LOG.info(f"Reinstall hint: {reinstall_hint}")
|
||||||
|
|
||||||
|
# Helper function to get Discord user by ID
|
||||||
|
async def get_discord_user_by_id(user_id) -> discord.User:
|
||||||
|
return await self.bot.fetch_user(user_id)
|
||||||
|
|
||||||
|
# Discord event: bot is ready
|
||||||
|
@self.bot.event
|
||||||
|
async def on_ready():
|
||||||
|
myLoop.start()
|
||||||
|
LOG.info(f"{self.bot.user} has connected to Discord!")
|
||||||
|
|
||||||
|
admin = await get_discord_user_by_id(self.config.get("admin_id"))
|
||||||
|
if admin:
|
||||||
|
LOG.info(f"Admin is {admin.name}")
|
||||||
|
await admin.send("I'm now online")
|
||||||
|
|
||||||
|
# Discord event: Process incoming messages
|
||||||
|
@self.bot.event
|
||||||
|
async def on_message(message):
|
||||||
|
if message.author == self.bot.user:
|
||||||
|
return
|
||||||
|
|
||||||
|
await self.bot.process_commands(message)
|
||||||
|
admin = await get_discord_user_by_id(self.config.get("admin_id"))
|
||||||
|
|
||||||
|
if message.author == admin:
|
||||||
|
if message.content.lower().startswith("tell mycroft"):
|
||||||
|
# The message starts with "tell mycroft"
|
||||||
|
# Implement the action you want to take in response to this here.
|
||||||
|
# For example, you can extract the command from the message and respond accordingly.
|
||||||
|
command = message.content[len("tell mycroft"):].strip() # Remove "tell mycroft" and strip any leading/trailing spaces.
|
||||||
|
# Now, you can execute the command or respond accordingly based on the extracted command.
|
||||||
|
self.bus.emit(
|
||||||
|
Message(
|
||||||
|
"recognizer_loop:utterance",
|
||||||
|
{
|
||||||
|
'utterances': [command],
|
||||||
|
'lang': 'en-us'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
await message.channel.send(f"Telling mycroft {command}")
|
||||||
|
|
||||||
|
QUEUE_POLL_INTERVAL = 0.2
|
||||||
|
@tasks.loop(seconds=QUEUE_POLL_INTERVAL)
|
||||||
|
async def myLoop():
|
||||||
|
admin = await get_discord_user_by_id(self.config.get("admin_id"))
|
||||||
|
while not self.message_queue.empty():
|
||||||
|
entity, message_content = self.message_queue.get()
|
||||||
|
print(f"{entity} said: {message_content}")
|
||||||
|
if entity == "user":
|
||||||
|
await admin.send(f"User said: {message_content}")
|
||||||
|
elif entity == "mycroft":
|
||||||
|
await admin.send(f"Mycroft said: {message_content}")
|
||||||
|
|
||||||
|
|
||||||
|
self.setup_configuration()
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
def runtime_requirements(self):
|
def runtime_requirements(self):
|
||||||
@@ -31,9 +104,60 @@ class DiscordBotPlugin(PHALPlugin):
|
|||||||
|
|
||||||
def on_utterance(self, message=None):
|
def on_utterance(self, message=None):
|
||||||
LOG.info(f"On utterance triggered: %s", message.serialize())
|
LOG.info(f"On utterance triggered: %s", message.serialize())
|
||||||
|
for utterance in message.data['utterances']:
|
||||||
|
self.message_queue.put(("user", utterance))
|
||||||
|
|
||||||
def on_speak(self, message=None):
|
def on_speak(self, message=None):
|
||||||
LOG.info(f"On speak triggered: %s", message.serialize())
|
LOG.info(f"On speak triggered: %s", message.serialize())
|
||||||
|
self.message_queue.put(("mycroft", message.data['utterance']))
|
||||||
|
|
||||||
|
|
||||||
|
def setup_configuration(self):
|
||||||
|
first_start = self.config.get("first_start", True)
|
||||||
|
if first_start:
|
||||||
|
self.config["first_start"] = False
|
||||||
|
config_patch = {
|
||||||
|
"PHAL": {
|
||||||
|
"ovos-PHAL-plugin-discord-bot": {
|
||||||
|
"first_start": False,
|
||||||
|
"api_token": "",
|
||||||
|
"admin_id": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_mycroft_config(config=config_patch, bus=self.bus)
|
||||||
|
self.init_configuration()
|
||||||
|
|
||||||
|
def init_configuration(self, message=None):
|
||||||
|
""" Initialize instance configuration """
|
||||||
|
configuration_first_start = self.config.get("first_start", True)
|
||||||
|
configuration_api_token = self.config.get("api_token", "")
|
||||||
|
configuration_admin_id = self.config.get("admin_id", "")
|
||||||
|
config = {"api_token": configuration_api_token, "admin_id": configuration_admin_id }
|
||||||
|
config_json = json.dumps(config)
|
||||||
|
LOG.info(f"Configuration updated: %s", config_json)
|
||||||
|
|
||||||
|
uninitialized_settings = []
|
||||||
|
if not configuration_api_token:
|
||||||
|
uninitialized_settings.append("api_token")
|
||||||
|
|
||||||
|
if not configuration_admin_id:
|
||||||
|
uninitialized_settings.append("admin_id")
|
||||||
|
|
||||||
|
if uninitialized_settings:
|
||||||
|
self.bus.emit(Message("ovos.phal.plugin.discord_bot.requires.configuration"))
|
||||||
|
config_issue = "The following configuration settings are uninitialized: " + ", ".join(uninitialized_settings)
|
||||||
|
LOG.info(config_issue)
|
||||||
|
else:
|
||||||
|
self.api_token = configuration_api_token
|
||||||
|
self.admin_id = configuration_admin_id
|
||||||
|
LOG.info("All configuration settings are initialized.")
|
||||||
|
self.init_bot()
|
||||||
|
|
||||||
|
def init_bot(self):
|
||||||
|
# Start the Discord bot
|
||||||
|
LOG.info("Starting the bot")
|
||||||
|
self.bot.run(self.api_token)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user