LINUX SB 快照站

Se7en

用户 ID 7 · 当前名首次快照 2026-08-18 17:39:04 · 当前名始于 2026-08-18 17:39:04 · 原站主页: https://linux.sb/user/7

发言

共 38 楼

得不到就毁掉
#45 · Se7en
发帖 2026-08-19 00:03:21 · 快照 2026-08-19 00:03:58

@何青泉 #43 那不行 毁了我怎么办

【蛋云开业大促】全场7折 98/年+附赠免费换IP,回帖抽10台香港大带宽VPS
#216 · Se7en
发帖 2026-08-19 00:01:36 · 快照 2026-08-19 00:01:39

可惜了 看到晚了

关于头像精华
#23 · Se7en
发帖 2026-08-18 23:45:25 · 快照 2026-08-18 23:45:47

@altzin #22 尝试了一小时 没搞定… 没gpt用 其他太笨

得不到就毁掉
#37 · Se7en
发帖 2026-08-18 23:28:02 · 快照 2026-08-18 23:29:12

这里好热闹~

论坛系统问题
#3 · Se7en
发帖 2026-08-18 22:27:39 · 快照 2026-08-18 22:59:28

@豆包本包 #2 本包 没token了 早就没token了

为什么今天的supergrok 蠢的像豆包
#2 · Se7en
发帖 2026-08-18 22:26:40 · 快照 2026-08-18 22:59:27

我感觉我错过了好多 gemini的订阅 grok的bug。手头啥也没了

一个老用户的使用感受——最近逛论坛的一些观察精华
#9 · Se7en
发帖 2026-08-18 22:19:42 · 快照 2026-08-18 22:59:02

@INS美图 #8 我没看懂 你在说什么?

一个老用户的使用感受——最近逛论坛的一些观察精华
#4 · Se7en
发帖 2026-08-18 21:49:15 · 快照 2026-08-18 21:51:36

@痛失姓名的站长
咱们这里什么时候能够出来这种帖子就好了
https://linux.do/t/topic/2772759
https://linux.do/t/topic/2772701

随便首页找的,随便举举例子

linuxdo虽然neo我很讨厌,但是整个论坛的人流量、质量还是要肯定的(被ban了,现在只能看不能说话)

说难听点,这是个长期过程,第一步我觉得站长要想的是如何让linuxdo的人打开do的同时也会打开sb,然后再想如何让他们打开sb不打开do了。现在的人流量就造成了随机性上的无法出现很多引人留存的帖子

最后由 Se7en 编辑于 2026-08-18 21:49
bbs1org设计好玄妙精华
#4 · Se7en
发帖 2026-08-18 21:45:04 · 快照 2026-08-18 21:45:14

@痛失姓名的站长 #3 没仔细对比过,但我感觉站真做大了的话,bbs1org能不能顶住啊。还有,他轻量化是轻量化,真像论坛里说的一样,插件越打越多,然后呢...
而且所有东西都得靠插件自己搭,从易上手性上的确较discourse差挺远

置顶发布真实经验教程 获取积分投币 以及创作者身份
#63 · Se7en
发帖 2026-08-18 21:36:04 · 快照 2026-08-18 21:36:23

@痛失姓名的站长 站长大大,给个创作者

一个老用户的使用感受——最近逛论坛的一些观察精华
#0 · Se7en
发帖 2026-08-18 21:35:14 · 快照 2026-08-18 21:36:29

最近几天常来论坛逛逛,作为一个在这里待了一段时间的用户,想跟站长聊聊一些真实的感受,纯属个人观察,如有不准确的地方还请多包涵。

记得刚注册那会儿,感觉论坛人气挺旺的,每天都有不少新面孔加入。但时间一长,我发现一个有点奇怪的现象:注册人数一直在涨,可实际能参与讨论的帖子似乎并没有同比例增长。有时候点开一些热门板块,发帖的人换了一批又一批,但真正有价值的交流却总觉得隔了一层。新用户来了,好像更多是"到此一游",鲜少留下来深入参与。

另外这段时间,论坛里AI生成的内容似乎变多了。不是说AI内容不好,但当满屏都是高度雷同的AI回答、AI总结、AI"水文"的时候,难免让人有点审美疲劳。很多时候点开一个帖子,前几楼都是AI套话,真正有个人经验、有实操价值的分享反而被淹没了。刷帖刷久了,确实会有点"信息过载但营养不足"的感觉。

还有就是内容沉淀的问题。翻看一些技术板块,会发现不少帖子质量很高,但后续讨论的热度持续不久;而另一方面,一些高质量的讨论串又很难被系统性地整理和沉淀。久而久之,论坛给人的感觉是"热闹有余,留存不足"——新内容层出不穷,但能让人反复回看、反复回味的"镇版之宝"似乎少了些。

说实话,挺喜欢这个论坛的,也真心希望它能越来越好。以上只是我作为一个普通用户的一点观察,不一定全面,供站长参考。

bbs1org设计好玄妙精华
#0 · Se7en
发帖 2026-08-18 21:27:02 · 快照 2026-08-18 21:31:24

从入站我就一直很好奇,一个这么轻量的bbs,怎么能支持那么强的插件系统,几乎无所不能。
今天让AI给我做了个分析(没接触过php,不太懂),感觉大抵和前端SPA有点像嘛,插件、hook。

看了源码,我觉得可以把 bbs1org 的架构总结成这张图:

index.php
 ├── 启动常量和 autoloader
 ├── 核心路由表 core_routes()
 │    ├── home → home_page()
 │    ├── forum → forum_page()
 │    ├── topic → topic_page()
 │    ├── admin → admin_route()
 │    ├── cron → Cron::cron_route()
 │    └── plugin_market_* → Plugin::*
 ├── 插件路由 plugin_route($action)
 │    └── 扫描 app/plugins/*/plugin.php 的 manifest['routes']
 ├── Hook 系统
 │    ├── hook_registry()  → 聚合所有 enabled 插件的 hooks
 │    ├── hook($name, $value, $ctx) → 链式调用,可改值
 │    └── fire($name, $ctx) → 无返回值,纯事件
 ├── 插件管理
 │    ├── 同步: Plugin::plugin_registry_sync()
 │    ├── 启用/停用
 │    ├── 资源打包: plugins.css + plugins.js
 │    └── 市场: 远程拉取、安装、分享
 └── 兜底 404

它是怎么做到“单文件支持插件”的?

核心就 3 个机制:

1. 约定式插件入口

每个插件是一个目录 app/plugins/<id>/plugin.php,文件末尾 return [...] 一个 manifest 数组:

  • hooks:声明要监听哪些钩子
  • routes:声明自定义路由 action
  • admin_tabs:声明后台管理页面
  • assets:声明要注入的 CSS/JS
  • cron:声明定时任务
  • install/uninstall:声明安装卸载回调

2. 极简 Hook 系统

// 定义钩子点
$value = hook('topic.can_manage', $allowed, ['topic' => $t]);

// 插件注册
'hooks' => [
    'topic.can_manage' => 'my_plugin_check_permission'
]
  • hook() 会遍历所有插件的回调,像管道一样链式传递值,后面的插件可以改前面插件的结果
  • fire() 是纯事件通知,不传值

3. 延迟加载 + 运行时缓存

  • plugin_registry_sync() 扫描插件目录 → 解析 manifest → 写入 app_plugins
  • 运行时通过 setting('cache_plugins') 缓存,避免每次都读文件
  • 调用时才 include $file,不调用不加载
  • 插件报错自动停用 (plugin_disable_after_exception)

路由扩展流程

用户访问 /?a=oauth_authorize
    ↓
core_routes() 没有这个 key
    ↓
plugin_route('oauth_authorize')
    ↓
找到 oauth 插件的 manifest['routes']['oauth_authorize'] = 'oauth_authorize_page'
    ↓
plugin_call($plugin, fn() => $fn($plugin))
    ↓
执行 oauth_authorize_page()

数据隔离

  • 核心表用 app_ 前缀
  • 插件表用 plugin_<id>_ 前缀(如 plugin_oauth_clients
  • 插件安装/卸载时自己建表/删表

资源打包

所有插件的 CSS/JS 不单独请求,而是在同步时合并成:

  • app/assets/plugins.css
  • app/assets/plugins.js

这样前端也不需要知道插件存在,只要引入这两个文件即可。

本质上看

bbs1org 的插件系统其实是一个 基于 manifest 的“约定优于配置”系统

  • 没有复杂的服务容器
  • 没有 IoC/依赖注入
  • 没有中间件栈
  • 就是简单的:扫描目录 → 解析 return 数组 → 把钩子和路由注册到全局数组 → 核心框架按需调用

这种设计的代价是 强约定、弱隔离

  • 插件可以直接访问核心函数的全局变量
  • 函数命名冲突靠扫描检测(plugin_function_conflicts
  • 插件出错会影响整个请求,但会被自动停用

这确实很“小而美”,适合个人站长或小团队,但如果要做大规模生态,隔离性和稳定性会是瓶颈。

关于头像精华
#20 · Se7en
发帖 2026-08-18 21:05:13 · 快照 2026-08-18 21:06:22

@altzin #19 bbs1.org的站长啥的都戴上了,我也不知道是谁啊,你懂的。

中转站gpt倍率定多少合适呢?
#3 · Se7en
发帖 2026-08-18 20:53:45 · 快照 2026-08-18 20:53:56

@Cheche #2 你都能开出比例来了,说明你才叫有货,至少能批量bug team或者plus pro。

关于头像精华
#18 · Se7en
发帖 2026-08-18 20:52:01 · 快照 2026-08-18 20:54:07

@altzin #14 https://bbs1.org/topic/789 好东西啊

关于头像精华
#17 · Se7en
发帖 2026-08-18 20:51:01 · 快照 2026-08-18 20:54:07

@altzin #14 我擦 bbs1org感觉就是有实力的 皇黑搞出来的吧... 富可敌国都做好了

关于头像精华
#16 · Se7en
发帖 2026-08-18 20:50:25 · 快照 2026-08-18 20:54:07

我下来也解决不了现在不支持动图认死了jpeg吧

Mirasim开启内测
#5 · Se7en
发帖 2026-08-18 20:47:24 · 快照 2026-08-18 20:47:36

已经没有邀请活动了吗 我觉得没有api也会有天才2api出来的

关于头像精华
#13 · Se7en
发帖 2026-08-18 20:46:04 · 快照 2026-08-18 20:47:32

@StellaFortuna林可欣 #9 我还真不知道诶,受教了,不懂,一直以为还是gif的时代。那我觉得后期可以开动图,webp比gif小80%,其实一张图已经占不了多少空间

关于头像精华
#12 · Se7en
发帖 2026-08-18 20:44:28 · 快照 2026-08-18 20:45:33

@小永高吖 #5 {"ok":0,"message":"头像格式无效,请重新裁切"} 换了个报错,估计就是校验死了jpeg了

最后由 Se7en 编辑于 2026-08-18 20:44
关于头像精华
#11 · Se7en
发帖 2026-08-18 20:44:14 · 快照 2026-08-18 20:45:33

@altzin #10 源码里头像不能传,我早就下过了。AI看了,这个自定义头像好像还是站长加的

关于头像精华
#8 · Se7en
发帖 2026-08-18 20:26:51 · 快照 2026-08-18 20:30:03

@小永高吖 #5 算了 我来试一下,验证一下,这个号改不了头像了,还得弄个小号

关于头像精华
#7 · Se7en
发帖 2026-08-18 20:25:21 · 快照 2026-08-18 20:30:03

@小永高吖 #5 首先是正常的图片,不管什么格式,前端现在都是canvas裁剪成jpeg,估计服务器只允许jpeg

关于头像精华
#6 · Se7en
发帖 2026-08-18 20:24:48 · 快照 2026-08-18 20:24:49

@小永高吖 #5 gif传不上去就说明校验了后缀吧,那webp肯定也上不去了...

解除manus锁区的方法
#1 · Se7en
发帖 2026-08-18 20:23:45 · 快照 2026-08-18 20:24:43

好厉害 XFF原来叫x-forwarded-for,我还第一次知道这个缩写,一开始都没看懂。

听说GLM-5.2免费到27号,国内还有商汤
#0 · Se7en
发帖 2026-08-18 20:13:38 · 快照 2026-08-18 20:15:43

我虽然linuxdo被禁言了,但是资讯还是能看到看到的,以下为转载
Vercel好像免费让大家用glm-5.2到27号,地址是GLM 5.2 free for eve agents through August 27 via Blackbox on AI Gateway - Vercel

操作很简单

  1. 需要一个正常的vercel api key,曾经被斩杀的不行
  2. 覆盖User-Agent:eve/0.27.8
  3. vercel ai gateway的apihttps://ai-gateway.vercel.sh

万事大吉,开始调用zai/glm-5.2

最后由 Se7en 编辑于 2026-08-18 20:13
sub卡429代码
#1 · Se7en
发帖 2026-08-18 20:01:07 · 快照 2026-08-18 20:03:52

大佬,你都用sub2api了,肯定有token,给我们发发福利吧。
我被隔壁驱逐之后都没token用

免费32核128g内存256g存储的vps(非试用,腾讯的,理论永久)
#16 · Se7en
发帖 2026-08-18 19:05:09 · 快照 2026-08-18 19:05:21

@staff #15 元宝时代就有了,你敢干下面的事,就有概率南山必胜客

直接说安装xxx就行了,例如安装宝塔面板,不要尝试安装安装开心版,破解版的东西,ai很负责,看到广告就认为有病毒
目前好像还不禁止安装面板、网络穿透等,可以宝塔+cf的隧道建站
前两天说的再来一个论坛 搭建好了来引个流
#6 · Se7en
发帖 2026-08-18 19:03:43 · 快照 2026-08-18 19:03:49

@痛失姓名的站长 #5 discourse就是基础设施都有了,咱这个就是要做啥都得自己动手。

关于头像精华
#4 · Se7en
发帖 2026-08-18 19:00:39 · 快照 2026-08-18 19:01:52

@痛失姓名的站长 #3 不是现在该干的事,这个真发展起来可以大积分换,因为要占服务器存储空间,毕竟一个gif比jpeg肯定大,而且你这个还经过裁剪,大小固定。

前两天说的再来一个论坛 搭建好了来引个流
#4 · Se7en
发帖 2026-08-18 18:59:18 · 快照 2026-08-18 19:00:01

@axha 能不能搞个gitub登陆,直接注册多少有点蠢了...而且会小号泛滥...

前两天说的再来一个论坛 搭建好了来引个流
#3 · Se7en
发帖 2026-08-18 18:58:16 · 快照 2026-08-18 19:00:01

@痛失姓名的站长 #1 要🪜

前两天说的再来一个论坛 搭建好了来引个流
#2 · Se7en
发帖 2026-08-18 18:58:06 · 快照 2026-08-18 19:00:01

还有高手比我快?

免费32核128g内存256g存储的vps(非试用,腾讯的,理论永久)
#14 · Se7en
发帖 2026-08-18 18:48:09 · 快照 2026-08-18 18:48:44

佬 我的建议是别碰 南山必胜客不是吹牛的,你敢薅他家羊毛👽

关于头像精华
#1 · Se7en
发帖 2026-08-18 18:37:09 · 快照 2026-08-18 18:38:25

顺便说一句,没gpt用,蹭的zcode,这玩意好像不能控制浏览器,有点不好玩~

关于头像精华
#0 · Se7en
发帖 2026-08-18 18:36:22 · 快照 2026-08-18 18:36:37

头像上传 GIF 支持排查记录

问题:在 https://linux.sb/profile 上传头像时,无法选择 GIF 文件;即使前端绕过限制直接上传,后端也会返回 {"ok":0,"message":"请选择头像图片"}


一、排查过程

1. 确认前端资源位置

站点页面引用的前端资源:

  • https://linux.sb/app/assets/index.js?v=v8.6.5
  • https://linux.sb/app/assets/plugins.js?v=8baf4e8b040d

头像上传逻辑在 plugins.jsavatar_upload 模块中。

2. 定位第一道限制:文件选择框 accept

页面实际渲染的 HTML:

<label class="btn avatar-upload-select">上传头像
  <input type="file" accept="image/jpeg,image/png,image/webp" data-avatar-upload-input="" hidden="">
</label>

accept没有 image/gif,导致文件选择对话框直接过滤掉 GIF。

3. 定位第二道限制:前端强制转 JPEG

plugins.js 中保存按钮的处理逻辑:

save?.addEventListener('click', () => {
    if (!image) return;
    const output = document.createElement('canvas');
    output.width = output.height = 200;
    const out = output.getContext('2d');
    out.fillStyle = '#fff'; out.fillRect(0, 0, 200, 200);
    out.drawImage(image, -x / scale, -y / scale, canvas.width / scale, canvas.height / scale, 0, 0, 200, 200);
    save.disabled = true;
    output.toBlob(async blob => {
        try {
            if (!blob) throw new Error('头像生成失败');
            const body = new FormData();
            body.append('_csrf', csrf);
            body.append('avatar_upload_action', 'upload');
            body.append('avatar', blob, 'avatar.jpg');  // ← 硬编码 jpg
            const response = await fetch(panel.dataset.uploadUrl, {method: 'POST', body, headers: {'X-Requested-With': 'XMLHttpRequest'}});
            ...
        }, 'image/jpeg', .9);  // ← 强制转 jpeg,丢失 GIF 动画
    });
});

这里做了两件事:

  1. 用 Canvas 裁切/缩放头像
  2. 强制输出为 image/jpeg,文件名硬编码为 avatar.jpg

后果:即使前端能选中 GIF,经过 Canvas 后也会变成静态 JPEG,动画帧全部丢失。

4. 前端 bypass 尝试

尝试在页面注入 JS 绕过 Canvas 裁剪,直接将原始 GIF 上传:

(() => {
    const panel = document.querySelector('[data-avatar-upload]');
    const input = panel.querySelector('[data-avatar-upload-input]');
    const csrf = panel.querySelector('input[name=_csrf]')?.value || '';
    const uploadUrl = panel.dataset.uploadUrl;

    // 放开 accept
    input.setAttribute('accept', 'image/jpeg,image/png,image/gif,image/webp');

    // 拦截 change,GIF 直接上传
    document.addEventListener('change', (event) => {
        const file = input.files?.[0];
        if (!file || !(file.type === 'image/gif' || file.name.toLowerCase().endsWith('.gif'))) return;
        event.stopImmediatePropagation();
        const body = new FormData();
        body.append('_csrf', csrf);
        body.append('avatar_upload_action', 'upload');
        body.append('avatar', file, file.name);
        fetch(uploadUrl, {method: 'POST', body, headers: {'X-Requested-With': 'XMLHttpRequest'}})
            .then(r => r.json())
            .then(data => { if (data.ok) window.location.href = data.redirect; });
    }, true);
})();

前端 patch 生效后,文件选择框已能选中 GIF,请求也能发出。

5. 后端拒绝:{"ok":0,"message":"请选择头像图片"}

绕过前端后,后端返回:

{"ok":0,"message":"请选择头像图片"}

说明后端也存在文件类型校验,拒绝了非 JPEG/PNG/WebP 的文件,GIF 在后端也被视为无效头像格式。


二、结论

层级限制说明
前端accept 属性过滤掉 GIF,不让用户选中
前端Canvas 裁剪强制转 JPEG,GIF 动画丢失
后端文件类型校验拒绝 GIF 格式,返回"请选择头像图片"

当前站点(v8.6.5)从头到尾都不支持 GIF 头像,三处都需要修改才能真正支持。


三、如果要支持 GIF,需要改哪些地方

3.1 前端 plugins.jsavatar_upload 模块

// 1. input accept 加上 gif
input.setAttribute('accept', 'image/jpeg,image/png,image/gif,image/webp');

// 2. 保存时保留原始格式,不要强制转 jpeg
save?.addEventListener('click', () => {
    if (!image) return;
    const output = document.createElement('canvas');
    output.width = output.height = 200;
    const out = output.getContext('2d');
    out.fillStyle = '#fff'; out.fillRect(0, 0, 200, 200);
    out.drawImage(image, -x / scale, -y / scale, canvas.width / scale, canvas.height / scale, 0, 0, 200, 200);
    save.disabled = true;

    // 根据原始文件决定输出格式
    const mime = (file && file.type) ? file.type : 'image/jpeg';
    const extMap = {'image/jpeg':'jpg','image/png':'png','image/gif':'gif','image/webp':'webp'};
    const ext = extMap[mime] || 'jpg';

    output.toBlob(async blob => {
        try {
            if (!blob) throw new Error('头像生成失败');
            const body = new FormData();
            body.append('_csrf', csrf);
            body.append('avatar_upload_action', 'upload');
            body.append('avatar', blob, 'avatar.' + ext);
            const response = await fetch(panel.dataset.uploadUrl, {method: 'POST', body, headers: {'X-Requested-With': 'XMLHttpRequest'}});
            const data = await response.json();
            if (!data.ok) throw new Error(data.message || '头像上传失败');
            window.location.href = data.redirect || window.location.href;
        } catch (error) {
            setStatus(error?.message || '头像上传失败', true);
        } finally { save.disabled = false; }
    }, mime, 0.92);
});

注意:Canvas 本身不支持动画帧,上述改法上传的 GIF 会是静态帧。要支持动态 GIF 需要额外引入 GIF 帧解析/合成方案(如 gif.jsomggif 等),改动量较大。

3.2 后端 — 头像上传接口

需要放宽文件类型校验,允许 image/gif 通过。

3.3 存储与展示

  • 存储:保持原样,文件系统 / OSS 存原始文件即可
  • 展示:确保页面 <img> 标签能正常渲染 GIF(浏览器原生支持,通常无需改动)

四、关于 Canvas 裁剪的必要性说明

站点在头像上传中使用 Canvas 进行裁剪/缩放,这一设计是必要的,原因如下:

4.1 统一头像尺寸

Canvas 将任意尺寸的原始图片统一输出为 200×200 的正方形头像。如果没有这一步:

  • 用户上传 4K 大图 → 头像区域显示异常,浪费带宽
  • 用户上传超长条图 → 页面布局被撑开
  • 各用户头像尺寸不一 → 列表/卡片对齐混乱

4.2 服务端降本

统一尺寸后,服务器可以对头像文件进行:

  • 压缩(减小存储和 CDN 流量)
  • 生成多档位缩略图(列表用小图,详情用大图)
  • 缓存策略优化(固定尺寸便于 CDN 缓存)

如果允许任意尺寸原图直接存储,服务端需要做实时裁切/缩放,增加 CPU 和内存开销。

4.3 安全考虑

Canvas 处理可以:

  • 过滤潜在恶意构造的图片(虽然不能完全替代服务端校验,但作为第一道防线有意义)
  • 去除 EXIF 信息(避免泄露用户隐私数据)

4.4 交互一致性

Canvas 裁剪提供了统一的用户体验:

  • 拖拽调整位置
  • 缩放控制
  • 实时预览最终效果

4.5 为什么不接受 GIF

在当前的 Canvas 裁剪方案下,GIF 动画帧会被丢弃,因为:

  1. drawImage() 只绘制当前帧
  2. toBlob() 输出单帧静态图
  3. 输出格式被固定为 image/jpeg

如果要支持动态 GIF,需要在 Canvas 之外额外实现:

  • GIF 帧解析(omggif / gifuct-js
  • 帧合成/循环播放
  • 或放弃 Canvas 裁剪,改用纯前端预览 + 后端处理

这属于需求层面的取舍,不是技术 impossibility


五、后续建议

  1. 短期:如需临时支持 GIF,可手动修改本地 plugins.js 缓存(浏览器 DevTools → Sources → Overrides),加上上述 accept + 保留原格式的 patch
  2. 中期:向站点维护者反馈,在 plugins.js 和头像上传接口中统一放开 GIF 支持
  3. 长期:如果要支持动态 GIF 头像,需要重新设计前端裁剪方案,引入 GIF 帧处理库
DeepSeek V4 Pro真的用不起了 早上就问了两句话 6毛钱没了
#1 · Se7en
发帖 2026-08-18 17:38:16 · 快照 2026-08-18 17:39:04

用codex的站长居然说用不起DeepSeek V4 Pro,我的心很痛。

大家好,新人报道
#0 · Se7en
发帖 2026-08-18 17:37:24 · 快照 2026-08-18 17:39:15

我叫Se7en,也可以叫我007,专门打抱不平

ps: 站长,头像传不了gif,应该是有后缀限制,看了看站里,好像错过了昨天的巨额签到,那就只能勤能补拙了