forked from gooberinc/goober
added sync hub
This commit is contained in:
parent
991264620a
commit
a20e9eb9f0
8 changed files with 173 additions and 19 deletions
|
@ -10,6 +10,7 @@ import logging
|
||||||
from modules.settings import instance as settings_manager
|
from modules.settings import instance as settings_manager
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
from modules.sync_conenctor import instance as sync_hub
|
||||||
|
|
||||||
logger = logging.getLogger("goober")
|
logger = logging.getLogger("goober")
|
||||||
|
|
||||||
|
@ -54,6 +55,11 @@ class BreakingNews(commands.Cog):
|
||||||
if not message.content.lower().startswith("breaking news:"):
|
if not message.content.lower().startswith("breaking news:"):
|
||||||
logger.debug("Ignoring message - doesnt start with breaking news:")
|
logger.debug("Ignoring message - doesnt start with breaking news:")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not sync_hub.can_breaking_news(message.id):
|
||||||
|
logger.debug("Sync hub denied breaking news request")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
texts = re.split("breaking news:", message.content, flags=re.IGNORECASE)
|
texts = re.split("breaking news:", message.content, flags=re.IGNORECASE)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import cpuinfo
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import updater
|
import updater
|
||||||
|
from modules.sync_conenctor import instance as sync_connector
|
||||||
|
|
||||||
settings = settings_manager.settings
|
settings = settings_manager.settings
|
||||||
|
|
||||||
|
@ -204,6 +205,25 @@ class BaseCommands(commands.Cog):
|
||||||
|
|
||||||
await send_message(ctx, response.text)
|
await send_message(ctx, response.text)
|
||||||
|
|
||||||
|
@requires_admin()
|
||||||
|
@commands.command()
|
||||||
|
async def test_synchub(self, ctx: commands.Context, message_id: str | None) -> None:
|
||||||
|
message_id = message_id or "0"
|
||||||
|
status = sync_connector.can_react(int(message_id))
|
||||||
|
|
||||||
|
await send_message(ctx, f"Is allowed to react to message id {message_id}? {status} (connection active? {sync_connector.connected})")
|
||||||
|
|
||||||
|
|
||||||
|
@requires_admin()
|
||||||
|
@commands.command()
|
||||||
|
async def connect_synchub(self, ctx: commands.Context) -> None:
|
||||||
|
await send_message(ctx, "Trying to connect...")
|
||||||
|
|
||||||
|
connected = sync_connector.try_to_connect()
|
||||||
|
if connected:
|
||||||
|
await send_message(ctx, "Succesfully connected to sync hub!")
|
||||||
|
else:
|
||||||
|
await send_message(ctx, "Failed to connect to sync hub")
|
||||||
|
|
||||||
async def setup(bot: discord.ext.commands.Bot):
|
async def setup(bot: discord.ext.commands.Bot):
|
||||||
print("Setting up base_commands")
|
print("Setting up base_commands")
|
||||||
|
|
41
bot.py
41
bot.py
|
@ -1,3 +1,20 @@
|
||||||
|
import logging
|
||||||
|
from modules.logger import GooberFormatter
|
||||||
|
|
||||||
|
logger = logging.getLogger("goober")
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
console_handler = logging.StreamHandler()
|
||||||
|
console_handler.setLevel(logging.DEBUG)
|
||||||
|
console_handler.setFormatter(GooberFormatter())
|
||||||
|
|
||||||
|
file_handler = logging.FileHandler("log.txt", mode="w+", encoding="UTF-8")
|
||||||
|
file_handler.setLevel(logging.DEBUG)
|
||||||
|
file_handler.setFormatter(GooberFormatter(colors=False))
|
||||||
|
|
||||||
|
logger.addHandler(console_handler)
|
||||||
|
logger.addHandler(file_handler)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
@ -25,7 +42,6 @@ from typing import (
|
||||||
)
|
)
|
||||||
import logging
|
import logging
|
||||||
from modules.prestartchecks import start_checks
|
from modules.prestartchecks import start_checks
|
||||||
from modules.logger import GooberFormatter
|
|
||||||
import modules.keys as k
|
import modules.keys as k
|
||||||
from modules import key_compiler
|
from modules import key_compiler
|
||||||
import logging
|
import logging
|
||||||
|
@ -33,6 +49,8 @@ from watchdog.observers import Observer
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
from modules.settings import instance as settings_manager, ActivityType
|
from modules.settings import instance as settings_manager, ActivityType
|
||||||
from modules.permission import requires_admin
|
from modules.permission import requires_admin
|
||||||
|
from modules.sync_conenctor import instance as sync_connector
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,20 +67,6 @@ def build_keys():
|
||||||
build_keys()
|
build_keys()
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("goober")
|
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
console_handler = logging.StreamHandler()
|
|
||||||
console_handler.setLevel(logging.DEBUG)
|
|
||||||
console_handler.setFormatter(GooberFormatter())
|
|
||||||
|
|
||||||
file_handler = logging.FileHandler("log.txt", mode="w+", encoding="UTF-8")
|
|
||||||
file_handler.setLevel(logging.DEBUG)
|
|
||||||
file_handler.setFormatter(GooberFormatter(colors=False))
|
|
||||||
|
|
||||||
logger.addHandler(console_handler)
|
|
||||||
logger.addHandler(file_handler)
|
|
||||||
|
|
||||||
settings = settings_manager.settings
|
settings = settings_manager.settings
|
||||||
|
|
||||||
splash_text: str = ""
|
splash_text: str = ""
|
||||||
|
@ -272,7 +276,7 @@ async def demotivator(ctx: commands.Context) -> None:
|
||||||
shutil.copy(fallback_image, temp_input)
|
shutil.copy(fallback_image, temp_input)
|
||||||
input_path = temp_input
|
input_path = temp_input
|
||||||
|
|
||||||
output_path: Optional[str] = await gen_demotivator(input_path)
|
output_path: Optional[str] = await gen_demotivator(input_path) # type: ignore
|
||||||
|
|
||||||
if output_path is None or not os.path.isfile(output_path):
|
if output_path is None or not os.path.isfile(output_path):
|
||||||
if temp_input and os.path.exists(temp_input):
|
if temp_input and os.path.exists(temp_input):
|
||||||
|
@ -354,6 +358,11 @@ async def on_message(message: discord.Message) -> None:
|
||||||
if sentiment_score > 0.8:
|
if sentiment_score > 0.8:
|
||||||
if not settings["bot"]["react_to_messages"]:
|
if not settings["bot"]["react_to_messages"]:
|
||||||
return
|
return
|
||||||
|
if not sync_connector.can_react(message.id):
|
||||||
|
logger.info("Sync hub determined that this instance cannot react")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
emoji = random.choice(EMOJIS)
|
emoji = random.choice(EMOJIS)
|
||||||
try:
|
try:
|
||||||
await message.add_reaction(emoji)
|
await message.add_reaction(emoji)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import importlib.metadata
|
||||||
import logging
|
import logging
|
||||||
import modules.keys as k
|
import modules.keys as k
|
||||||
from modules.settings import instance as settings_manager
|
from modules.settings import instance as settings_manager
|
||||||
|
from modules.sync_conenctor import instance as sync_hub
|
||||||
|
|
||||||
settings = settings_manager.settings
|
settings = settings_manager.settings
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ def check_requirements():
|
||||||
"better_profanity": "better-profanity",
|
"better_profanity": "better-profanity",
|
||||||
"dotenv": "python-dotenv",
|
"dotenv": "python-dotenv",
|
||||||
"pil": "pillow",
|
"pil": "pillow",
|
||||||
|
"websocket": "websocket-client"
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_dir = os.path.dirname(os.path.abspath(__file__))
|
parent_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
@ -260,6 +262,11 @@ def presskey2skip(timeout):
|
||||||
finally:
|
finally:
|
||||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||||
|
|
||||||
|
def check_synchub():
|
||||||
|
if not sync_hub.connected:
|
||||||
|
logger.warning("Sync hub not connected properly! The bot will not be able to react to messages, or create breaking news unless you disable synchub in settings")
|
||||||
|
else:
|
||||||
|
logger.info("Sync hub is conencted")
|
||||||
|
|
||||||
beta = beta
|
beta = beta
|
||||||
|
|
||||||
|
@ -277,6 +284,7 @@ def start_checks():
|
||||||
check_memory()
|
check_memory()
|
||||||
check_memoryjson()
|
check_memoryjson()
|
||||||
check_cpu()
|
check_cpu()
|
||||||
|
check_synchub()
|
||||||
if os.path.exists(".env"):
|
if os.path.exists(".env"):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -9,6 +9,9 @@ logger = logging.getLogger("goober")
|
||||||
|
|
||||||
ActivityType = Literal["listening", "playing", "streaming", "competing", "watching"]
|
ActivityType = Literal["listening", "playing", "streaming", "competing", "watching"]
|
||||||
|
|
||||||
|
class SyncHub(TypedDict):
|
||||||
|
url: str
|
||||||
|
enabled: bool
|
||||||
|
|
||||||
class Activity(TypedDict):
|
class Activity(TypedDict):
|
||||||
content: str
|
content: str
|
||||||
|
@ -32,6 +35,7 @@ class BotSettings(TypedDict):
|
||||||
misc: MiscBotOptions
|
misc: MiscBotOptions
|
||||||
enabled_cogs: List[str]
|
enabled_cogs: List[str]
|
||||||
active_memory: str
|
active_memory: str
|
||||||
|
sync_hub: SyncHub
|
||||||
|
|
||||||
|
|
||||||
class SettingsType(TypedDict):
|
class SettingsType(TypedDict):
|
||||||
|
@ -93,6 +97,15 @@ class Settings:
|
||||||
|
|
||||||
del self.settings["bot"]["misc"]["active_song"] # type: ignore
|
del self.settings["bot"]["misc"]["active_song"] # type: ignore
|
||||||
|
|
||||||
|
sync_hub: SyncHub | None = self.settings.get("bot", {}).get("sync_hub")
|
||||||
|
|
||||||
|
if not sync_hub:
|
||||||
|
logger.warning("Adding sync hub settings")
|
||||||
|
self.settings["bot"]["sync_hub"] = {
|
||||||
|
"enabled": True,
|
||||||
|
"url": "ws://goober.frii.site"
|
||||||
|
}
|
||||||
|
|
||||||
self.commit()
|
self.commit()
|
||||||
|
|
||||||
def reload_settings(self) -> None:
|
def reload_settings(self) -> None:
|
||||||
|
|
93
modules/sync_conenctor.py
Normal file
93
modules/sync_conenctor.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import websocket
|
||||||
|
from modules.settings import instance as settings_manager
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger("goober")
|
||||||
|
settings = settings_manager.settings
|
||||||
|
|
||||||
|
class SyncConnector:
|
||||||
|
def __init__(self, url: str):
|
||||||
|
self.connected: bool = True
|
||||||
|
self.url = url
|
||||||
|
self.client: websocket.WebSocket | None = None
|
||||||
|
|
||||||
|
self.try_to_connect()
|
||||||
|
|
||||||
|
def __connect(self) -> bool:
|
||||||
|
try:
|
||||||
|
self.client = websocket.create_connection(self.url)
|
||||||
|
except OSError as e:
|
||||||
|
logger.debug(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def try_to_connect(self) -> bool:
|
||||||
|
if self.__connect():
|
||||||
|
logger.info("Connected to sync hub!")
|
||||||
|
self.connected = True
|
||||||
|
else:
|
||||||
|
logger.error("Failed to connect to sync hub.. Disabling for the time being")
|
||||||
|
self.connected = False
|
||||||
|
|
||||||
|
return self.connected
|
||||||
|
|
||||||
|
|
||||||
|
def can_react(self, message_id: int) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if goober can react to a messsage
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.can_event(message_id, "react")
|
||||||
|
|
||||||
|
|
||||||
|
def can_breaking_news(self, message_id: int) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if goober can send a breaking news alert
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.can_event(message_id, "breaking_news")
|
||||||
|
|
||||||
|
|
||||||
|
def can_event(self, message_id: int, event: str, retry_depth: int = 0) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if goober can send a breaking news alert
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger.debug(f"Checking {event} for message {message_id}")
|
||||||
|
|
||||||
|
if not settings["bot"]["sync_hub"]["enabled"]:
|
||||||
|
logger.info("Skipping sync hub check")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if retry_depth > 2:
|
||||||
|
logger.error("Too many retries. Returning false")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.client:
|
||||||
|
logger.error("Client no connected")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.connected:
|
||||||
|
logger.warning("Not connected to sync hub.. Returning False to avoid conflicts")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.client.send(f"event={event};ref={message_id}")
|
||||||
|
return self.client.recv() == "unhandled"
|
||||||
|
except ConnectionResetError:
|
||||||
|
logger.error("Connection to sync hub reset! Retrying...")
|
||||||
|
|
||||||
|
if not self.__connect():
|
||||||
|
logger.error("Failed to reconnect to sync hub... Disabling")
|
||||||
|
self.connected = False
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info("Managed to reconnect to sync hub! Retrying requests")
|
||||||
|
self.connected = True
|
||||||
|
return self.can_event(message_id, event, retry_depth+1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
instance = SyncConnector("ws://localhost:80")
|
|
@ -9,4 +9,5 @@ python-dotenv
|
||||||
dotenv
|
dotenv
|
||||||
pillow
|
pillow
|
||||||
watchdog
|
watchdog
|
||||||
py-cpuinfo
|
py-cpuinfo
|
||||||
|
websocket-client
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"bot": {
|
"bot": {
|
||||||
"prefix": "p.",
|
"prefix": "o.",
|
||||||
"owner_ids": [
|
"owner_ids": [
|
||||||
642441889181728810
|
642441889181728810
|
||||||
],
|
],
|
||||||
|
@ -25,7 +25,11 @@
|
||||||
"enabled_cogs": [
|
"enabled_cogs": [
|
||||||
"pulse",
|
"pulse",
|
||||||
"breaking_news"
|
"breaking_news"
|
||||||
]
|
],
|
||||||
|
"sync_hub": {
|
||||||
|
"url": "ws://goober.frii.site",
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"locale": "en",
|
"locale": "en",
|
||||||
"name": "gubert",
|
"name": "gubert",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue