mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2024-11-23 20:45:06 +08:00
namerena 加上 peek
This commit is contained in:
parent
ed6af04570
commit
3d338b8ba0
|
@ -1,6 +1,6 @@
|
||||||
# Python 兼容版本 3.8+
|
# Python 兼容版本 3.8+
|
||||||
|
|
||||||
from typing import Callable, Tuple, NewType, TYPE_CHECKING, TypeVar, Optional
|
from typing import Callable, Tuple, NewType, TYPE_CHECKING, TypeVar, Optional, Union
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ica.rs
|
ica.rs
|
||||||
|
@ -270,6 +270,15 @@ class TailchatClient:
|
||||||
"""向日志中输出警告信息"""
|
"""向日志中输出警告信息"""
|
||||||
|
|
||||||
|
|
||||||
|
class ReciveMessage(TailchatReciveMessage, IcaNewMessage):
|
||||||
|
"""
|
||||||
|
继承了两边的消息
|
||||||
|
只是用来类型标记, 不能实例化
|
||||||
|
"""
|
||||||
|
def reply_with(self, message: str) -> Union["IcaReplyMessage", "TailchatSendingMessage"]: # type: ignore
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class ConfigData:
|
class ConfigData:
|
||||||
def __getitem__(self, key: str):
|
def __getitem__(self, key: str):
|
||||||
...
|
...
|
||||||
|
|
213
ica-rs/plugins/name_utils/__init__.py
Normal file
213
ica-rs/plugins/name_utils/__init__.py
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
import io
|
||||||
|
|
||||||
|
sklname = [
|
||||||
|
"火球术",
|
||||||
|
"冰冻术",
|
||||||
|
"雷击术",
|
||||||
|
"地裂术",
|
||||||
|
"吸血攻击",
|
||||||
|
"投毒",
|
||||||
|
"连击",
|
||||||
|
"会心一击",
|
||||||
|
"瘟疫",
|
||||||
|
"生命之轮",
|
||||||
|
"狂暴术",
|
||||||
|
"魅惑",
|
||||||
|
"加速术",
|
||||||
|
"减速术",
|
||||||
|
"诅咒",
|
||||||
|
"治愈魔法",
|
||||||
|
"苏生术",
|
||||||
|
"净化",
|
||||||
|
"铁壁",
|
||||||
|
"蓄力",
|
||||||
|
"聚气",
|
||||||
|
"潜行",
|
||||||
|
"血祭",
|
||||||
|
"分身",
|
||||||
|
"幻术",
|
||||||
|
"防御",
|
||||||
|
"守护",
|
||||||
|
"伤害反弹",
|
||||||
|
"护身符",
|
||||||
|
"护盾",
|
||||||
|
"反击",
|
||||||
|
"吞噬",
|
||||||
|
"召唤亡灵",
|
||||||
|
"垂死抗争",
|
||||||
|
"隐匿",
|
||||||
|
"sklvoid1",
|
||||||
|
"sklvoid2",
|
||||||
|
"sklvoid3",
|
||||||
|
"sklvoid4",
|
||||||
|
"sklvoid5",
|
||||||
|
]
|
||||||
|
|
||||||
|
prop_names = [
|
||||||
|
"HP",
|
||||||
|
"攻",
|
||||||
|
"防",
|
||||||
|
"速",
|
||||||
|
"敏",
|
||||||
|
"魔",
|
||||||
|
"抗",
|
||||||
|
"智",
|
||||||
|
"八维",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Player:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.name = ""
|
||||||
|
self.team = ""
|
||||||
|
self.val = [i for i in range(0, 256)]
|
||||||
|
self.name_base = [0] * 128
|
||||||
|
self.name_str = [0] * 256
|
||||||
|
self.team_str = [0] * 256
|
||||||
|
self.name_len = 0
|
||||||
|
self.team_len = 0
|
||||||
|
self.name_prop = [0] * 8
|
||||||
|
self.skl_id = [i for i in range(0, 40)]
|
||||||
|
self.skl_freq = [0] * 40
|
||||||
|
|
||||||
|
def load(self, raw_name: str):
|
||||||
|
if raw_name == "":
|
||||||
|
print("错误:输入不能为空。")
|
||||||
|
return False
|
||||||
|
if raw_name.count("@") > 1:
|
||||||
|
print("错误:无法分割名字与战队名,请检查输入。")
|
||||||
|
return False
|
||||||
|
name_lst = list(raw_name.rpartition("@"))
|
||||||
|
if len(name_lst[0]) > 256 or len(name_lst[2]) > 256:
|
||||||
|
print("错误:名字或战队名长度过大。")
|
||||||
|
return False
|
||||||
|
if name_lst[1] == "@":
|
||||||
|
if name_lst[2] == "":
|
||||||
|
name_lst[2] = name_lst[0]
|
||||||
|
else:
|
||||||
|
name_lst[0] = name_lst[2]
|
||||||
|
name_bytes = name_lst[0].encode()
|
||||||
|
team_bytes = name_lst[2].encode()
|
||||||
|
self.name = name_lst[0]
|
||||||
|
self.team = name_lst[2]
|
||||||
|
self.name_len = len(name_lst[0])
|
||||||
|
self.team_len = len(name_lst[2])
|
||||||
|
for i in range(self.name_len):
|
||||||
|
self.name_str[i + 1] = name_bytes[i]
|
||||||
|
for i in range(self.team_len):
|
||||||
|
self.team_str[i + 1] = team_bytes[i]
|
||||||
|
self.name_len += 1
|
||||||
|
self.team_len += 1
|
||||||
|
|
||||||
|
s = 0
|
||||||
|
for i in range(256):
|
||||||
|
s += self.team_str[i % self.team_len] + self.val[i]
|
||||||
|
s %= 256
|
||||||
|
self.val[i], self.val[s] = self.val[s], self.val[i]
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
s = 0
|
||||||
|
for j in range(256):
|
||||||
|
s += self.name_str[j % self.name_len] + self.val[j]
|
||||||
|
s %= 256
|
||||||
|
self.val[j], self.val[s] = self.val[s], self.val[j]
|
||||||
|
s = 0
|
||||||
|
for i in range(256):
|
||||||
|
m = ((self.val[i] * 181) + 160) % 256
|
||||||
|
if m >= 89 and m < 217:
|
||||||
|
self.name_base[s] = m & 63
|
||||||
|
s += 1
|
||||||
|
|
||||||
|
propcnt = 0
|
||||||
|
r = self.name_base[0:32]
|
||||||
|
for i in range(10, 31, 3):
|
||||||
|
r[i : i + 3] = sorted(r[i : i + 3])
|
||||||
|
self.name_prop[propcnt] = r[i + 1]
|
||||||
|
propcnt += 1
|
||||||
|
r[0:10] = sorted(r[0:10])
|
||||||
|
self.name_prop[propcnt] = 154
|
||||||
|
propcnt += 1
|
||||||
|
for i in range(3, 7):
|
||||||
|
self.name_prop[propcnt - 1] += r[i]
|
||||||
|
for i in range(7):
|
||||||
|
self.name_prop[i] += 36
|
||||||
|
|
||||||
|
self.skl_id = list(range(0, 40))
|
||||||
|
self.skl_freq = [0] * 40
|
||||||
|
a = b = 0
|
||||||
|
randbase = []
|
||||||
|
randbase[:] = self.val[:]
|
||||||
|
|
||||||
|
def randgen():
|
||||||
|
def m():
|
||||||
|
nonlocal a, b, randbase
|
||||||
|
a = (a + 1) % 256
|
||||||
|
b = (b + randbase[a]) % 256
|
||||||
|
randbase[a], randbase[b] = randbase[b], randbase[a]
|
||||||
|
return randbase[(randbase[a] + randbase[b]) & 255]
|
||||||
|
|
||||||
|
return ((m() << 8) | m()) % 40
|
||||||
|
|
||||||
|
s = 0
|
||||||
|
for i in range(2):
|
||||||
|
for j in range(40):
|
||||||
|
rand = randgen()
|
||||||
|
s = (s + rand + self.skl_id[j]) % 40
|
||||||
|
self.skl_id[j], self.skl_id[s] = self.skl_id[s], self.skl_id[j]
|
||||||
|
last = -1
|
||||||
|
j = 0
|
||||||
|
for i in range(64, 128, 4):
|
||||||
|
p = (
|
||||||
|
min(
|
||||||
|
self.name_base[i],
|
||||||
|
self.name_base[i + 1],
|
||||||
|
self.name_base[i + 2],
|
||||||
|
self.name_base[i + 3],
|
||||||
|
)
|
||||||
|
% 256
|
||||||
|
)
|
||||||
|
if p > 10 and self.skl_id[j] < 35:
|
||||||
|
self.skl_freq[j] = p - 10
|
||||||
|
if self.skl_id[j] < 25:
|
||||||
|
last = j
|
||||||
|
j += 1
|
||||||
|
if last != -1:
|
||||||
|
self.skl_freq[last] *= 2
|
||||||
|
if self.skl_freq[14] > 0 and last != 14:
|
||||||
|
self.skl_freq[14] += min(
|
||||||
|
self.name_base[60], self.name_base[61], self.skl_freq[14]
|
||||||
|
)
|
||||||
|
if self.skl_freq[15] > 0 and last != 15:
|
||||||
|
self.skl_freq[15] += min(
|
||||||
|
self.name_base[62], self.name_base[63], self.skl_freq[15]
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def display(self) -> str:
|
||||||
|
cache = io.StringIO()
|
||||||
|
cache.write(f"{self.name}@{self.team}|")
|
||||||
|
full = sum(self.name_prop[0:7]) + round(self.name_prop[7] / 3)
|
||||||
|
datas = [
|
||||||
|
self.name_prop[7],
|
||||||
|
*self.name_prop[0:7],
|
||||||
|
full
|
||||||
|
]
|
||||||
|
cache.write(
|
||||||
|
"|".join(
|
||||||
|
[
|
||||||
|
f"{prop_names[index]}:{value}"
|
||||||
|
for index, value in enumerate(datas)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cache.write("\n")
|
||||||
|
cache.write(
|
||||||
|
"|".join(
|
||||||
|
[
|
||||||
|
f"{sklname[self.skl_id[index]]}:{self.skl_freq[index]}"
|
||||||
|
for index, value in enumerate(self.skl_freq)
|
||||||
|
if value > 0
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return cache.getvalue()
|
|
@ -1,3 +1,5 @@
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -6,31 +8,67 @@ from pathlib import Path
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, TypeVar
|
from typing import TYPE_CHECKING, TypeVar
|
||||||
|
|
||||||
|
if str(Path(__file__).parent.absolute()) not in sys.path:
|
||||||
|
sys.path.append(str(Path(__file__).parent.absolute()))
|
||||||
|
|
||||||
|
import name_utils
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ica_typing import IcaNewMessage, IcaClient, ConfigData
|
from ica_typing import IcaNewMessage, IcaClient, ConfigData, ReciveMessage, TailchatReciveMessage
|
||||||
|
|
||||||
CONFIG_DATA: ConfigData
|
CONFIG_DATA: ConfigData
|
||||||
else:
|
else:
|
||||||
CONFIG_DATA = None # type: ignore
|
CONFIG_DATA = None # type: ignore
|
||||||
IcaNewMessage = TypeVar("NewMessage")
|
IcaNewMessage = TypeVar("NewMessage")
|
||||||
IcaClient = TypeVar("IcaClient")
|
IcaClient = TypeVar("IcaClient")
|
||||||
|
ReciveMessage = TypeVar("ReciveMessage")
|
||||||
|
TailchatReciveMessage = TypeVar("TailchatReciveMessage")
|
||||||
|
|
||||||
_version_ = "0.4.2"
|
|
||||||
|
|
||||||
COMMAND = "/namerena"
|
_version_ = "0.5.0"
|
||||||
|
|
||||||
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
|
EVAL_PREFIX = "/namerena"
|
||||||
if not msg.content.startswith("/namerena") or msg.is_reply:
|
CONVERT_PREFIX = "/namer-peek"
|
||||||
return
|
|
||||||
|
def convert_name(msg: ReciveMessage, client) -> None:
|
||||||
|
# 也是多行
|
||||||
if msg.content.find("\n") == -1:
|
if msg.content.find("\n") == -1:
|
||||||
client.send_message(
|
client.send_message(
|
||||||
msg.reply_with(
|
msg.reply_with(
|
||||||
f"请使用 {COMMAND} 命令,然后换行输入名字,例如:\n{COMMAND}\n张三\n李四\n王五\n"
|
f"请使用 {CONVERT_PREFIX} 命令,然后换行输入名字,例如:\n{CONVERT_PREFIX}\n张三\n李四\n王五\n"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
# 去掉 /name
|
# 去掉 prefix
|
||||||
names = msg.content[len(COMMAND) :]
|
names = msg.content[len(CONVERT_PREFIX) :]
|
||||||
|
# 去掉第一个 \n
|
||||||
|
names = names[names.find("\n") + 1 :]
|
||||||
|
cache = io.StringIO()
|
||||||
|
raw_players = [x for x in names.split("\n") if x != ""]
|
||||||
|
players = [name_utils.Player() for _ in raw_players]
|
||||||
|
for i, player in enumerate(players):
|
||||||
|
if not player.load(raw_players[i]):
|
||||||
|
cache.write(f"{i+1} {raw_players[i]} 无法解析\n")
|
||||||
|
raw_players[i] = ""
|
||||||
|
for i, player in enumerate(players):
|
||||||
|
if raw_players[i] == "":
|
||||||
|
continue
|
||||||
|
cache.write(player.display())
|
||||||
|
cache.write("\n")
|
||||||
|
reply = msg.reply_with(f"{cache.getvalue()}版本:{_version_}")
|
||||||
|
client.send_message(reply)
|
||||||
|
|
||||||
|
|
||||||
|
def eval_fight(msg: ReciveMessage, client) -> None:
|
||||||
|
if msg.content.find("\n") == -1:
|
||||||
|
client.send_message(
|
||||||
|
msg.reply_with(
|
||||||
|
f"请使用 {EVAL_PREFIX} 命令,然后换行输入名字,例如:\n{EVAL_PREFIX}\n张三\n李四\n王五\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
# 去掉 prefix
|
||||||
|
names = msg.content[len(EVAL_PREFIX) :]
|
||||||
# 去掉第一个 \n
|
# 去掉第一个 \n
|
||||||
names = names[names.find("\n") + 1 :]
|
names = names[names.find("\n") + 1 :]
|
||||||
|
|
||||||
|
@ -64,6 +102,18 @@ def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
|
||||||
reply = msg.reply_with(f"发生错误:{e}\n{traceback.format_exc()}")
|
reply = msg.reply_with(f"发生错误:{e}\n{traceback.format_exc()}")
|
||||||
client.send_message(reply)
|
client.send_message(reply)
|
||||||
|
|
||||||
|
def dispatch_msg(msg: ReciveMessage, client) -> None:
|
||||||
|
if msg.is_reply or msg.is_from_self:
|
||||||
|
return
|
||||||
|
if msg.content.startswith(EVAL_PREFIX):
|
||||||
|
eval_fight(msg, client)
|
||||||
|
elif msg.content.startswith(CONVERT_PREFIX):
|
||||||
|
convert_name(msg, client)
|
||||||
|
|
||||||
def on_tailchat_message(msg, client) -> None:
|
|
||||||
on_ica_message(msg, client)
|
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
|
||||||
|
dispatch_msg(msg, client) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def on_tailchat_message(msg: TailchatReciveMessage, client) -> None:
|
||||||
|
dispatch_msg(msg, client) # type: ignore
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use rust_socketio::asynchronous::Client;
|
use rust_socketio::asynchronous::Client;
|
||||||
use tracing::{event, info, warn, Level};
|
use tracing::{event, info, warn, Level};
|
||||||
|
|
||||||
use crate::data_struct::tailchat::status::BotStatus;
|
|
||||||
use crate::data_struct::{ica, tailchat};
|
use crate::data_struct::{ica, tailchat};
|
||||||
use crate::error::PyPluginError;
|
use crate::error::PyPluginError;
|
||||||
use crate::py::{class, PyPlugin, PyStatus};
|
use crate::py::{class, PyPlugin, PyStatus};
|
||||||
|
|
|
@ -79,12 +79,13 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
||||||
type Error = PyErr;
|
type Error = PyErr;
|
||||||
fn try_from(value: RawPyPlugin) -> Result<Self, Self::Error> {
|
fn try_from(value: RawPyPlugin) -> Result<Self, Self::Error> {
|
||||||
let (path, changed_time, content) = value;
|
let (path, changed_time, content) = value;
|
||||||
let py_module = py_module_from_code(&content, &path);
|
let py_module = match py_module_from_code(&content, &path) {
|
||||||
if let Err(e) = py_module {
|
Ok(module) => module,
|
||||||
|
Err(e) => {
|
||||||
warn!("加载 Python 插件: {:?} 失败", e);
|
warn!("加载 Python 插件: {:?} 失败", e);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let py_module = py_module.unwrap();
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let module = py_module.bind(py);
|
let module = py_module.bind(py);
|
||||||
if let Ok(config_func) = call::get_func(module, "on_config") {
|
if let Ok(config_func) = call::get_func(module, "on_config") {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user