[feat] Heavy push to Docker
This commit is contained in:
parent
bfd5087aa9
commit
5d164ede9b
14 changed files with 1319 additions and 1646 deletions
|
@ -7,7 +7,8 @@
|
|||
!/jarvis.png
|
||||
!/jarvis_small.png
|
||||
!/run.py
|
||||
!/config.yaml
|
||||
!/README.md
|
||||
!/poetry.lock
|
||||
# Needed for jarvis-compose
|
||||
!/.git
|
||||
|
||||
|
|
8
.gitlab-ci.yml
Normal file
8
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
build dev:
|
||||
stage: build
|
||||
image: docker
|
||||
before_script:
|
||||
- echo "$ZEVARYX_REGISTRY_PASSWORD" | docker login -u "$ZEVARYX_REGISTRY_USERNAME" --password-stdin "$ZEVARYX_REGISTRY_URL"
|
||||
script:
|
||||
- docker build -t $ZEVARYX_REGISTRY_URL/jarvis-bot:$CI_COMMIT_BRANCH .
|
||||
- docker push $ZEVARYX_REGISTRY_URL/jarvis-bot:$CI_COMMIT_BRANCH
|
33
Dockerfile
33
Dockerfile
|
@ -1,11 +1,34 @@
|
|||
FROM python:3.10
|
||||
FROM python:3.12-bookworm as builder
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install ffmpeg libsm6 libxext6 -y
|
||||
RUN pip install poetry==1.7.1
|
||||
|
||||
ENV POETRY_NO_INTERACTION=1 \
|
||||
POETRY_VIRTUALENVS_IN_PROJECT=1 \
|
||||
POETRY_VIRTUALENVS_CREATE=1 \
|
||||
POETRY_CACHE_DIR=/tmp/poetry_cache
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . /app
|
||||
RUN pip install --no-cache-dir .
|
||||
COPY pyproject.toml poetry.lock README.md ./
|
||||
|
||||
RUN poetry install --without dev --no-root && rm -rf $POETRY_CACHE_DIR
|
||||
|
||||
FROM python:3.12-slim-bookworm as runtime
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
libjpeg-dev \
|
||||
libopenjp2-7-dev \
|
||||
libgl-dev \
|
||||
libglib2.0-dev
|
||||
|
||||
ENV VIRTUAL_ENV=/app/.venv \
|
||||
PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
|
||||
|
||||
COPY . /app/
|
||||
|
||||
CMD [ "python", "run.py" ]
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
token: bot token
|
||||
twitter:
|
||||
consumer_key: key
|
||||
consumer_secret: secret
|
||||
access_token: access token
|
||||
access_secret: access secret
|
||||
mongo:
|
||||
connect:
|
||||
username: username
|
||||
password: password
|
||||
host: hostname
|
||||
port: 27017
|
||||
database: database
|
||||
urls:
|
||||
extra: urls
|
||||
max_messages: 10000
|
||||
gitlab_token: token
|
||||
cogs:
|
||||
- admin
|
||||
- autoreact
|
||||
- dev
|
||||
- image
|
||||
- gl
|
||||
- remindme
|
||||
- rolegiver
|
||||
# - settings
|
||||
- starboard
|
||||
- twitter
|
||||
- util
|
||||
- verify
|
||||
log_level: INFO
|
||||
sync: false
|
||||
#sync_commands: True
|
|
@ -1,4 +1,5 @@
|
|||
"""JARVIS bot utility commands."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import platform
|
||||
|
@ -13,10 +14,8 @@ from interactions.models.discord.components import Button
|
|||
from interactions.models.discord.embed import EmbedField
|
||||
from interactions.models.discord.enums import ButtonStyle
|
||||
from interactions.models.discord.file import File
|
||||
from rich.console import Console
|
||||
|
||||
from jarvis.utils import build_embed
|
||||
from jarvis.utils.updates import update
|
||||
|
||||
|
||||
class BotutilCog(Extension):
|
||||
|
@ -36,12 +35,6 @@ class BotutilCog(Extension):
|
|||
await ctx.send(content)
|
||||
await ctx.message.delete()
|
||||
|
||||
@prefixed_command(name="stop")
|
||||
async def _stop(self, ctx: PrefixedContext) -> None:
|
||||
await ctx.send("Shutting down now")
|
||||
loop = asyncio.get_running_loop()
|
||||
loop.stop()
|
||||
|
||||
@prefixed_command(name="tail")
|
||||
async def _tail(self, ctx: PrefixedContext, count: int = 10) -> None:
|
||||
lines = []
|
||||
|
@ -56,7 +49,9 @@ class BotutilCog(Extension):
|
|||
file_bytes.write(log.encode("UTF8"))
|
||||
file_bytes.seek(0)
|
||||
log = File(file_bytes, file_name=f"tail_{count}.log")
|
||||
await ctx.reply(content=f"Here's the last {count} lines of the log", file=log)
|
||||
await ctx.reply(
|
||||
content=f"Here's the last {count} lines of the log", file=log
|
||||
)
|
||||
else:
|
||||
await ctx.reply(content=f"```\n{log}\n```")
|
||||
|
||||
|
@ -79,62 +74,25 @@ class BotutilCog(Extension):
|
|||
st_ts = int(self.bot.start_time.timestamp())
|
||||
ut_ts = int(psutil.boot_time())
|
||||
fields = (
|
||||
EmbedField(name="Operation System", value=platform.system() or "Unknown", inline=False),
|
||||
EmbedField(
|
||||
name="Operation System",
|
||||
value=platform.system() or "Unknown",
|
||||
inline=False,
|
||||
),
|
||||
EmbedField(name="Version", value=platform.release() or "N/A", inline=False),
|
||||
EmbedField(name="System Start Time", value=f"<t:{ut_ts}:F> (<t:{ut_ts}:R>)"),
|
||||
EmbedField(
|
||||
name="System Start Time", value=f"<t:{ut_ts}:F> (<t:{ut_ts}:R>)"
|
||||
),
|
||||
EmbedField(name="Python Version", value=platform.python_version()),
|
||||
EmbedField(name="Bot Start Time", value=f"<t:{st_ts}:F> (<t:{st_ts}:R>)"),
|
||||
)
|
||||
embed = build_embed(title="System Info", description="", fields=fields)
|
||||
embed.set_image(url=self.bot.user.avatar.url)
|
||||
components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
components = Button(
|
||||
style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@prefixed_command(name="update")
|
||||
async def _update(self, ctx: PrefixedContext) -> None:
|
||||
status = await update(self.bot)
|
||||
if status:
|
||||
console = Console()
|
||||
with console.capture() as capture:
|
||||
console.print(status.table)
|
||||
self.logger.debug(capture.get())
|
||||
self.logger.debug(len(capture.get()))
|
||||
added = "\n".join(status.added)
|
||||
removed = "\n".join(status.removed)
|
||||
changed = "\n".join(status.changed)
|
||||
|
||||
fields = [
|
||||
EmbedField(name="Old Commit", value=status.old_hash),
|
||||
EmbedField(name="New Commit", value=status.new_hash),
|
||||
]
|
||||
if added:
|
||||
fields.append(EmbedField(name="New Modules", value=f"```\n{added}\n```"))
|
||||
if removed:
|
||||
fields.append(EmbedField(name="Removed Modules", value=f"```\n{removed}\n```"))
|
||||
if changed:
|
||||
fields.append(EmbedField(name="Changed Modules", value=f"```\n{changed}\n```"))
|
||||
|
||||
embed = build_embed("Update Status", description="Updates have been applied", fields=fields)
|
||||
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
||||
|
||||
self.logger.info("Updates applied")
|
||||
content = f"```ansi\n{capture.get()}\n```"
|
||||
components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
if len(content) < 3000:
|
||||
await ctx.reply(content, embeds=embed, components=components)
|
||||
else:
|
||||
await ctx.reply(
|
||||
f"Total Changes: {status.lines['total_lines']}",
|
||||
embeds=embed,
|
||||
components=components,
|
||||
)
|
||||
|
||||
else:
|
||||
embed = build_embed(title="Update Status", description="No changes applied", fields=[])
|
||||
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
||||
components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.reply(embeds=embed, components=components)
|
||||
|
||||
|
||||
def setup(bot: Client) -> None:
|
||||
"""Add BotutilCog to JARVIS"""
|
||||
|
|
|
@ -36,7 +36,7 @@ from tzlocal import get_localzone
|
|||
from jarvis import const as jconst
|
||||
from jarvis.data import pigpen
|
||||
from jarvis.data.robotcamo import emotes, hk, names
|
||||
from jarvis.utils import build_embed, get_repo_hash
|
||||
from jarvis.utils import build_embed
|
||||
|
||||
JARVIS_LOGO = Image.open("jarvis_small.png").convert("RGBA")
|
||||
|
||||
|
@ -148,14 +148,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh
|
|||
)
|
||||
)
|
||||
self.bot.logger.debug("Getting repo information")
|
||||
repo_url = f"https://git.zevaryx.com/stark-industries/jarvis/jarvis-bot/-/tree/{get_repo_hash()}"
|
||||
fields.append(
|
||||
EmbedField(
|
||||
name="Git Hash",
|
||||
value=f"[{get_repo_hash()[:7]}]({repo_url})",
|
||||
inline=True,
|
||||
)
|
||||
)
|
||||
repo_url = "https://git.zevaryx.com/stark-industries/jarvis/jarvis-bot/"
|
||||
fields.append(
|
||||
EmbedField(name="Online Since", value=f"<t:{uptime}:F>", inline=False)
|
||||
)
|
||||
|
|
|
@ -11,6 +11,7 @@ No longer being a part of the community and hearing about *certain users* talkin
|
|||
that request said features, means that I am no longer putting any energy into this. If you want to keep
|
||||
it running, make a PR to fix things.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
@ -97,7 +98,7 @@ class DbrandCog(Extension):
|
|||
self.base_url = "https://dbrand.com/"
|
||||
self._session = aiohttp.ClientSession()
|
||||
self._session.headers.update({"Content-Type": "application/json"})
|
||||
self.api_url = load_config().urls["dbrand_shipping"]
|
||||
# self.api_url = load_config().urls["dbrand_shipping"]
|
||||
self.cache = {}
|
||||
|
||||
def __del__(self):
|
||||
|
@ -401,7 +402,4 @@ class DbrandCog(Extension):
|
|||
|
||||
def setup(bot: Client) -> None:
|
||||
"""Add dbrandcog to JARVIS"""
|
||||
if load_config().urls.get("dbrand_shipping"):
|
||||
DbrandCog(bot)
|
||||
else:
|
||||
bot.logger.info("Missing dbrand shipping URL, not loading dbrand cog")
|
||||
DbrandCog(bot)
|
||||
|
|
124
jarvis/config.py
124
jarvis/config.py
|
@ -1,22 +1,12 @@
|
|||
"""Load the config for JARVIS"""
|
||||
|
||||
from enum import Enum
|
||||
from os import environ
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import orjson as json
|
||||
import yaml
|
||||
from dotenv import load_dotenv
|
||||
from jarvis_core.util import find_all
|
||||
from pydantic import BaseModel
|
||||
|
||||
try:
|
||||
from yaml import CLoader as Loader
|
||||
except ImportError:
|
||||
from yaml import Loader
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Mongo(BaseModel):
|
||||
class Mongo(BaseSettings):
|
||||
"""MongoDB config."""
|
||||
|
||||
host: list[str] | str = "localhost"
|
||||
|
@ -25,7 +15,7 @@ class Mongo(BaseModel):
|
|||
port: int = 27017
|
||||
|
||||
|
||||
class Redis(BaseModel):
|
||||
class Redis(BaseSettings):
|
||||
"""Redis config."""
|
||||
|
||||
host: str = "localhost"
|
||||
|
@ -33,7 +23,7 @@ class Redis(BaseModel):
|
|||
password: Optional[str] = None
|
||||
|
||||
|
||||
class Mastodon(BaseModel):
|
||||
class Mastodon(BaseSettings):
|
||||
"""Mastodon config."""
|
||||
|
||||
token: str
|
||||
|
@ -47,7 +37,7 @@ class Environment(Enum):
|
|||
develop = "develop"
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
class Config(BaseSettings, case_sensitive=False):
|
||||
"""JARVIS config model."""
|
||||
|
||||
token: str
|
||||
|
@ -55,109 +45,19 @@ class Config(BaseModel):
|
|||
erapi: str
|
||||
"""exchangerate-api.org API token"""
|
||||
environment: Environment = Environment.develop
|
||||
mongo: Mongo
|
||||
redis: Redis
|
||||
mastodon: Optional[Mastodon] = None
|
||||
urls: Optional[dict[str, str]] = None
|
||||
mongo: Mongo = Mongo()
|
||||
redis: Redis = Redis()
|
||||
sync: bool = False
|
||||
log_level: str = "INFO"
|
||||
jurigged: bool = False
|
||||
|
||||
|
||||
_config: Config = None
|
||||
|
||||
|
||||
def _load_json() -> Config | None:
|
||||
path = Path("config.json")
|
||||
config = None
|
||||
if path.exists():
|
||||
with path.open() as f:
|
||||
j = json.loads(f.read())
|
||||
config = Config(**j)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def _load_yaml() -> Config | None:
|
||||
path = Path("config.yaml")
|
||||
config = None
|
||||
if path.exists():
|
||||
with path.open() as f:
|
||||
y = yaml.load(f.read(), Loader=Loader)
|
||||
config = Config(**y)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def _load_env() -> Config | None:
|
||||
load_dotenv()
|
||||
data = {}
|
||||
mongo = {}
|
||||
redis = {}
|
||||
mastodon = {}
|
||||
urls = {}
|
||||
mongo_keys = find_all(lambda x: x.upper().startswith("MONGO"), environ.keys())
|
||||
redis_keys = find_all(lambda x: x.upper().startswith("REDIS"), environ.keys())
|
||||
mastodon_keys = find_all(lambda x: x.upper().startswith("MASTODON"), environ.keys())
|
||||
url_keys = find_all(lambda x: x.upper().startswith("URLS"), environ.keys())
|
||||
|
||||
config_keys = (
|
||||
mongo_keys
|
||||
+ redis_keys
|
||||
+ mastodon_keys
|
||||
+ url_keys
|
||||
+ ["TOKEN", "SYNC", "LOG_LEVEL", "JURIGGED"]
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env", env_file_encoding="utf-8", env_nested_delimiter="."
|
||||
)
|
||||
|
||||
for item, value in environ.items():
|
||||
if item not in config_keys:
|
||||
continue
|
||||
|
||||
if item in mongo_keys:
|
||||
key = "_".join(item.split("_")[1:]).lower()
|
||||
mongo[key] = value
|
||||
elif item in redis_keys:
|
||||
key = "_".join(item.split("_")[1:]).lower()
|
||||
redis[key] = value
|
||||
elif item in mastodon_keys:
|
||||
key = "_".join(item.split("_")[1:]).lower()
|
||||
mastodon[key] = value
|
||||
elif item in url_keys:
|
||||
key = "_".join(item.split("_")[1:]).lower()
|
||||
urls[key] = value
|
||||
else:
|
||||
if item == "SYNC":
|
||||
value = value.lower() in ["yes", "true"]
|
||||
data[item.lower()] = value
|
||||
|
||||
data["mongo"] = mongo
|
||||
data["redis"] = redis
|
||||
if all(x is not None for x in mastodon.values()):
|
||||
data["mastodon"] = mastodon
|
||||
data["urls"] = {k: v for k, v in urls if v}
|
||||
|
||||
return Config(**data)
|
||||
|
||||
|
||||
def load_config(method: Optional[str] = None) -> Config:
|
||||
def load_config() -> Config:
|
||||
"""
|
||||
Load the config using the specified method first
|
||||
|
||||
Args:
|
||||
method: Method to use first
|
||||
"""
|
||||
global _config
|
||||
if _config is not None:
|
||||
return _config
|
||||
|
||||
methods = {"yaml": _load_yaml, "json": _load_json, "env": _load_env}
|
||||
method_names = list(methods.keys())
|
||||
if method and method in method_names:
|
||||
method_names.remove(method)
|
||||
method_names.insert(0, method)
|
||||
|
||||
for method in method_names:
|
||||
if _config := methods[method]():
|
||||
return _config
|
||||
|
||||
raise FileNotFoundError("Missing one of: config.yaml, config.json, .env")
|
||||
return Config()
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
"""JARVIS constants."""
|
||||
|
||||
from importlib.metadata import version as _v
|
||||
|
||||
try:
|
||||
__version__ = _v("jarvis")
|
||||
except Exception:
|
||||
__version__ = "0.0.0"
|
||||
__version__ = "2.5.2"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from datetime import datetime, timezone
|
||||
from pkgutil import iter_modules
|
||||
|
||||
import git
|
||||
from interactions.models.discord.embed import Embed, EmbedField
|
||||
from interactions.models.discord.guild import AuditLogEntry
|
||||
from interactions.models.discord.user import Member
|
||||
|
@ -66,25 +65,4 @@ def modlog_embed(
|
|||
def get_extensions(path: str) -> list:
|
||||
"""Get JARVIS cogs."""
|
||||
vals = [x.name for x in iter_modules(path)]
|
||||
return [f"jarvis.cogs.{x}" for x in vals]
|
||||
|
||||
|
||||
def update() -> int:
|
||||
"""JARVIS update utility."""
|
||||
repo = git.Repo(".")
|
||||
dirty = repo.is_dirty()
|
||||
current_hash = repo.head.object.hexsha
|
||||
origin = repo.remotes.origin
|
||||
origin.fetch()
|
||||
if current_hash != origin.refs["main"].object.hexsha:
|
||||
if dirty:
|
||||
return 2
|
||||
origin.pull()
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def get_repo_hash() -> str:
|
||||
"""JARVIS current branch hash."""
|
||||
repo = git.Repo(".")
|
||||
return repo.head.object.hexsha
|
||||
return [f"jarvis.cogs.{x}" for x in vals]
|
|
@ -1,27 +1,19 @@
|
|||
"""JARVIS update handler."""
|
||||
import asyncio
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from importlib import import_module
|
||||
from inspect import getmembers, isclass
|
||||
from pkgutil import iter_modules
|
||||
from types import FunctionType, ModuleType
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
|
||||
from typing import Any, Callable, Dict, List
|
||||
|
||||
import git
|
||||
from interactions.client.errors import ExtensionNotFound
|
||||
from interactions.client.utils.misc_utils import find, find_all
|
||||
from interactions.client.utils.misc_utils import find_all
|
||||
from interactions.models.internal.application_commands import SlashCommand
|
||||
from interactions.models.internal.extension import Extension
|
||||
from rich.table import Table
|
||||
|
||||
import jarvis.cogs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from interactions.client.client import Client
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpdateResult:
|
||||
|
@ -61,153 +53,3 @@ def get_all_commands(module: ModuleType = jarvis.cogs) -> Dict[str, Callable]:
|
|||
values = cog.__dict__.values()
|
||||
commands[cog.__module__] = find_all(lambda x: isinstance(x, SlashCommand), values)
|
||||
return {k: v for k, v in commands.items() if v}
|
||||
|
||||
|
||||
def get_git_changes(repo: git.Repo) -> dict:
|
||||
"""Get all Git changes"""
|
||||
logger = _logger
|
||||
logger.debug("Getting all git changes")
|
||||
current_hash = repo.head.ref.object.hexsha
|
||||
tracking = repo.head.ref.tracking_branch()
|
||||
|
||||
file_changes = {}
|
||||
for commit in tracking.commit.iter_items(repo, f"{repo.head.ref.path}..{tracking.path}"):
|
||||
if commit.hexsha == current_hash:
|
||||
break
|
||||
files = commit.stats.files
|
||||
file_changes.update({key: {"insertions": 0, "deletions": 0, "lines": 0} for key in files.keys()})
|
||||
for file, stats in files.items():
|
||||
if file not in file_changes:
|
||||
file_changes[file] = {"insertions": 0, "deletions": 0, "lines": 0}
|
||||
for key, val in stats.items():
|
||||
file_changes[file][key] += val
|
||||
logger.debug("Found %i changed files", len(file_changes))
|
||||
|
||||
table = Table(title="File Changes")
|
||||
|
||||
table.add_column("File", justify="left", style="white", no_wrap=True)
|
||||
table.add_column("Insertions", justify="center", style="green")
|
||||
table.add_column("Deletions", justify="center", style="red")
|
||||
table.add_column("Lines", justify="center", style="magenta")
|
||||
|
||||
i_total = 0
|
||||
d_total = 0
|
||||
l_total = 0
|
||||
for file, stats in file_changes.items():
|
||||
i_total += stats["insertions"]
|
||||
d_total += stats["deletions"]
|
||||
l_total += stats["lines"]
|
||||
table.add_row(
|
||||
file,
|
||||
str(stats["insertions"]),
|
||||
str(stats["deletions"]),
|
||||
str(stats["lines"]),
|
||||
)
|
||||
logger.debug("%i insertions, %i deletions, %i total", i_total, d_total, l_total)
|
||||
|
||||
table.add_row("Total", str(i_total), str(d_total), str(l_total))
|
||||
return {
|
||||
"table": table,
|
||||
"lines": {"inserted_lines": i_total, "deleted_lines": d_total, "total_lines": l_total},
|
||||
}
|
||||
|
||||
|
||||
async def update(bot: "Client") -> Optional[UpdateResult]:
|
||||
"""
|
||||
Update JARVIS and return an UpdateResult.
|
||||
|
||||
Args:
|
||||
bot: Bot instance
|
||||
|
||||
Returns:
|
||||
UpdateResult object
|
||||
"""
|
||||
logger = _logger
|
||||
repo = git.Repo(".")
|
||||
current_hash = repo.head.object.hexsha
|
||||
origin = repo.remotes.origin
|
||||
origin.fetch()
|
||||
remote_hash = origin.refs[repo.active_branch.name].object.hexsha
|
||||
|
||||
if current_hash != remote_hash:
|
||||
logger.info("Updating from %s to %s", current_hash, remote_hash)
|
||||
current_commands = get_all_commands()
|
||||
changes = get_git_changes(repo)
|
||||
|
||||
origin.pull()
|
||||
await asyncio.sleep(3)
|
||||
|
||||
new_commands = get_all_commands()
|
||||
|
||||
logger.info("Checking if any modules need reloaded...")
|
||||
|
||||
reloaded = []
|
||||
loaded = []
|
||||
unloaded = []
|
||||
|
||||
logger.debug("Checking for removed cogs")
|
||||
for module in current_commands.keys():
|
||||
if module not in new_commands:
|
||||
logger.debug("Module %s removed after update", module)
|
||||
bot.unload_extension(module)
|
||||
unloaded.append(module)
|
||||
|
||||
logger.debug("Checking for new/modified commands")
|
||||
for module, commands in new_commands.items():
|
||||
logger.debug("Processing %s", module)
|
||||
if module not in current_commands:
|
||||
bot.load_extension(module)
|
||||
loaded.append(module)
|
||||
elif len(current_commands[module]) != len(commands):
|
||||
try:
|
||||
bot.reload_extension(module)
|
||||
except ExtensionNotFound:
|
||||
bot.load_extension(module)
|
||||
reloaded.append(module)
|
||||
else:
|
||||
for command in commands:
|
||||
old_command = find(lambda x: x.resolved_name == command.resolved_name, current_commands[module])
|
||||
|
||||
# Extract useful info
|
||||
old_args = old_command.options
|
||||
if old_args:
|
||||
old_arg_names = [x.name for x in old_args]
|
||||
new_args = command.options
|
||||
if new_args:
|
||||
new_arg_names = [x.name for x in new_args]
|
||||
|
||||
# No changes
|
||||
if not old_args and not new_args:
|
||||
continue
|
||||
|
||||
# Check if number arguments have changed
|
||||
if len(old_args) != len(new_args):
|
||||
try:
|
||||
bot.reload_extension(module)
|
||||
except ExtensionNotFound:
|
||||
bot.load_extension(module)
|
||||
reloaded.append(module)
|
||||
elif any(x not in old_arg_names for x in new_arg_names) or any(
|
||||
x not in new_arg_names for x in old_arg_names
|
||||
):
|
||||
try:
|
||||
bot.reload_extension(module)
|
||||
except ExtensionNotFound:
|
||||
bot.load_extension(module)
|
||||
reloaded.append(module)
|
||||
elif any(new_args[idx].type != x.type for idx, x in enumerate(old_args)):
|
||||
try:
|
||||
bot.reload_extension(module)
|
||||
except ExtensionNotFound:
|
||||
bot.load_extension(module)
|
||||
reloaded.append(module)
|
||||
|
||||
return UpdateResult(
|
||||
old_hash=current_hash,
|
||||
new_hash=remote_hash,
|
||||
added=loaded,
|
||||
removed=unloaded,
|
||||
changed=reloaded,
|
||||
**changes,
|
||||
)
|
||||
return None
|
||||
|
|
2457
poetry.lock
generated
2457
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "jarvis"
|
||||
version = "2.5.2"
|
||||
version = "2.5.3"
|
||||
description = "JARVIS admin bot"
|
||||
authors = ["Zevaryx <zevaryx@gmail.com>"]
|
||||
|
||||
|
@ -37,6 +37,7 @@ pydantic = ">=2.3.0,<3"
|
|||
orjson = "^3.8.8"
|
||||
croniter = "^1.4.1"
|
||||
erapi = { git = "https://git.zevaryx.com/zevaryx-technologies/erapi.git" }
|
||||
pydantic-settings = "^2.2.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pre-commit = "^2.21.0"
|
||||
|
|
20
sample.env
20
sample.env
|
@ -1,5 +1,6 @@
|
|||
# Base Config, required
|
||||
TOKEN=
|
||||
ERAPI=
|
||||
|
||||
# Base Config, optional
|
||||
ENVIRONMENT=develop
|
||||
|
@ -17,22 +18,3 @@ MONGO_PORT=27017
|
|||
REDIS_HOST=localhost
|
||||
REDIS_USERNAME=
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# Mastodon, optional
|
||||
MASTODON_TOKEN=
|
||||
MASTODON_URL=
|
||||
|
||||
# Reddit, optional
|
||||
REDDIT_USER_AGENT=
|
||||
REDDIT_CLIENT_SECRET=
|
||||
REDDIT_CLIENT_ID=
|
||||
|
||||
# Twitter, optional
|
||||
TWITTER_CONSUMER_KEY=
|
||||
TWITTER_CONSUMER_SECRET=
|
||||
TWITTER_ACCESS_TOKEN=
|
||||
TWITTER_ACCESS_SECRET=
|
||||
TWITTER_BEARER_TOKEN=
|
||||
|
||||
# URLs, optional
|
||||
URL_DBRAND=
|
Loading…
Add table
Reference in a new issue