ARTICLE · 1312482
群聊系统看似自研,实则是付费源码的汉化版!!
声明一下:本文涉及的源码仅用于分享和学习,原代码都放在源码库里作为记录。
看着像自己写的系统
功能做得很细底子不是
从零写的
自托管群聊社区系统 · 双角色权限 · 富文本过滤
bbbb.bid · 狗凯源码仓库
📦 5 Parts + Conclusion
👉 滑动
PART 01
底子哪来的
付费脚本汉化版
PART 02
权限分层
两套角色表
PART 03
富文本过滤
白名单五步
PART 04
音视频推送
两个前置条件
PART ///
写在最后
三处值得翻
一个想给站点加社区功能的人,搜到这套源码,把功能列表拉下来挺长:公开群、私密群、一对一私聊、图片文件 GIF 表情语音视频、链接预览、脏话过滤、徽章、封禁、广告位、多语言、PWA、开放 API。

看着不像几百行能写出来的东西。
01
PART
底子不是开源:Grupo Pro 3.1 的付费汉化版
ORIGIN · 来历是三手
来历标注得挺清楚:国外付费系统 Grupo Pro 的 3.1 版本,国内转售商「松果」汉化,这一套是经过审计清理后的版本。

原厂那边安装要填数据库信息,再填一个 Purchase Code,安装向导才能往下走。3.1 版本官方列出来的功能里,Flood Control、Profanity Filter、Image Moderation、Recaptcha、四十多个社交登录提供商、PWA、WordPress 集成、暗色模式、RTL 布局,全在清单上。
所以手上这份代码的路径是:原厂产品,转售商汉化,源码库再清一遍。
功能清单本身不含糊,它就是照着原厂那套下来的。含糊的是这串转手。
02
PART
双角色权限:site_roles 和 group_roles 分层管人
ROLES · 两套表叠着用
权限这块是这套源码做得比较细的部分。
站点角色和群角色是两张独立的表:site_roles 管全站,group_roles 管单个群。分层是管理员、普通会员、群主、群管理。徽章另走一套 assign_badges。

封禁分三档:封单个群、封全站、封 IP 段,最后这项走 ip_blacklist。注册要不要人工审批由 approve_users 开关控制,用户资料能挂自定义字段 custom_field。

原厂的 User Role Manager 是勾选式的能力配置——勾上某个角色能干什么,保存生效。两层角色叠起来意味着:一个人可以是站点普通会员,在某个群里是群主,在另一个群里什么都不是。
这套表结构值得单独看一眼。
03
PART
用户发的富文本:HTMLPurifier 白名单过一遍
XSS · 白名单五步
聊天消息能带图片、文件、GIF、贴纸、表情,前端是 Summernote 编辑器,存下来的是富文本 HTML。这种内容直接入库直接渲染就是 XSS 入口。
这里的做法是上 HTMLPurifier。它不是拿正则去黑名单匹配危险标签,而是白名单驱动:先把文档解析成结构,按允许清单丢掉不在名单上的标签和属性,属性值本身也要查(href 里的 URL 会被验),CSS 属性同样按白名单过一遍,最后重新序列化成一份规范的 HTML。
流程是解析、词法、过滤、转换、序列化五步。输出既挡了 XSS,也顺带保证 HTML 合规。
同一批安全库里还放着 PHPMailer 负责邮件、一个自研 firewall 模块。
消息从编辑器出来到入库,中间就隔着这一层。
04
PART
语音和视频:FFMpeg 没装就只剩个播放器
MEDIA · 链路与前置
音视频有明确前置条件:FFMpeg 封装在代码里,但服务器得自己装 ffmpeg,不装就只有播放器,没有转码也没有缩略图。
实时这块是 fns/realtime 包起来的轮询和推送,再加 OneSignal 做 Web Push。
浏览器推送的链路不是服务端直连浏览器。浏览器订阅后把订阅信息交回服务端存起来;要推的时候,服务端加密报文,POST 到浏览器的推送服务,推送服务等设备能收的时候把消息送过去,浏览器的 service worker 被唤醒,由它决定怎么弹。
前提是站要走 HTTPS、service worker 注册成功、用户授权通过,而且浏览器得开着——页面全关的时候,Web Push 收不到。

///
LAST
写在最后:这三处代码值得翻
READING · 三处主线
这套代码里值得翻的是三处:双角色权限那套表结构,HTMLPurifier 在消息入口的位置,fns/realtime 怎么把轮询和推送揉在一起。
上手之前先把两个前置确认了:ffmpeg 装没装,PHP 扩展齐不齐。
资源来源:源码库 bbbb.bid关注星标公众号,不定期分享源码干货与安全审计笔记。















































































