This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from .cs_autochess import (
|
||||
CARD_BY_ID,
|
||||
COACH_BONUSES,
|
||||
COACH_POOL,
|
||||
MAX_PLAYERS,
|
||||
MIN_PLAYERS,
|
||||
PLAYER_POOL,
|
||||
@@ -32,6 +33,8 @@ from .local_commands import (
|
||||
LocalCommandError,
|
||||
deterministic_int,
|
||||
local_command_parts,
|
||||
pack_reply_parts,
|
||||
unpack_reply_parts,
|
||||
)
|
||||
from .runtime import (
|
||||
LocalExtensionError,
|
||||
@@ -49,6 +52,7 @@ from .steam import (
|
||||
__all__ = [
|
||||
"CARD_BY_ID",
|
||||
"COACH_BONUSES",
|
||||
"COACH_POOL",
|
||||
"CsMajorAutochess",
|
||||
"DICE_CHALLENGE_TIMEOUT_SECONDS",
|
||||
"DEFAULT_STEAM_MIHOMO_PROXY_URL",
|
||||
@@ -79,9 +83,11 @@ __all__ = [
|
||||
"local_extension_command_token",
|
||||
"lineup_power",
|
||||
"matchup_modifier",
|
||||
"pack_reply_parts",
|
||||
"parse_autochess_action",
|
||||
"unpack_reply_parts",
|
||||
"extension_for_kind",
|
||||
"render_feature_list",
|
||||
]
|
||||
|
||||
__version__ = "0.6.5a0+1015"
|
||||
__version__ = "0.6.6a0+1015"
|
||||
|
||||
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ def _handler(context: SingleGroupContext, command: str):
|
||||
"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")
|
||||
|
||||
+1032
-472
File diff suppressed because it is too large
Load Diff
+36
-1
@@ -25,6 +25,7 @@ MAX_RPS_PLAYERS = 8
|
||||
BEIJING_TIMEZONE = ZoneInfo("Asia/Shanghai")
|
||||
DICE_PATTERN = re.compile(r"^(?:(\d{1,2})[dD](\d{1,3}))?$")
|
||||
RANDOM_NUMBER_PATTERN = re.compile(r"^(-?\d{1,6})\s+(-?\d{1,6})$")
|
||||
MULTI_REPLY_MARKER = "\x1eJWEBOT_MULTI_REPLY_V1\x1e"
|
||||
|
||||
|
||||
class LocalCommandError(RuntimeError):
|
||||
@@ -53,6 +54,36 @@ def deterministic_int(seed: str, lower: int, upper: int) -> int:
|
||||
return lower + value % (upper - lower + 1)
|
||||
|
||||
|
||||
def pack_reply_parts(parts: list[str] | tuple[str, ...]) -> str:
|
||||
cleaned = [str(part).strip() for part in parts if str(part).strip()]
|
||||
if not cleaned:
|
||||
raise LocalCommandError("本地命令没有可发送回复")
|
||||
if len(cleaned) == 1:
|
||||
return cleaned[0]
|
||||
return MULTI_REPLY_MARKER + json.dumps(
|
||||
cleaned,
|
||||
ensure_ascii=False,
|
||||
separators=(",", ":"),
|
||||
)
|
||||
|
||||
|
||||
def unpack_reply_parts(value: object) -> list[str] | None:
|
||||
text = str(value or "")
|
||||
if not text.startswith(MULTI_REPLY_MARKER):
|
||||
return None
|
||||
try:
|
||||
payload = json.loads(text[len(MULTI_REPLY_MARKER) :])
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
if (
|
||||
not isinstance(payload, list)
|
||||
or not payload
|
||||
or any(not isinstance(item, str) or not item.strip() for item in payload)
|
||||
):
|
||||
return None
|
||||
return [item.strip() for item in payload]
|
||||
|
||||
|
||||
def local_command_parts(question: str) -> tuple[str, str]:
|
||||
normalized = question.lstrip()
|
||||
if not normalized.startswith("/"):
|
||||
@@ -131,7 +162,11 @@ class LocalCommandEngine:
|
||||
}:
|
||||
return self.reply_cleaner(self.players.handle(row, kind, arguments))
|
||||
if kind == "cs_autochess":
|
||||
return self.reply_cleaner(self.autochess.handle(row))
|
||||
parts = [
|
||||
self.reply_cleaner(part)
|
||||
for part in self.autochess.handle_parts(row)
|
||||
]
|
||||
return pack_reply_parts(parts)
|
||||
if kind == "dice":
|
||||
return self.reply_cleaner(self.dice(row, arguments))
|
||||
if kind == "dice_challenge":
|
||||
|
||||
@@ -14,6 +14,8 @@ from .local_commands import (
|
||||
LocalCommandEngine,
|
||||
local_command_parts,
|
||||
utc_now,
|
||||
pack_reply_parts,
|
||||
unpack_reply_parts,
|
||||
)
|
||||
|
||||
|
||||
@@ -74,7 +76,11 @@ class LocalServiceBroker:
|
||||
"question": f"{command} {arguments}".rstrip(),
|
||||
"created_at": str(event.get("observed_at") or utc_now()),
|
||||
}
|
||||
return {"text": self.engine.handle(row, event)}
|
||||
text = self.engine.handle(row, event)
|
||||
parts = unpack_reply_parts(text)
|
||||
if parts is not None:
|
||||
return {"text": parts[0], "texts": parts}
|
||||
return {"text": text}
|
||||
|
||||
|
||||
class _Context:
|
||||
@@ -162,6 +168,8 @@ class LocalExtensionRuntime:
|
||||
result = handler(sdk_event, arguments)
|
||||
if not isinstance(result, ExtensionResult):
|
||||
raise LocalExtensionError("local adapter returned invalid result")
|
||||
if result.reply.kind is PlanKind.MULTI_TEXT:
|
||||
return pack_reply_parts(list(result.reply.messages))
|
||||
if result.reply.kind is not PlanKind.TEXT:
|
||||
raise LocalExtensionError("local command returned no visible reply")
|
||||
return result.reply.message
|
||||
|
||||
Reference in New Issue
Block a user