@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jwebot-config"
|
||||
version = "1.2.8b1+1019"
|
||||
version = "2.0.0b1+1021"
|
||||
description = "Profile-based configuration compiler for JWeBot"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
|
||||
@@ -36,4 +36,4 @@ __all__ = [
|
||||
"write_default_profile",
|
||||
]
|
||||
|
||||
__version__ = "1.2.8b1+1019"
|
||||
__version__ = "2.0.0b1+1021"
|
||||
|
||||
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jwebot-extension-host"
|
||||
version = "1.2.8b1+1019"
|
||||
version = "2.0.0b1+1021"
|
||||
description = "Single-release, single-invocation process host for JWeBot extensions"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"jwebot-sdk==1.2.8b1+1019",
|
||||
"jwebot-kernel==1.2.8b1+1019",
|
||||
"jwebot-sdk==2.0.0b1+1021",
|
||||
"jwebot-kernel==2.0.0b1+1021",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -16,4 +16,4 @@ __all__ = [
|
||||
"process_request",
|
||||
]
|
||||
|
||||
__version__ = "1.2.8b1+1019"
|
||||
__version__ = "2.0.0b1+1021"
|
||||
|
||||
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jwebot-kernel"
|
||||
version = "1.2.8b1+1019"
|
||||
version = "2.0.0b1+1021"
|
||||
description = "Stable routing and extension authority for JWeBot"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"jwebot-config==1.2.8b1+1019",
|
||||
"jwebot-sdk==1.2.8b1+1019",
|
||||
"jwebot-official-extensions==1.2.8b1+1019",
|
||||
"jwebot-config==2.0.0b1+1021",
|
||||
"jwebot-sdk==2.0.0b1+1021",
|
||||
"jwebot-official-extensions==2.0.0b1+1021",
|
||||
"tomli>=2; python_version < '3.11'",
|
||||
]
|
||||
|
||||
|
||||
@@ -107,4 +107,4 @@ __all__ = [
|
||||
"verify_installed_release_signature",
|
||||
]
|
||||
|
||||
__version__ = "1.2.8b1+1019"
|
||||
__version__ = "2.0.0b1+1021"
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
"""Fail-closed conversation identities for local OCR shadow testing."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Any, Mapping
|
||||
|
||||
|
||||
SHADOW_CONFIG_ENV = "JWEBOT_CONVERSATION_SHADOW_CONFIG"
|
||||
SHADOW_CONFIG_VERSION = 1
|
||||
MAX_SHADOW_TARGETS = 8
|
||||
MAX_EVENT_TEXT = 5_000
|
||||
CONVERSATION_KEY = re.compile(r"^[a-z0-9][a-z0-9._-]{0,63}$")
|
||||
TITLE_FINGERPRINT = re.compile(r"^[0-9a-f]{64}$")
|
||||
|
||||
|
||||
class ConversationConfigError(ValueError):
|
||||
"""Raised when an opt-in shadow conversation registry is invalid."""
|
||||
|
||||
|
||||
class ConversationKind(str, Enum):
|
||||
GROUP = "group"
|
||||
DIRECT = "direct"
|
||||
|
||||
|
||||
def _required_text(value: object, *, name: str, limit: int) -> str:
|
||||
text = str(value or "").strip()
|
||||
if not text:
|
||||
raise ConversationConfigError(f"{name} is required")
|
||||
if len(text) > limit:
|
||||
raise ConversationConfigError(f"{name} exceeds {limit} characters")
|
||||
return text
|
||||
|
||||
|
||||
def _trigger_question(text: str, *, bot_mention: str, direct: bool) -> str:
|
||||
mention_prefix = r"(?:[@@]\s*)?" if direct else r"[@@]\s*"
|
||||
mention = re.compile(
|
||||
rf"^\s*{mention_prefix}{re.escape(bot_mention)}"
|
||||
r"(?:\s*[::,,])?\s*(\S.*)$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
for line in text.splitlines():
|
||||
stripped = line.strip()
|
||||
if direct and stripped.startswith("/"):
|
||||
return stripped
|
||||
match = mention.match(line)
|
||||
if match:
|
||||
return match.group(1).strip()
|
||||
return ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ConversationTarget:
|
||||
"""One explicitly registered title fingerprint in shadow mode."""
|
||||
|
||||
key: str
|
||||
kind: ConversationKind
|
||||
title_fingerprint: str
|
||||
sender: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if not CONVERSATION_KEY.fullmatch(self.key):
|
||||
raise ConversationConfigError("conversation key must be an opaque slug")
|
||||
if not TITLE_FINGERPRINT.fullmatch(self.title_fingerprint):
|
||||
raise ConversationConfigError(
|
||||
"title_fingerprint must be a lowercase SHA-256 digest"
|
||||
)
|
||||
if self.kind is ConversationKind.DIRECT:
|
||||
_required_text(self.sender, name="direct sender", limit=120)
|
||||
elif self.sender:
|
||||
raise ConversationConfigError("group targets cannot define a fixed sender")
|
||||
|
||||
@classmethod
|
||||
def from_mapping(cls, value: Mapping[str, Any]) -> "ConversationTarget":
|
||||
if not isinstance(value, Mapping):
|
||||
raise ConversationConfigError("conversation target must be an object")
|
||||
unknown = set(value) - {
|
||||
"key",
|
||||
"kind",
|
||||
"title_fingerprint",
|
||||
"sender",
|
||||
}
|
||||
if unknown:
|
||||
raise ConversationConfigError("conversation target has unknown fields")
|
||||
try:
|
||||
kind = ConversationKind(str(value.get("kind", "")))
|
||||
except ValueError as error:
|
||||
raise ConversationConfigError("conversation kind is invalid") from error
|
||||
return cls(
|
||||
key=_required_text(value.get("key"), name="conversation key", limit=64),
|
||||
kind=kind,
|
||||
title_fingerprint=_required_text(
|
||||
value.get("title_fingerprint"),
|
||||
name="title_fingerprint",
|
||||
limit=64,
|
||||
).casefold(),
|
||||
sender=str(value.get("sender", "")).strip(),
|
||||
)
|
||||
|
||||
def question(self, text: str, *, bot_mention: str) -> str:
|
||||
return _trigger_question(
|
||||
text,
|
||||
bot_mention=bot_mention,
|
||||
direct=self.kind is ConversationKind.DIRECT,
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ShadowConversationRegistry:
|
||||
"""A registry that can observe but can never authorize delivery."""
|
||||
|
||||
enabled: bool = False
|
||||
targets: tuple[ConversationTarget, ...] = ()
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
keys = [target.key for target in self.targets]
|
||||
fingerprints = [target.title_fingerprint for target in self.targets]
|
||||
if len(keys) != len(set(keys)):
|
||||
raise ConversationConfigError("conversation keys must be unique")
|
||||
if len(fingerprints) != len(set(fingerprints)):
|
||||
raise ConversationConfigError("title fingerprints must be unique")
|
||||
|
||||
@classmethod
|
||||
def disabled(cls) -> "ShadowConversationRegistry":
|
||||
return cls()
|
||||
|
||||
@classmethod
|
||||
def from_mapping(cls, value: Mapping[str, Any]) -> "ShadowConversationRegistry":
|
||||
if not isinstance(value, Mapping):
|
||||
raise ConversationConfigError("shadow registry must be an object")
|
||||
unknown = set(value) - {"format_version", "enabled", "targets"}
|
||||
if unknown:
|
||||
raise ConversationConfigError("shadow registry has unknown fields")
|
||||
if value.get("format_version") != SHADOW_CONFIG_VERSION:
|
||||
raise ConversationConfigError("unsupported shadow registry version")
|
||||
enabled = value.get("enabled", False)
|
||||
if not isinstance(enabled, bool):
|
||||
raise ConversationConfigError("shadow registry enabled must be boolean")
|
||||
raw_targets = value.get("targets", [])
|
||||
if not isinstance(raw_targets, list):
|
||||
raise ConversationConfigError("shadow registry targets must be a list")
|
||||
if len(raw_targets) > MAX_SHADOW_TARGETS:
|
||||
raise ConversationConfigError("shadow registry has too many targets")
|
||||
targets = tuple(ConversationTarget.from_mapping(item) for item in raw_targets)
|
||||
if any(target.kind is not ConversationKind.DIRECT for target in targets):
|
||||
raise ConversationConfigError("shadow registry accepts direct targets only")
|
||||
return cls(enabled=enabled, targets=targets)
|
||||
|
||||
@classmethod
|
||||
def from_environment(
|
||||
cls,
|
||||
environment: Mapping[str, str] | None = None,
|
||||
) -> "ShadowConversationRegistry":
|
||||
source = environment if environment is not None else os.environ
|
||||
raw_path = str(source.get(SHADOW_CONFIG_ENV, "")).strip()
|
||||
if not raw_path:
|
||||
return cls.disabled()
|
||||
path = Path(raw_path).expanduser()
|
||||
if path.is_symlink() or not path.is_file():
|
||||
raise ConversationConfigError("shadow registry path must be a regular file")
|
||||
try:
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError) as error:
|
||||
raise ConversationConfigError("shadow registry cannot be read") from error
|
||||
if not isinstance(value, Mapping):
|
||||
raise ConversationConfigError("shadow registry must be an object")
|
||||
return cls.from_mapping(value)
|
||||
|
||||
def target_for_fingerprint(
|
||||
self,
|
||||
fingerprint: str,
|
||||
) -> ConversationTarget | None:
|
||||
if not self.enabled:
|
||||
return None
|
||||
normalized = str(fingerprint).casefold()
|
||||
return next(
|
||||
(
|
||||
target
|
||||
for target in self.targets
|
||||
if target.title_fingerprint == normalized
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
|
||||
def build_shadow_event(
|
||||
target: ConversationTarget,
|
||||
*,
|
||||
observed_at: str,
|
||||
text: str,
|
||||
body_confidence: float,
|
||||
visual_signature: str,
|
||||
bot_mention: str,
|
||||
observed_sender: str = "",
|
||||
sender_confidence: float = 0.0,
|
||||
ordinal: int = 0,
|
||||
) -> dict[str, Any]:
|
||||
"""Build a non-dispatchable observation for synthetic and shadow tests."""
|
||||
|
||||
content = _required_text(text, name="event text", limit=MAX_EVENT_TEXT)
|
||||
question = target.question(content, bot_mention=bot_mention)
|
||||
sender = (
|
||||
target.sender
|
||||
if target.kind is ConversationKind.DIRECT
|
||||
else _required_text(observed_sender, name="observed sender", limit=120)
|
||||
)
|
||||
effective_sender_confidence = (
|
||||
1.0
|
||||
if target.kind is ConversationKind.DIRECT
|
||||
else max(0.0, min(1.0, float(sender_confidence)))
|
||||
)
|
||||
effective_body_confidence = max(0.0, min(1.0, float(body_confidence)))
|
||||
seed = (
|
||||
f"{target.key}\n{observed_at}\n{ordinal}\n{visual_signature}\n"
|
||||
f"{sender}\n{content}"
|
||||
)
|
||||
return {
|
||||
"version": 1,
|
||||
"event_id": f"shadow-{hashlib.sha256(seed.encode()).hexdigest()[:24]}",
|
||||
"observed_at": observed_at,
|
||||
"sender": sender,
|
||||
"text": content,
|
||||
"question": question,
|
||||
"confidence": min(
|
||||
effective_sender_confidence,
|
||||
effective_body_confidence,
|
||||
),
|
||||
"sender_confidence": effective_sender_confidence,
|
||||
"body_confidence": effective_body_confidence,
|
||||
"side": "incoming",
|
||||
"mention_bot": bool(question),
|
||||
"group_fingerprint": target.title_fingerprint,
|
||||
"conversation_key": target.key,
|
||||
"conversation_kind": target.kind.value,
|
||||
"source": (
|
||||
"rapidocr-private-shadow"
|
||||
if target.kind is ConversationKind.DIRECT
|
||||
else "rapidocr-group-shadow"
|
||||
),
|
||||
"shadow_only": True,
|
||||
"dispatch_allowed": False,
|
||||
}
|
||||
@@ -8009,6 +8009,20 @@ class EdgeApplication:
|
||||
started = time.monotonic()
|
||||
event_id = str(event.get("event_id", ""))
|
||||
group_id = str(event.get("group_fingerprint", ""))
|
||||
if event.get("shadow_only") or event.get("dispatch_allowed") is False:
|
||||
self.telemetry.elapsed(
|
||||
"edge.event.accepted",
|
||||
started,
|
||||
status="shadow_ignored",
|
||||
event_id=event_id,
|
||||
group_id=group_id,
|
||||
route="none",
|
||||
execution_path="none",
|
||||
)
|
||||
return {
|
||||
"status": "ignored",
|
||||
"reason": "shadow_only",
|
||||
}
|
||||
question = event_question(event)
|
||||
decision = route_question(question)
|
||||
route = decision.route.value
|
||||
|
||||
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jwebot-official-extensions"
|
||||
version = "1.2.8b1+1019"
|
||||
version = "2.0.0b1+1021"
|
||||
description = "Reviewed local command adapters and broker implementation for JWeBot"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"jwebot-sdk==1.2.8b1+1019",
|
||||
"jwebot-sdk==2.0.0b1+1021",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
|
||||
@@ -90,4 +90,4 @@ __all__ = [
|
||||
"render_feature_list",
|
||||
]
|
||||
|
||||
__version__ = "1.2.8b1+1019"
|
||||
__version__ = "2.0.0b1+1021"
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for coin."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '抛一枚硬币'
|
||||
HELP_ENTRIES = ('/翻硬币',)
|
||||
COMMANDS = ('/翻硬币',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for coin-loan."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin-loan'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '贷款'
|
||||
HELP_ENTRIES = ('/贷款;/还款',)
|
||||
COMMANDS = ('/贷款', '/借款', '/loan', '/borrow', '/还款', '/repay')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for coin-ranking."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin-ranking'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '富榜'
|
||||
HELP_ENTRIES = ('/大富翁榜',)
|
||||
COMMANDS = ('/摩拉排行', '/摩拉排行榜', '/金币排行', '/金币排行榜', '/大富翁榜', '/richlist')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for coin-taffy."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin-taffy'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = 'Taffy摩拉'
|
||||
HELP_ENTRIES = ('/Taffy摩拉(兼容 /Taffy金币)',)
|
||||
COMMANDS = ('/Taffy摩拉', '/Taffy金币', '/taffycoins')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for coin-transfer."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin-transfer'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '摩拉转账'
|
||||
HELP_ENTRIES = ('/转账 对方 金额;/transfer',)
|
||||
COMMANDS = ('/转账', '/transfer')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for context-summary."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'context-summary'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = '上下文总结'
|
||||
HELP_ENTRIES = ('/上下文 [100|200|300];/context [100|200|300]',)
|
||||
COMMANDS = ('/上下文', '/context')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for cs-major-autochess."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'cs-major-autochess'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '自走棋'
|
||||
HELP_ENTRIES = ('/自走棋 开始|报名|选',)
|
||||
COMMANDS = ('/自走棋', '/cs自走棋', '/autochess', '/选', '/刷新', '/锁定', '/战术', '/升级教练', '/上阵', '/下阵', '/出售', '/阵容', '/赛程', '/结束回合')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for daily-fortune."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'daily-fortune'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '生成当天稳定一致的运势'
|
||||
HELP_ENTRIES = ('/今日运势',)
|
||||
COMMANDS = ('/今日运势',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for debug-telemetry."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'debug-telemetry'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = '埋点 p50/p95'
|
||||
HELP_ENTRIES = ('/debug',)
|
||||
COMMANDS = ('/debug',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for dice."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'dice'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '骰子和多人骰子挑战'
|
||||
HELP_ENTRIES = ('/丢骰子 [NdM]', '/丢骰子挑战 [5d6|5d20|状态|结算|战绩|结束]')
|
||||
COMMANDS = ('/丢骰子', '/骰子', '/丢骰子挑战', '/骰子挑战')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for draw-lot."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'draw-lot'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '抽取一条本地签文'
|
||||
HELP_ENTRIES = ('/抽签',)
|
||||
COMMANDS = ('/抽签',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for game-history."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'game-history'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '游戏记录'
|
||||
HELP_ENTRIES = ('/游戏记录 /个人记录 /gamehistory',)
|
||||
COMMANDS = ('/游戏记录', '/个人记录', '/gamehistory')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for guess-number."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'guess-number'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '群内持久化猜数字游戏'
|
||||
HELP_ENTRIES = ('/猜数字 开始 [上限];/猜 数字;/猜数字 [状态|结束]',)
|
||||
COMMANDS = ('/猜数字', '/猜')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for history-search."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'history-search'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '搜索本地群聊文字记录'
|
||||
HELP_ENTRIES = ('/查记录 关键词',)
|
||||
COMMANDS = ('/查记录', '/历史搜索')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for jwebot-version."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'jwebot-version'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = 'JWeBot 版本'
|
||||
HELP_ENTRIES = ('/version /版本',)
|
||||
COMMANDS = ('/版本', '/version')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for person-directory."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'person-directory'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = '人物索引'
|
||||
HELP_ENTRIES = ('/人物列表 [页码] /people;/人物 [名称或别名] /person',)
|
||||
COMMANDS = ('/人物列表', '/别名列表', '/people', '/人物', '/个人属性', '/person')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for person-memory."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'person-memory'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = '管理个人和同群人物记忆'
|
||||
HELP_ENTRIES = ('/记住 内容;/我的记忆;/忘记 关键词或全部;/人物记忆 [显示名]',)
|
||||
COMMANDS = ('/记住', '/我的记忆', '/忘记', '/人物记忆', '/记忆帮助')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for primogem-economy."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'primogem-economy'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '原石系统'
|
||||
HELP_ENTRIES = ('/原石祈愿 /原石榜;/扫码加权 人;/Taffy发话 [定时HH:MM] 内容',)
|
||||
COMMANDS = ('/原石祈愿', '/祈愿', '/wish', '/原石榜', '/primogem榜', '/扫码加权', '/扫码概率', '/Taffy发话', '/taffysay')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for random-number."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'random-number'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '在指定整数范围内取随机数'
|
||||
HELP_ENTRIES = ('/随机数 最小值 最大值',)
|
||||
COMMANDS = ('/随机数',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for repeat-ranking."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'repeat-ranking'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '查看北京时间今日复读排行'
|
||||
HELP_ENTRIES = ('/复读榜',)
|
||||
COMMANDS = ('/复读榜', '/复读')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for rock-paper-scissors."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'rock-paper-scissors'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '多人石头剪刀布游戏'
|
||||
HELP_ENTRIES = ('/石头剪刀布 [开始|加入|出 选择|状态|结算|结束]',)
|
||||
COMMANDS = ('/石头剪刀布',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for scan-ranking."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'scan-ranking'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '查看北京时间今日扫码排行'
|
||||
HELP_ENTRIES = ('/扫码排行',)
|
||||
COMMANDS = ('/扫码排行', '/扫码榜', '/今日扫码')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for server-status."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'server-status'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'official'
|
||||
DESCRIPTION = '服务器状态'
|
||||
HELP_ENTRIES = ('/状态;/status',)
|
||||
COMMANDS = ('/状态', '/status')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for single-player-games."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'single-player-games'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '摩拉游戏'
|
||||
HELP_ENTRIES = ('/摩拉/原石 /抽奖 /彩票 /21点 /游戏帮助',)
|
||||
COMMANDS = ('/摩拉', '/金币', '/wallet', '/原石', '/抽奖', '/draw', '/彩票', '/买彩票', '/lottery', '/21点', '/二十一点', '/blackjack', '/游戏帮助', '/games')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for steam-presence."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'steam-presence'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = 'Steam 状态与时长'
|
||||
HELP_ENTRIES = ('/steam;/steam时长 游戏[、玩家]',)
|
||||
COMMANDS = ('/steam',)
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
+6
-33
@@ -1,6 +1,6 @@
|
||||
"""Generated reviewed adapter for trivia-quiz."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
from jwebot_sdk import ServiceCommandAdapter, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'trivia-quiz'
|
||||
@@ -8,38 +8,11 @@ AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '冷门知识问答'
|
||||
HELP_ENTRIES = ('/回答 A;/answer A',)
|
||||
COMMANDS = ('/回答', '/answer')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
ADAPTER = ServiceCommandAdapter(
|
||||
PROFILE,
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
ADAPTER.register(context, COMMANDS)
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jwebot-sdk"
|
||||
version = "1.2.8b1+1019"
|
||||
version = "2.0.0b1+1021"
|
||||
description = "Typed, capability-limited extension API for JWeBot plugins"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = []
|
||||
|
||||
@@ -8,6 +8,7 @@ from .context import (
|
||||
PluginLogger,
|
||||
PluginStorage,
|
||||
Scheduler,
|
||||
ServiceCommandAdapter,
|
||||
SingleGroupContext,
|
||||
)
|
||||
from .contracts import (
|
||||
@@ -35,7 +36,8 @@ __all__ = [
|
||||
"PluginStorage",
|
||||
"ReplyPlan",
|
||||
"Scheduler",
|
||||
"ServiceCommandAdapter",
|
||||
"SingleGroupContext",
|
||||
]
|
||||
|
||||
__version__ = "1.2.8b1+1019"
|
||||
__version__ = "2.0.0b1+1021"
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Mapping
|
||||
from collections.abc import Callable, Iterable, Mapping
|
||||
from typing import Protocol
|
||||
|
||||
from .contracts import Event, ExtensionResult, Fact
|
||||
from .contracts import Event, ExtensionResult, Fact, ReplyPlan
|
||||
|
||||
|
||||
CommandHandler = Callable[[Event, str], ExtensionResult]
|
||||
@@ -68,3 +68,67 @@ class SingleGroupContext(Protocol):
|
||||
facts: FactWriter
|
||||
scheduler: Scheduler
|
||||
logger: PluginLogger
|
||||
|
||||
|
||||
class ServiceCommandAdapter:
|
||||
"""Register commands that delegate only to declared kernel service profiles."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
profile: str,
|
||||
*,
|
||||
operation: str = "execute",
|
||||
metadata: Mapping[str, str] | None = None,
|
||||
) -> None:
|
||||
self.profile = self._bounded_text(profile, "profile")
|
||||
self.operation = self._bounded_text(operation, "operation")
|
||||
self.metadata = {
|
||||
str(key): str(value)
|
||||
for key, value in (metadata or {}).items()
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _bounded_text(value: object, name: str) -> str:
|
||||
text = str(value or "").strip()
|
||||
if not text or len(text) > 80:
|
||||
raise ValueError(f"{name} is invalid")
|
||||
return text
|
||||
|
||||
def _handler(self, context: SingleGroupContext, command: str) -> CommandHandler:
|
||||
command_name = self._bounded_text(command, "command")
|
||||
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
self.profile,
|
||||
operation=self.operation,
|
||||
payload={
|
||||
"command": command_name,
|
||||
"arguments": str(arguments),
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts:
|
||||
if not all(isinstance(item, str) and item.strip() for item in texts):
|
||||
raise ValueError("service returned invalid text parts")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata=self.metadata,
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata=self.metadata,
|
||||
)
|
||||
|
||||
return handle
|
||||
|
||||
def register(
|
||||
self,
|
||||
context: SingleGroupContext,
|
||||
commands: Iterable[str],
|
||||
) -> None:
|
||||
for command in commands:
|
||||
context.commands.register(command, self._handler(context, command))
|
||||
|
||||
Reference in New Issue
Block a user