mirror of
https://github.com/migatu/conjurer.git
synced 2026-07-14 13:34:40 +00:00
f9a1e7c03a
Make the stable 'working copy' bot the canonical code at the repository
root so the install/deploy scripts operate against it again.
- Move working_copy/* to root (bot entrypoint is bot.py)
- Restore root-level install/ops scripts from c4fa88e (deploy.sh,
install_main_bot.sh, status_report.*, conjurer.service, etc.)
- Fix deploy.sh: copy bot.py (was thin_client.py) and add the
conanjurer_* modules; bump command count
- Remove side-by-side variant dirs (backup_old_docker, prototype_one,
prototype_musician_one, musician_old, working_copy) and docker cruft
- Keep components as subdirs: conjurer_librarian, conjurer_musician,
spotify_dl, yt_dlp, fonts, utils, docs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
# ai command cogs
|
|
import logging
|
|
import discord
|
|
from discord.ext import commands
|
|
from other_functions import discord_friendly_send, discord_friendly_reply
|
|
from __future__ import annotations
|
|
import asyncio
|
|
import logging
|
|
|
|
from conanjurer_functions import watch, Event
|
|
log = logging.getLogger("discord")
|
|
|
|
def is_gm():
|
|
async def predicate(ctx: commands.Context) -> bool:
|
|
role_id = ctx.bot.cfg.gm_role_id
|
|
ok = any(r.id == role_id for r in getattr(ctx.author, "roles", []))
|
|
if not ok:
|
|
await ctx.reply("⛔ Tylko GM.", mention_author=False)
|
|
return ok
|
|
return commands.check(predicate)
|
|
|
|
|
|
class FromConan(commands.Cog):
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
self._task: asyncio.Task | None = None
|
|
|
|
async def cog_load(self):
|
|
self._task = asyncio.create_task(self._run())
|
|
|
|
async def cog_unload(self):
|
|
if self._task:
|
|
self._task.cancel()
|
|
|
|
async def _run(self):
|
|
await self.bot.wait_until_ready()
|
|
cfg = self.bot.cfg
|
|
chat_ch = self.bot.get_channel(cfg.chan_chat)
|
|
evt_ch = self.bot.get_channel(cfg.chan_events)
|
|
|
|
async def on_event(e: Event):
|
|
target = chat_ch if e.kind == "chat" else evt_ch
|
|
if target is not None:
|
|
# allowed_mentions: nie pinguj nikogo treścią z gry
|
|
await target.send(e.text, allowed_mentions=discord.AllowedMentions.none())
|
|
|
|
log.info("Start obserwacji logu (tryb=%s)", cfg.log_mode)
|
|
await watch(cfg, on_event)
|
|
|
|
class ToConan(commands.Cog):
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
|
|
@commands.command(name="say")
|
|
@is_gm()
|
|
async def say(self, ctx: commands.Context, *, message: str):
|
|
"""Discord -> Conan: ogłoszenie widoczne dla wszystkich graczy w grze."""
|
|
resp = await self.bot.rcon.command(f"broadcast {message}")
|
|
await ctx.reply(f"✅ Wysłano do gry. (serwer: `{resp.strip() or 'OK'}`)",
|
|
mention_author=False)
|
|
|
|
@commands.command(name="players")
|
|
@is_gm()
|
|
async def players(self, ctx: commands.Context):
|
|
"""Lista graczy online (RCON listplayers)."""
|
|
resp = await self.bot.rcon.command("listplayers")
|
|
await ctx.reply(f"```\n{resp.strip() or 'brak danych'}\n```",
|
|
mention_author=False)
|
|
|
|
@commands.command(name="kick")
|
|
@is_gm()
|
|
async def kick(self, ctx: commands.Context, *, who: str):
|
|
"""Wyrzuć gracza (po nazwie/charname — zależnie od wersji serwera)."""
|
|
resp = await self.bot.rcon.command(f"kick {who}")
|
|
await ctx.reply(f"👢 `{resp.strip() or 'OK'}`", mention_author=False)
|
|
|
|
@commands.command(name="rcon")
|
|
@is_gm()
|
|
async def raw_rcon(self, ctx: commands.Context, *, cmd: str):
|
|
"""Surowa komenda RCON (dla zaawansowanych GM). Używaj ostrożnie."""
|
|
resp = await self.bot.rcon.command(cmd)
|
|
await ctx.reply(f"```\n{resp.strip() or 'OK'}\n```", mention_author=False)
|
|
|
|
# --- HOOK pod przyszły mod mostu (Chat V2 API) ---
|
|
@commands.command(name="ogłoś", aliases=["oglos", "rp"])
|
|
@is_gm()
|
|
async def rp_announce(self, ctx: commands.Context, nadawca: str, *, message: str):
|
|
"""Wiadomość RP 'z nadawcą' (np. ogłoszenie w imieniu Króla Khasara).
|
|
|
|
Na samym RCON realizujemy to jako sformatowany broadcast. Gdy dodasz
|
|
własny mod na Chat V2 API z dedykowaną komendą czatu, podmień tę linię
|
|
na wywołanie tej komendy (np. 'tot_rp_say <nadawca> <msg>').
|
|
"""
|
|
resp = await self.bot.rcon.command(f"broadcast [{nadawca}]: {message}")
|
|
await ctx.reply(f"📜 Ogłoszono jako **{nadawca}**.", mention_author=False)
|
|
|
|
|
|
async def setup(bot: commands.Bot):
|
|
await bot.add_cog(ToConan(bot))
|
|
await bot.add_cog(FromConan(bot))
|
|
|
|
|