Compare commits
9 Commits
fix/databa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
39c7c043ca
|
|||
|
39accb16e0
|
|||
| ec1f9627f3 | |||
| c0590dacbc | |||
| d748e242db | |||
| e2fd0809a5 | |||
|
2144b1e0eb
|
|||
|
7d0d53bead
|
|||
| 4bfcc9b41c |
@ -5,6 +5,8 @@ ENV VIRTUAL_ENV=/app/.venv \
|
|||||||
PLAYWRIGHT_BROWSERS_PATH=/usr/lib/pw-browsers
|
PLAYWRIGHT_BROWSERS_PATH=/usr/lib/pw-browsers
|
||||||
|
|
||||||
# 安装所有都需要的底层依赖
|
# 安装所有都需要的底层依赖
|
||||||
|
#
|
||||||
|
# xz-utils: 解压需要它
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
libfontconfig1 libgl1 libegl1 libglvnd0 mesa-vulkan-drivers at-spi2-common fontconfig \
|
libfontconfig1 libgl1 libegl1 libglvnd0 mesa-vulkan-drivers at-spi2-common fontconfig \
|
||||||
@ -16,6 +18,7 @@ RUN apt-get update && \
|
|||||||
libatk-bridge2.0-0t64 libatspi2.0-0t64 libxcomposite1 libxdamage1 libxfixes3 \
|
libatk-bridge2.0-0t64 libatspi2.0-0t64 libxcomposite1 libxdamage1 libxfixes3 \
|
||||||
libxkbcommon0 libasound2t64 libnss3 fonts-noto-cjk fonts-noto-cjk-extra \
|
libxkbcommon0 libasound2t64 libnss3 fonts-noto-cjk fonts-noto-cjk-extra \
|
||||||
fonts-noto-color-emoji \
|
fonts-noto-color-emoji \
|
||||||
|
xz-utils \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,14 @@ class ArtifactDepends:
|
|||||||
tasks = set()
|
tasks = set()
|
||||||
for f in self.callbacks:
|
for f in self.callbacks:
|
||||||
tasks.add(f(downloaded))
|
tasks.add(f(downloaded))
|
||||||
return await asyncio.gather(*tasks, return_exceptions=True)
|
result = await asyncio.gather(*tasks, return_exceptions=True)
|
||||||
|
|
||||||
|
for r in result:
|
||||||
|
if isinstance(r, BaseException):
|
||||||
|
logger.warning("完成了二进制文件的下载,但是有未捕捉的错误")
|
||||||
|
logger.exception(r)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
@ -73,12 +80,7 @@ async def _():
|
|||||||
|
|
||||||
async def _task(artifact: ArtifactDepends):
|
async def _task(artifact: ArtifactDepends):
|
||||||
async with semaphore:
|
async with semaphore:
|
||||||
downloaded = await ensure_artifact(artifact)
|
await ensure_artifact(artifact)
|
||||||
result = await artifact._finished(downloaded)
|
|
||||||
for r in result:
|
|
||||||
if isinstance(r, BaseException):
|
|
||||||
logger.warning("完成了二进制文件的下载,但是有未捕捉的错误")
|
|
||||||
logger.exception(r)
|
|
||||||
|
|
||||||
tasks: set[asyncio.Task] = set()
|
tasks: set[asyncio.Task] = set()
|
||||||
for a in artifact_list:
|
for a in artifact_list:
|
||||||
@ -116,9 +118,16 @@ async def download_artifact(artifact: ArtifactDepends):
|
|||||||
f"下载到的二进制的 sha256 与需求不同 TARGET={artifact.target} REQUESTED={artifact.sha256} ACTUAL={m.hexdigest()}"
|
f"下载到的二进制的 sha256 与需求不同 TARGET={artifact.target} REQUESTED={artifact.sha256} ACTUAL={m.hexdigest()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await artifact._finished(True)
|
||||||
|
|
||||||
|
|
||||||
async def ensure_artifact(artifact: ArtifactDepends) -> bool:
|
async def ensure_artifact(artifact: ArtifactDepends) -> bool:
|
||||||
|
"""
|
||||||
|
确保所需的二进制存在。返回是否下载了这个二进制文件。
|
||||||
|
"""
|
||||||
|
|
||||||
if not artifact.is_corresponding_platform():
|
if not artifact.is_corresponding_platform():
|
||||||
|
logger.debug(f"所需求的平台不是当前平台,跳过二进制下载 artifact={artifact}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not artifact.target.exists():
|
if not artifact.target.exists():
|
||||||
@ -136,6 +145,7 @@ async def ensure_artifact(artifact: ArtifactDepends) -> bool:
|
|||||||
artifact.target.unlink()
|
artifact.target.unlink()
|
||||||
await download_artifact(artifact)
|
await download_artifact(artifact)
|
||||||
return True
|
return True
|
||||||
|
await artifact._finished(False)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
# 指令介绍
|
# 指令介绍
|
||||||
简易 Raymarch 小玩具
|
简易 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)
|
例: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`)。
|
其中 `obj_ty`、`op_ty` 分别为物体类型(如 `cube`、`sphere`、`torus` 等)与变换类型(如 `pos`、`rot`)。
|
||||||
|
|
||||||
@ -37,4 +37,4 @@
|
|||||||
`rounded`:圆角
|
`rounded`:圆角
|
||||||
|
|
||||||
# 特殊说明
|
# 特殊说明
|
||||||
`<op_ty>` 不包含 scale。非正交的变换会破坏 SDF 的性质。
|
`[op_ty]` 不包含 scale。非正交的变换会破坏 SDF 的性质。
|
||||||
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 float EPS = 0.001;
|
||||||
const int MAX_ITER = 128;
|
const int MAX_ITER = 128;
|
||||||
const float INF = 1e10;
|
const float INF = 1e10;
|
||||||
|
const float PI = 3.14159;
|
||||||
|
|
||||||
uniform vec2 u_resolution;
|
uniform vec2 u_resolution;
|
||||||
out vec4 fragColor;
|
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) {
|
vec4 materialColor(int obj_id) {
|
||||||
<COLOR_BLOCK>
|
<COLOR_BLOCK>
|
||||||
return vec4(1.0);
|
return vec4(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 color(vec3 p, int obj_id) {
|
vec4 color(vec3 p, vec3 r, int obj_id) {
|
||||||
vec3 normal = nrm(p);
|
vec3 light_col = vec3(1.0);
|
||||||
vec3 light_dir = normalize(vec3(0.5, 0.8, -0.6));
|
vec4 albedo = materialColor(obj_id);
|
||||||
float light = 0.2 + 0.8 * max(dot(normal, light_dir), 0.0);
|
vec3 N = nrm(p);
|
||||||
vec4 base = materialColor(obj_id);
|
vec3 V = normalize(-r);
|
||||||
return vec4(base.rgb * light, base.a);
|
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) {
|
vec4 march(vec3 p, vec3 r) {
|
||||||
@ -87,7 +147,7 @@ vec4 march(vec3 p, vec3 r) {
|
|||||||
for(int i = 0; i < MAX_ITER; ++i) {
|
for(int i = 0; i < MAX_ITER; ++i) {
|
||||||
qry = sd(p);
|
qry = sd(p);
|
||||||
if(qry.value < EPS){
|
if(qry.value < EPS){
|
||||||
col = color(p, qry.obj_id);
|
col = color(p, r, qry.obj_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p += qry.value * r;
|
p += qry.value * r;
|
||||||
|
|||||||
@ -41,6 +41,7 @@ bin_path: Path | None = None
|
|||||||
|
|
||||||
@arti_typst_linux.on_finished
|
@arti_typst_linux.on_finished
|
||||||
async def _(downloaded: bool):
|
async def _(downloaded: bool):
|
||||||
|
logger.debug("安装好了 Linux 版本的 Typst")
|
||||||
global bin_path
|
global bin_path
|
||||||
|
|
||||||
tar_path = arti_typst_linux.target
|
tar_path = arti_typst_linux.target
|
||||||
@ -71,6 +72,7 @@ async def _(downloaded: bool):
|
|||||||
|
|
||||||
@arti_typst_windows.on_finished
|
@arti_typst_windows.on_finished
|
||||||
async def _(downloaded: bool):
|
async def _(downloaded: bool):
|
||||||
|
logger.debug("安装好了 Windows 版本的 Typst")
|
||||||
global bin_path
|
global bin_path
|
||||||
zip_path = arti_typst_windows.target
|
zip_path = arti_typst_windows.target
|
||||||
bin_path = BINARY_PATH / "typst.exe"
|
bin_path = BINARY_PATH / "typst.exe"
|
||||||
@ -160,6 +162,7 @@ async def _(
|
|||||||
# 对于本地机器,一般不会在应用启动时自动下载,这里再保证存在
|
# 对于本地机器,一般不会在应用启动时自动下载,这里再保证存在
|
||||||
await ensure_artifact(arti_typst_linux)
|
await ensure_artifact(arti_typst_linux)
|
||||||
await ensure_artifact(arti_typst_windows)
|
await ensure_artifact(arti_typst_windows)
|
||||||
|
|
||||||
if bin_path is None or not bin_path.exists():
|
if bin_path is None or not bin_path.exists():
|
||||||
logger.warning("当前环境不存在 Typst,但仍然调用了")
|
logger.warning("当前环境不存在 Typst,但仍然调用了")
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user