Compare commits
13 Commits
2144b1e0eb
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
9265c250b3
|
|||
|
4dd9320678
|
|||
|
db96202d5d
|
|||
|
881b08c41f
|
|||
|
c11d29e136
|
|||
|
1fa74b61d6
|
|||
|
f0601acbe9
|
|||
|
39c7c043ca
|
|||
|
39accb16e0
|
|||
| ec1f9627f3 | |||
| c0590dacbc | |||
| d748e242db | |||
| e2fd0809a5 |
BIN
assets/img/meme/xiaomu.png
Executable file
BIN
assets/img/meme/xiaomu.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 242 KiB |
@ -29,10 +29,21 @@ async def _to_entity_chain(el: _EntityLike):
|
||||
|
||||
|
||||
class PermManager:
|
||||
"""
|
||||
权限管理模块
|
||||
"""
|
||||
|
||||
def __init__(self, db: DatabaseManager) -> None:
|
||||
self.db = db
|
||||
|
||||
async def get_permission_info(self, entities: _EntityLike, key: str):
|
||||
async def get_permission_info(
|
||||
self, entities: _EntityLike, key: str
|
||||
) -> tuple[PermEntity, str, bool] | None:
|
||||
"""
|
||||
获得一个权限实体或权限实体串对一个 key 的权限信息。若未入库(默认值)则
|
||||
代表没有该权限相关的记录
|
||||
"""
|
||||
|
||||
entities = await _to_entity_chain(entities)
|
||||
key = key.removesuffix("*").removesuffix(".")
|
||||
key_split = key.split(".")
|
||||
@ -52,17 +63,29 @@ class PermManager:
|
||||
return None
|
||||
|
||||
async def check_has_permission(self, entities: _EntityLike, key: str) -> bool:
|
||||
"""
|
||||
检查一个权限实体或者权限实体串是否有权限
|
||||
"""
|
||||
|
||||
res = await self.get_permission_info(entities, key)
|
||||
if res is None:
|
||||
return False
|
||||
return res[2]
|
||||
|
||||
async def update_permission(self, entity: PermEntity, key: str, perm: bool | None):
|
||||
"""
|
||||
更新一个具体的权限实体的一则权限
|
||||
"""
|
||||
|
||||
async with self.db.get_conn() as conn:
|
||||
repo = PermRepo(conn)
|
||||
await repo.update_perm_info(entity, key, perm)
|
||||
|
||||
async def list_permission(self, entities: _EntityLike, query: PagerQuery):
|
||||
"""
|
||||
列出一个权限实体或权限实体串拥有的所有权限记录
|
||||
"""
|
||||
|
||||
entities = await _to_entity_chain(entities)
|
||||
async with self.db.get_conn() as conn:
|
||||
repo = PermRepo(conn)
|
||||
@ -113,6 +136,22 @@ def register_default_allow_permission(key: str):
|
||||
|
||||
|
||||
def require_permission(perm: str) -> Rule: # pragma: no cover
|
||||
"""
|
||||
`require_permission` 是一个 Nonebot 规则,可以用来要求一个 Nonebot 的指令需
|
||||
要拥有一定的权限。
|
||||
|
||||
```python
|
||||
from konabot.common.permsys import require_permission
|
||||
from nonebot import on_command
|
||||
|
||||
cmd = on_command("kz", rule=require_permission("kagami.kz"))
|
||||
|
||||
@cmd.handle()
|
||||
async def _():
|
||||
await cmd.finish("你抓到了普通pt")
|
||||
```
|
||||
"""
|
||||
|
||||
async def check_permission(event: Event, pm: DepPermManager) -> bool:
|
||||
return await pm.check_has_permission(event, perm)
|
||||
|
||||
|
||||
@ -22,6 +22,11 @@ class PermEntity:
|
||||
|
||||
|
||||
def get_entity_chain_of_entity(entity: PermEntity) -> list[PermEntity]:
|
||||
"""
|
||||
获得一个权限实体的权限串。实际上返回三个权限,从小到大分别是用户、平台全体和
|
||||
系统全局的权限实体。
|
||||
"""
|
||||
|
||||
return [
|
||||
PermEntity("sys", "global", "global"),
|
||||
PermEntity(entity.platform, "global", "global"),
|
||||
@ -30,6 +35,10 @@ def get_entity_chain_of_entity(entity: PermEntity) -> list[PermEntity]:
|
||||
|
||||
|
||||
async def get_entity_chain(event: Event) -> list[PermEntity]: # pragma: no cover
|
||||
"""
|
||||
获得一个 Nonebot Event 的权限实体串。
|
||||
"""
|
||||
|
||||
entities = [PermEntity("sys", "global", "global")]
|
||||
|
||||
if isinstance(event, OB11Event):
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
# 关于罗文和洛温
|
||||
|
||||
AdoreLowen 希望和洛温阿特金森区分,所以最好就不要叫他洛温了!此方 BOT 会在一些群提醒叫错了的人。
|
||||
@ -1,16 +1,16 @@
|
||||
# 指令介绍
|
||||
简易 Raymarch 小玩具
|
||||
用法:march `<scene>`
|
||||
用法:march `[scene]`
|
||||
例:march torus(1.0, 0.2).color(1.0, 0.2, 0.2) torus(1.0, 0.2).rot(90, 0, 0).color(0.2, 0.2, 1.0) camera(4.0).pos(4, 0, 0).lookat(0)
|
||||
|
||||
# 主要语法
|
||||
`<scene>` ::= `<scene>` "." `<op>` |`<obj>`
|
||||
`[scene]` ::= `[scene]` "." `[op]` |`[obj]`
|
||||
|
||||
`<obj>` ::= `<obj_ty>` | `<obj_ty>` "(" <args> ")"
|
||||
`[obj]` ::= `[obj_ty]` | `[obj_ty]` "(" [args] ")"
|
||||
|
||||
`<op>` ::= `<op_ty>` | `<op_ty>` "(" `<args>` ")"
|
||||
`[op]` ::= `[op_ty]` | `[op_ty]` "(" `[args]` ")"
|
||||
|
||||
`<args>` ::= `<args>` "," `<arg>` | `<arg>`
|
||||
`[args]` ::= `[args]` "," `[arg]` | `[arg]`
|
||||
|
||||
其中 `obj_ty`、`op_ty` 分别为物体类型(如 `cube`、`sphere`、`torus` 等)与变换类型(如 `pos`、`rot`)。
|
||||
|
||||
@ -37,4 +37,4 @@
|
||||
`rounded`:圆角
|
||||
|
||||
# 特殊说明
|
||||
`<op_ty>` 不包含 scale。非正交的变换会破坏 SDF 的性质。
|
||||
`[op_ty]` 不包含 scale。非正交的变换会破坏 SDF 的性质。
|
||||
8
konabot/docs/user/此方晚安.txt
Normal file
8
konabot/docs/user/此方晚安.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# 指令介绍
|
||||
|
||||
**此方晚安** - 让此方 BOT 禁言你一段时间
|
||||
|
||||
## 指令格式
|
||||
|
||||
- `@此方BOT 此方晚安`: 禁言几个小时
|
||||
- `@此方BOT 此方午安`: 禁言几十分钟
|
||||
44
konabot/plugins/guihuasay.py
Normal file
44
konabot/plugins/guihuasay.py
Normal file
@ -0,0 +1,44 @@
|
||||
import re
|
||||
from typing import Any
|
||||
from nonebot import on_message
|
||||
from nonebot.adapters import Event
|
||||
from nonebot_plugin_alconna import UniMessage, UniMsg
|
||||
from playwright.async_api import Page
|
||||
|
||||
from konabot.common.nb import match_keyword
|
||||
from konabot.common.web_render import WebRenderer, konaweb
|
||||
|
||||
|
||||
async def render_image(message: str) -> UniMessage[Any]:
|
||||
"""
|
||||
渲染文本为图片
|
||||
"""
|
||||
|
||||
async def page_function(page: Page):
|
||||
await page.wait_for_function("typeof setContent === 'function'")
|
||||
await page.evaluate(
|
||||
"([ message ]) => { return setContent(message); }",
|
||||
[ message ],
|
||||
)
|
||||
|
||||
img_data = await WebRenderer.render(
|
||||
url=konaweb("guihuasay"),
|
||||
target="#main",
|
||||
other_function=page_function,
|
||||
)
|
||||
return UniMessage.image(raw=img_data)
|
||||
|
||||
|
||||
cmd = on_message(
|
||||
rule=match_keyword.match_keyword(
|
||||
re.compile(r"^(桂花[说想])\s.+", re.I),
|
||||
),
|
||||
)
|
||||
|
||||
@cmd.handle()
|
||||
async def _(event: Event, msg: UniMsg):
|
||||
text = msg.extract_plain_text().lstrip()
|
||||
_, content = text.split(maxsplit=1)
|
||||
msg = await render_image(content)
|
||||
await msg.send(event)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
const float EPS = 0.001;
|
||||
const int MAX_ITER = 128;
|
||||
const float INF = 1e10;
|
||||
const float PI = 3.14159;
|
||||
|
||||
uniform vec2 u_resolution;
|
||||
out vec4 fragColor;
|
||||
@ -68,17 +69,76 @@ vec3 nrm(vec3 p) {
|
||||
));
|
||||
}
|
||||
|
||||
float saturate(float x) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float ggx_distribution(vec3 n, vec3 h, float roughness) {
|
||||
float alpha = roughness * roughness;
|
||||
float alpha2 = alpha * alpha;
|
||||
float NdotH = saturate(dot(n, h));
|
||||
float denom = NdotH * NdotH * (alpha2 - 1.0) + 1.0;
|
||||
return alpha2 / max(PI * denom * denom, EPS);
|
||||
}
|
||||
|
||||
float geometry_schlick_ggx(float NdotX, float roughness) {
|
||||
float r = roughness + 1.0;
|
||||
float k = r * r / 8.0;
|
||||
return NdotX / max(NdotX * (1.0 - k) + k, EPS);
|
||||
}
|
||||
|
||||
float geometry_smith(vec3 n, vec3 v, vec3 l, float roughness) {
|
||||
float NdotV = saturate(dot(n, v));
|
||||
float NdotL = saturate(dot(n, l));
|
||||
return geometry_schlick_ggx(NdotV, roughness) * geometry_schlick_ggx(NdotL, roughness);
|
||||
}
|
||||
|
||||
vec3 fresnel_schlick(vec3 f0, float cos_theta) {
|
||||
return f0 + (1.0 - f0) * pow(1.0 - saturate(cos_theta), 5.0);
|
||||
}
|
||||
|
||||
vec3 tonemap_aces(vec3 c) {
|
||||
const float a = 2.51;
|
||||
const float b = 0.03;
|
||||
const float c1 = 2.43;
|
||||
const float d = 0.59;
|
||||
const float e = 0.14;
|
||||
return clamp((c * (a * c + b)) / (c * (c1 * c + d) + e), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 materialColor(int obj_id) {
|
||||
<COLOR_BLOCK>
|
||||
return vec4(1.0);
|
||||
}
|
||||
|
||||
vec4 color(vec3 p, int obj_id) {
|
||||
vec3 normal = nrm(p);
|
||||
vec3 light_dir = normalize(vec3(0.5, 0.8, -0.6));
|
||||
float light = 0.2 + 0.8 * max(dot(normal, light_dir), 0.0);
|
||||
vec4 base = materialColor(obj_id);
|
||||
return vec4(base.rgb * light, base.a);
|
||||
vec4 color(vec3 p, vec3 r, int obj_id) {
|
||||
vec3 light_col = vec3(1.0);
|
||||
vec4 albedo = materialColor(obj_id);
|
||||
vec3 N = nrm(p);
|
||||
vec3 V = normalize(-r);
|
||||
vec3 L = normalize(vec3(0.5, 0.8, -0.6));
|
||||
vec3 H = normalize(V + L);
|
||||
float roughness = 0.45;
|
||||
float metallic = 0.02;
|
||||
float NdotL = saturate(dot(N, L));
|
||||
float NdotV = saturate(dot(N, V));
|
||||
float D = ggx_distribution(N, H, roughness);
|
||||
float G = geometry_smith(N, V, L, roughness);
|
||||
vec3 F0 = mix(vec3(0.04), albedo.rgb, metallic);
|
||||
vec3 F = fresnel_schlick(F0, dot(V, H));
|
||||
vec3 kD = (1.0 - F) * (1.0 - metallic);
|
||||
vec3 diffuse = kD * albedo.rgb / PI;
|
||||
vec3 specular = D * G * F / max(4.0 * NdotL * NdotV, EPS);
|
||||
|
||||
float hemi = N.y * 0.5 + 0.5;
|
||||
vec3 sky_ambient = vec3(0.60, 0.72, 0.92);
|
||||
vec3 ground_ambient = vec3(0.18, 0.16, 0.14);
|
||||
vec3 ambient = mix(ground_ambient, sky_ambient, hemi) * (diffuse + 0.25 * F0) * 0.35;
|
||||
|
||||
vec3 col = ambient + (diffuse + specular) * light_col * NdotL;
|
||||
col = tonemap_aces(col);
|
||||
col = pow(col, vec3(1.0 / 2.2));
|
||||
return vec4(col, 1.0);
|
||||
}
|
||||
|
||||
vec4 march(vec3 p, vec3 r) {
|
||||
@ -87,7 +147,7 @@ vec4 march(vec3 p, vec3 r) {
|
||||
for(int i = 0; i < MAX_ITER; ++i) {
|
||||
qry = sd(p);
|
||||
if(qry.value < EPS){
|
||||
col = color(p, qry.obj_id);
|
||||
col = color(p, r, qry.obj_id);
|
||||
break;
|
||||
}
|
||||
p += qry.value * r;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
from io import BytesIO
|
||||
from typing import Iterable, cast
|
||||
|
||||
import PIL.Image
|
||||
|
||||
from loguru import logger
|
||||
from nonebot import on_message
|
||||
from nonebot_plugin_alconna import (
|
||||
@ -18,7 +20,7 @@ from nonebot_plugin_alconna import (
|
||||
from playwright.async_api import ConsoleMessage, Page
|
||||
|
||||
from konabot.common.nb.match_keyword import match_keyword
|
||||
from konabot.common.nb.extract_image import DepPILImage
|
||||
from konabot.common.nb.extract_image import DepImageBytesOrNone, DepPILImage
|
||||
from konabot.common.web_render import konaweb
|
||||
from konabot.common.web_render.core import WebRenderer
|
||||
from konabot.common.web_render.host_images import host_tempdir
|
||||
@ -35,6 +37,7 @@ from konabot.plugins.memepack.drawing.saying import (
|
||||
draw_pt,
|
||||
draw_suan,
|
||||
draw_vr,
|
||||
draw_xm
|
||||
)
|
||||
from konabot.plugins.memepack.drawing.watermark import draw_doubao_watermark
|
||||
|
||||
@ -361,3 +364,33 @@ async def _(saying: list[str]):
|
||||
|
||||
await vrsay.send(await UniMessage().image(raw=img_bytes).export())
|
||||
|
||||
|
||||
xmsay = on_alconna(
|
||||
Alconna(
|
||||
"小睦说",
|
||||
Args[
|
||||
"saying",
|
||||
MultiVar(str, "*"),
|
||||
Field(missing_tips=lambda: "你没有写小睦说了什么"),
|
||||
],
|
||||
Args["image?", Image | None],
|
||||
),
|
||||
use_cmd_start=True,
|
||||
use_cmd_sep=False,
|
||||
skip_for_unmatch=False,
|
||||
aliases={"小睦想"},
|
||||
)
|
||||
|
||||
|
||||
@xmsay.handle()
|
||||
async def _(saying: list[str], image: DepImageBytesOrNone):
|
||||
if image is not None:
|
||||
img = PIL.Image.open(BytesIO(image))
|
||||
else:
|
||||
img = None
|
||||
img = await draw_xm("\n".join(saying), img)
|
||||
img_bytes = BytesIO()
|
||||
img.save(img_bytes, format="PNG")
|
||||
|
||||
await xmsay.send(await UniMessage().image(raw=img_bytes).export())
|
||||
|
||||
|
||||
@ -7,23 +7,41 @@ import PIL.Image
|
||||
from konabot.common.path import ASSETS_PATH
|
||||
from konabot.common.utils.to_async import make_async
|
||||
|
||||
from .base.fonts import HARMONYOS_SANS_SC_BLACK, HARMONYOS_SANS_SC_REGULAR, LXGWWENKAI_REGULAR
|
||||
from .base.fonts import (
|
||||
HARMONYOS_SANS_SC_BLACK,
|
||||
HARMONYOS_SANS_SC_REGULAR,
|
||||
LXGWWENKAI_REGULAR,
|
||||
)
|
||||
|
||||
geimao_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "geimao.jpg").convert("RGBA")
|
||||
geimao_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "geimao.jpg").convert(
|
||||
"RGBA"
|
||||
)
|
||||
pt_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "ptsay.png").convert("RGBA")
|
||||
mnk_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "mnksay.jpg").convert("RGBA")
|
||||
dasuan_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "dss.png").convert("RGBA")
|
||||
suan_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "suanleba.png").convert("RGBA")
|
||||
cute_ten_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "tententen.png").convert("RGBA")
|
||||
suan_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "suanleba.png").convert(
|
||||
"RGBA"
|
||||
)
|
||||
cute_ten_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "tententen.png").convert(
|
||||
"RGBA"
|
||||
)
|
||||
kio_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "kiosay.jpg").convert("RGBA")
|
||||
vr_image = PIL.Image.open(ASSETS_PATH / 'img' / 'meme' / 'vr.jpg').convert("RGBA")
|
||||
vr_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "vr.jpg").convert("RGBA")
|
||||
xm_image = PIL.Image.open(ASSETS_PATH / "img" / "meme" / "xiaomu.png").convert("RGBA")
|
||||
|
||||
|
||||
def _draw_geimao(saying: str):
|
||||
img = geimao_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 960, 50, 0.5, 0, 1920, 240, HARMONYOS_SANS_SC_BLACK,
|
||||
saying,
|
||||
960,
|
||||
50,
|
||||
0.5,
|
||||
0,
|
||||
1920,
|
||||
240,
|
||||
HARMONYOS_SANS_SC_BLACK,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
0.8,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -42,7 +60,14 @@ def _draw_pt(saying: str):
|
||||
img = pt_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 259, 278, 0.5, 0.5, 360, 48, HARMONYOS_SANS_SC_REGULAR,
|
||||
saying,
|
||||
259,
|
||||
278,
|
||||
0.5,
|
||||
0.5,
|
||||
360,
|
||||
48,
|
||||
HARMONYOS_SANS_SC_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -59,7 +84,14 @@ def _draw_mnk(saying: str):
|
||||
img = mnk_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 540, 25, 0.5, 0, 1080, 120, HARMONYOS_SANS_SC_BLACK,
|
||||
saying,
|
||||
540,
|
||||
25,
|
||||
0.5,
|
||||
0,
|
||||
1080,
|
||||
120,
|
||||
HARMONYOS_SANS_SC_BLACK,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
0.8,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -81,7 +113,14 @@ def _draw_suan(saying: str, dasuan: bool = False):
|
||||
img = suan_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 1020, 290, 0.5, 0.5, 400, 48, LXGWWENKAI_REGULAR,
|
||||
saying,
|
||||
1020,
|
||||
290,
|
||||
0.5,
|
||||
0.5,
|
||||
400,
|
||||
48,
|
||||
LXGWWENKAI_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -98,7 +137,14 @@ def _draw_cute_ten(saying: str):
|
||||
img = cute_ten_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 390, 479, 0.5, 0.5, 760, 96, LXGWWENKAI_REGULAR,
|
||||
saying,
|
||||
390,
|
||||
479,
|
||||
0.5,
|
||||
0.5,
|
||||
760,
|
||||
96,
|
||||
LXGWWENKAI_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -116,7 +162,14 @@ def draw_kiosay(saying: str):
|
||||
img = kio_image.copy()
|
||||
with imagetext_py.Writer(img) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, 450, 540, 0.5, 0.5, 900, 96, LXGWWENKAI_REGULAR,
|
||||
saying,
|
||||
450,
|
||||
540,
|
||||
0.5,
|
||||
0.5,
|
||||
900,
|
||||
96,
|
||||
LXGWWENKAI_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -131,12 +184,19 @@ def draw_vr(saying: str):
|
||||
w, h = img.size
|
||||
hw = 300
|
||||
|
||||
img2 = PIL.Image.new("RGBA", (w, h + hw), 'white')
|
||||
img2 = PIL.Image.new("RGBA", (w, h + hw), "white")
|
||||
img2.paste(img, (0, hw))
|
||||
|
||||
with imagetext_py.Writer(img2) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying, w // 2, hw // 2 + 15, 0.5, 0.5, w, 64, LXGWWENKAI_REGULAR,
|
||||
saying,
|
||||
w // 2,
|
||||
hw // 2 + 15,
|
||||
0.5,
|
||||
0.5,
|
||||
w,
|
||||
64,
|
||||
LXGWWENKAI_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
@ -145,3 +205,36 @@ def draw_vr(saying: str):
|
||||
|
||||
return img2
|
||||
|
||||
|
||||
@make_async
|
||||
def draw_xm(saying: str, image: PIL.Image.Image | None = None):
|
||||
img_base = PIL.Image.new("RGBA", xm_image.size, (255, 255, 255, 255))
|
||||
with imagetext_py.Writer(img_base) as iw:
|
||||
iw.draw_text_wrapped(
|
||||
saying,
|
||||
442,
|
||||
200,
|
||||
0.5,
|
||||
0.5,
|
||||
884,
|
||||
64,
|
||||
LXGWWENKAI_REGULAR,
|
||||
imagetext_py.Paint.Color(imagetext_py.Color.from_hex("000000FF")),
|
||||
1.0,
|
||||
imagetext_py.TextAlign.Center,
|
||||
draw_emojis=True,
|
||||
)
|
||||
if image is not None:
|
||||
image_r = image.copy().convert("RGBA")
|
||||
|
||||
width, height = image_r.size
|
||||
base_width = img_base.size[0]
|
||||
height = int(height / width * base_width)
|
||||
image_r = image_r.resize((base_width, height))
|
||||
|
||||
# try to align center
|
||||
y = 215 - image_r.height // 2
|
||||
img_base.paste(image_r, (0, y), mask=image_r)
|
||||
img_base.paste(xm_image, (0, 0), mask=xm_image)
|
||||
return img_base
|
||||
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
import nonebot
|
||||
|
||||
from nonebot.adapters.onebot.v11.bot import Bot
|
||||
from nonebot.adapters.onebot.v11.event import GroupMessageEvent
|
||||
from nonebot_plugin_alconna import UniMsg, UniMessage
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class NoLuowenConfig(BaseModel):
|
||||
plugin_noluowen_qqid: int = -1
|
||||
plugin_noluowen_enable_group: list[int] = []
|
||||
|
||||
config = nonebot.get_plugin_config(NoLuowenConfig)
|
||||
|
||||
|
||||
async def is_luowen_mentioned(evt: GroupMessageEvent, msg: UniMsg) -> bool:
|
||||
if config.plugin_noluowen_qqid <= 0:
|
||||
return False
|
||||
if evt.user_id == config.plugin_noluowen_qqid:
|
||||
return False
|
||||
if evt.group_id not in config.plugin_noluowen_enable_group:
|
||||
return False
|
||||
txt = msg.extract_plain_text()
|
||||
if "洛温" not in txt:
|
||||
return False
|
||||
if "罗文" in txt:
|
||||
return False
|
||||
if "阿特金森" in txt:
|
||||
return False
|
||||
return True
|
||||
|
||||
evt_luowen_mentioned = nonebot.on_message(rule=is_luowen_mentioned)
|
||||
|
||||
|
||||
@evt_luowen_mentioned.handle()
|
||||
async def _(evt: GroupMessageEvent, bot: Bot):
|
||||
msg = (
|
||||
UniMessage()
|
||||
.reply(str(evt.message_id))
|
||||
.at(str(config.plugin_noluowen_qqid))
|
||||
.text(" 好像有人念错了你的 ID")
|
||||
)
|
||||
await evt_luowen_mentioned.send(await msg.export(bot=bot))
|
||||
|
||||
64
konabot/plugins/oyasumi/__init__.py
Normal file
64
konabot/plugins/oyasumi/__init__.py
Normal file
@ -0,0 +1,64 @@
|
||||
import random
|
||||
from nonebot import on_command
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
|
||||
from nonebot.rule import to_me
|
||||
from nonebot_plugin_alconna import UniMessage
|
||||
from konabot.common.permsys import require_permission
|
||||
|
||||
|
||||
async def make_sleep(event: GroupMessageEvent, bot: Bot, duration: int):
|
||||
"""
|
||||
让人睡着
|
||||
"""
|
||||
|
||||
await bot.set_group_ban(
|
||||
group_id=event.group_id,
|
||||
user_id=event.user_id,
|
||||
duration=duration,
|
||||
)
|
||||
|
||||
seconds = duration % 60
|
||||
minutes = (duration // 60) % 60
|
||||
hours = duration // 3600
|
||||
|
||||
t1 = f"{hours} 小时 {minutes} 分钟 {seconds} 秒"
|
||||
|
||||
message = f" 好好睡吧!奖励你 {t1}的睡眠💤"
|
||||
message = UniMessage.at(str(event.user_id)).text(message)
|
||||
|
||||
await message.send(target=event, bot=bot)
|
||||
|
||||
|
||||
cmd_sleep_night = on_command(
|
||||
"此方晚安",
|
||||
rule=require_permission("oyasumi") & to_me(),
|
||||
aliases={"晚安"},
|
||||
)
|
||||
|
||||
|
||||
@cmd_sleep_night.handle()
|
||||
async def oyasumi(event: GroupMessageEvent, bot: Bot):
|
||||
"""
|
||||
限定只能用 GroupMessageEvent,因为它只能在 QQ 群中使用
|
||||
"""
|
||||
|
||||
# 考虑到有人是熬夜很久,所以这里就给一个 3 到 5 小时睡眠的随机数。这个时间内
|
||||
# 要睡不着我觉得是个小概率事件了!
|
||||
|
||||
duration = random.randint(3 * 3600, 5 * 3600)
|
||||
await make_sleep(event, bot, duration)
|
||||
await cmd_sleep_night.finish()
|
||||
|
||||
|
||||
cmd_sleep_noon = on_command(
|
||||
"此方午安",
|
||||
rule=require_permission("oyasumi") & to_me(),
|
||||
aliases={"午安"},
|
||||
)
|
||||
|
||||
|
||||
@cmd_sleep_noon.handle()
|
||||
async def sleep_noon(event: GroupMessageEvent, bot: Bot):
|
||||
duration = random.randint(60 * 15, 60 * 30)
|
||||
await make_sleep(event, bot, duration)
|
||||
await cmd_sleep_night.finish()
|
||||
1431
poetry.lock
generated
1431
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user