mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-09 14:23:44 +00:00
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch: accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes they need. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
"""python3 -m chat_bridge --config config.json [--check] [-v]"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import asyncio
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
from .adapters import ADAPTERS
|
|
from .bridge import Bridge, Link
|
|
from .config import load_config
|
|
from .dashboard import ApiError, Dashboard
|
|
|
|
|
|
class _Subscribed(Exception):
|
|
pass
|
|
|
|
|
|
def _stop() -> None:
|
|
raise _Subscribed
|
|
|
|
|
|
async def check(dashboard: Dashboard) -> int:
|
|
"""Try the token: who it signs in as, and whether it can read and subscribe (it doesn't post anything)."""
|
|
me = await dashboard.me()
|
|
if not me.get("valid"):
|
|
print("token: not valid")
|
|
return 1
|
|
print(f"token: {me['username']} (account {me['accountId']}, GM {me['gmLevel']})")
|
|
ok = True
|
|
try:
|
|
page = await dashboard.chat_page({"limit": "1"})
|
|
print(f"read chat (chat_view): yes, newest id {page.get('last_id')}")
|
|
except ApiError as e:
|
|
print(f"read chat (chat_view): no ({e})")
|
|
ok = False
|
|
try:
|
|
await asyncio.wait_for(dashboard.watch_chat(lambda _e: None, _stop), 10)
|
|
except _Subscribed:
|
|
print("live chat (WebSocket): yes")
|
|
except ImportError:
|
|
print("live chat (WebSocket): no, the websockets package isn't installed (the bridge will poll)")
|
|
except Exception as e:
|
|
print(f"live chat (WebSocket): no ({e}); the bridge will poll")
|
|
print("send chat (chat_send): not tried here; see the Permissions page")
|
|
return 0 if ok else 1
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(prog="chat_bridge", description="Bridge game chat to Discord and other services through the dashboard API")
|
|
parser.add_argument("--config", default=os.environ.get("CHAT_BRIDGE_CONFIG", "config.json"))
|
|
parser.add_argument("--check", action="store_true", help="check the token and permissions, then exit")
|
|
parser.add_argument("-v", "--verbose", action="store_true")
|
|
args = parser.parse_args()
|
|
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, stream=sys.stderr,
|
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s")
|
|
# websockets' debug log prints request headers, which carry the API token
|
|
logging.getLogger("websockets").setLevel(logging.INFO)
|
|
|
|
config = load_config(args.config, {name: cls.default_label for name, cls in ADAPTERS.items()})
|
|
if not os.path.isabs(config.state_file):
|
|
config.state_file = os.path.join(os.path.dirname(os.path.abspath(args.config)), config.state_file)
|
|
dashboard = Dashboard(config.url, config.token)
|
|
if args.check:
|
|
return asyncio.run(check(dashboard))
|
|
|
|
links = []
|
|
for link_cfg in config.links:
|
|
if link_cfg.adapter not in ADAPTERS:
|
|
parser.error(f"unknown adapter {link_cfg.adapter!r}; known: {', '.join(ADAPTERS)}")
|
|
links.append(Link(link_cfg, ADAPTERS[link_cfg.adapter](link_cfg.settings)))
|
|
try:
|
|
asyncio.run(Bridge(config, dashboard, links).run())
|
|
except KeyboardInterrupt:
|
|
pass
|
|
except RuntimeError as e:
|
|
logging.error("%s", e)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|