├── .github └── workflows │ └── frontend-dispatch.yml ├── .gitignore ├── LICENSE ├── README.md ├── Timeline.md ├── api.yaml ├── index.html ├── 人物.md ├── 图片.md ├── 条目.md ├── 用户.md ├── 用户收藏.md ├── 编辑历史.md ├── 角色.md └── 讨论贴.md /.github/workflows/frontend-dispatch.yml: -------------------------------------------------------------------------------- 1 | name: Fronend Dispatch 2 | on: 3 | push: 4 | paths: [ 'api.yaml' ] 5 | 6 | jobs: 7 | dispatch: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Repository Dispatch 11 | uses: peter-evans/repository-dispatch@v2 12 | with: 13 | token: ${{ secrets.REPO_ACCESS_TOKEN }} 14 | repository: bangumi/frontend 15 | event-type: update-types 16 | client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}' 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Bangumi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 开发文档 2 | 3 | 本仓库包含开发文档和 meta issue (如 [roadmap](https://github.com/bangumi/dev-docs/issues/1))。 4 | 5 | ## 仓库说明 6 | 7 | - 现有API相关 8 | - [`bangumi/server`](https://github.com/bangumi/server) 仓库为目前 bangumi 网站运作的新 api 后端,基于 Go,实现现有的公开 api。 9 | - 新网站相关 10 | - [`bangumi/frontend`](https://github.com/bangumi/frontend) 仓库为新网站的前端。 11 | - [`bangumi/server-private`](https://github.com/bangumi/server-private) 仓库为新网站 api 后端,基于 TypeScript,实现私有 API,专为新网站前端使用。 12 | - 开发相关 13 | - [`bangumi/dev-env`](https://github.com/bangumi/dev-env) 仓库包含配置文件(docker-compose)和开发数据,用于后端开发和测试使用。 14 | - [`bangumi/api`](https://github.com/bangumi/api) 仓库包括 API 文档,用于第三方开发者查看。 15 | - 微服务 16 | - [`bangumi/img-proxy`](https://github.com/bangumi/img-proxy) 切图服务器。 17 | - 其他 18 | - [`bangumi/wiki-syntax-spec`](https://github.com/bangumi/wiki-syntax-spec) 为 wiki 语法的定义,用于未来扩展 wiki 功能。 19 | - [`bangumi/common`](https://github.com/bangumi/common) 仓库包括 relation, platform, staff 等常量对应关系的 yaml 文件。 20 | 21 | 不同的仓库拥有更具体的贡献要求,请阅读相关仓库的说明和贡献指南。 22 | 23 | ## API 24 | 25 | ### 现有公开 API 26 | 27 | 目前 bangumi 网站实际提供的了两套 API 28 | 29 | 1. 旧的公开 API 30 | 31 | 这套 API 是 bangumi 最老也是最开始提供的 API,由 sai 编写,未开源。目前此 API 已停止维护(修 BUG 加功能得找 sai,但 sai 精力有限)。 32 | 33 | `https://api.bgm.tv/subject/100` 这种 API 路径中没有 `/v0/` 版本信息的 API 就是旧有 API。 34 | 35 | 很多有一点历史的第三方开源项目仍在使用此 API。出于兼容考虑旧 API 依旧能访问但已不推荐使用,相关 API 文档已隐藏。 36 | 2. 新的公开 API 37 | 38 | 为了取代旧的公开 API,目前 bangumi 提供了另一套 API。`https://api.bgm.tv/v0/subject/100` 这种路径以 `/v0/` 开头的即新的公开API。 39 | 40 | 此 API 代码开源,由 Go 编写任何人都可参与项目,代码仓库为 [`bangumi/server`](https://github.com/bangumi/server)。在使用 API 时如遇到BUG 或有新需求可提 issue,也欢迎提 PR 贡献代码。但因为新的公开 API 已经发布,需要保证兼容性,所以即便有功能变动也不会引入 break change。 41 | 42 | 新公开 API 使用 access token 进行用户认证,GET 请求支持跨域。 43 | 44 | | | 信息 | 45 | | ------------------------------------------------ | ---------------------------------------------- | 46 | | OpenAPI 文档 | https://bangumi.github.io/api/ | 47 | | OpenAPI 文档仓库 | [`bangumi/api`](https://github.com/bangumi/api) | 48 | | 生产环境Domain | `api.bgm.tv` | 49 | | 开发环境Domain``(仅支持路径 `/v0/` 下的路由) | `api.bgm38.tv` | 50 | 51 | 52 | > 开发环境使用仓库 [`bangumi/dev-env`](https://github.com/bangumi/dev-env) 中包含的数据,不定时会进行重置 53 | > 54 | 55 | ### 新网站和私有 API 56 | 57 | 目前 bangumi 正在进行新网站的开发,基于 React/TypeScript/Vite。新网站也开源,前端仓库位于 [`bangumi/frontend`](https://github.com/bangumi/frontend),欢迎提交代码。 58 | 59 | 新网站前端使用 API 与后端通信,前端所使用的 API 被称为私有 API。私有 API 与现有公开 API 不同,专为新网站前端使用而开发。使用 cookies session 进行用户认证,目前仍处于开发阶段,无兼容性保证,不支持跨域。仓库位于 [`bangumi/server-private`](https://github.com/bangumi/server-private) 。 60 | 61 | | | 信息 | 62 | | -------------- | ----------------------------------------------------------------------- | 63 | | OpenAPI 文档 | https://bangumi.github.io/dev-docs/ https://next.bgm38.com/p1/ | 64 | | 生产环境Domain | `next.bgm.tv` | 65 | | 开发环境Domain | `next.bgm38.tv` | 66 | 67 | 开发环境使用仓库 [`bangumi/dev-env`](https://github.com/bangumi/dev-env) 中包含的数据,不定时会进行重置。开发环境 `bangumi/dev-env` 所包含的账号如下: 68 | 69 | | uid | 昵称 | 邮箱 | 密码 | 备注 | 70 | | :--------: | :------------: | :-------------------------: | :--------------: | :----------------: | 71 | | `2` | `nickname 2` | `2@bgm38.com` | `lovemeplease` | 拥有 wiki 编辑权限 | 72 | | `382951` | `树洞1` | `treeholechan@gmail.com` | `lovemeplease` | | 73 | | `318250` | `树洞2` | `treeholechan2@gmail.com` | `lovemeplease` | | 74 | 75 | ## 公开 API 和私有 API 的关系 76 | 77 | 公开 API 主要为 APP 等客户端而开发,今后新网站发布后也依旧会持续维护和使用。 私有 API 专为新网站前端开发,为网站前端专用。今后新网站发布后将会同时存在两套 API 。 78 | -------------------------------------------------------------------------------- /Timeline.md: -------------------------------------------------------------------------------- 1 | # Timeline 2 | 3 | # Data Structure 4 | 5 | ```sql 6 | CREATE TABLE IF NOT EXISTS `chii_timeline` ( 7 | `tml_id` int unsigned NOT NULL AUTO_INCREMENT, 8 | `tml_uid` mediumint unsigned NOT NULL DEFAULT '0', 9 | `tml_cat` smallint unsigned NOT NULL, 10 | `tml_type` smallint unsigned NOT NULL DEFAULT '0', 11 | `tml_related` char(255) NOT NULL DEFAULT '0', 12 | `tml_memo` mediumtext NOT NULL, 13 | `tml_img` mediumtext NOT NULL, 14 | `tml_batch` tinyint unsigned NOT NULL, 15 | `tml_source` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '更新来源', 16 | `tml_replies` mediumint unsigned NOT NULL COMMENT '回复数', 17 | `tml_dateline` int unsigned NOT NULL DEFAULT '0', 18 | PRIMARY KEY (`tml_id`) 19 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 20 | ``` 21 | 22 | - `tml_cat` 一级分类 23 | - `tml_type` 二级类型 24 | - `tml_related` 直接关联 ID 25 | - `tml_memo` 关联数据 26 | - `tml_img` 关联图片数据(封面、头像、小组图标等,v2 将废弃) 27 | - `tml_batch` 是否为批量数据 28 | 29 | # Constants 30 | 31 | ## Category 32 | 33 | ```yaml 34 | CAT_DAILY = 1 #日常行为 35 | CAT_WIKI = 2 #维基操作 36 | CAT_SBJ_COLLECT = 3 #收藏 37 | CAT_BGM_PROGRESS = 4 #进度管理 38 | CAT_STATUS = 5 #吐槽 39 | CAT_BLOG = 6 #日志 40 | CAT_INDEX = 7 #目录 41 | CAT_MONO = 8 #人物 42 | ``` 43 | 44 | ## Type 45 | 46 | 不同 Category 对应二级的 Type 47 | 48 | - CAT_DAILY 49 | 50 | ```yaml 51 | 注册 = 1 52 | 添加好友 = 2 53 | 加入小组 = 3 54 | 创建小组 = 4 55 | 加入乐园 = 5 56 | ``` 57 | 58 | - CAT_BGM_PROGRESS 59 | 60 | ```yaml 61 | TYPE_BGM_PROGRESS_BATCH = 0 62 | TYPE_BGM_PROGRESS_SINGLE = 1 63 | ``` 64 | 65 | - CAT_STATUS 66 | 67 | ```yaml 68 | TYPE_STATUS_SIGN = 0 69 | TYPE_STATUS_TSUKKOMI = 1 70 | TYPE_STATUS_NICKNAME = 2 71 | ``` 72 | 73 | - CAT_SBJ_COLLECT 根据条目类型与收藏动作类型进行 Mapping,用于对于不同收藏动作 74 | 75 | ```yaml 76 | #subject_type: { collect_type: tml_type } 77 | 1: {1: 1, 2: 5, 3: 9, 4: 13, 5: 14} 78 | 2: {1: 2, 2: 6, 3: 10, 4: 13, 5: 14} 79 | 3: {1: 3, 2: 7, 3: 11, 4: 13, 5: 14} 80 | 4: {1: 4, 2: 8, 3: 12, 4: 13, 5: 14} 81 | 6: {1: 2, 2: 6, 3: 10, 4: 13, 5: 14} 82 | ``` 83 | 84 | ```yaml 85 | 1 = 想读 86 | 2 = 想看 87 | 3 = 想听 88 | 4 = 想玩 89 | 5 = 读过 90 | 6 = 看过 91 | 7 = 听过 92 | 8 = 玩过 93 | 9 = 在读 94 | 10 = 在看 95 | 11 = 在听 96 | 12 = 在玩 97 | 13 = 搁置了 98 | 14 = 抛弃了 99 | ``` 100 | 101 | 102 | # V2 tml_memo 103 | 104 | php serialize 存储,未来迁移到 json 格式 105 | 106 | v2 起,在 `tml_memo` 与中不再存储关联条目详细数据,展示 Timeline 时动态获取条目信息。 107 | 108 | - `tml_memo` 中只存储关联条目 id,在展示时通过 `subject_id` 、`ep_id` 等查询对应条目详细信息 109 | - `tml_img` 废弃,不存储图片信息 110 | 111 | 目前 v2 支持的类型: 112 | 113 | - CAT_WIKI 114 | - CAT_SBJ_COLLECT 115 | - CAT_BGM_PROGRESS 116 | 117 | ### CAT_WIKI 维基编辑 118 | 119 | - subject_id 120 | 121 | ### CAT_SBJ_COLLECT 条目收藏 122 | 123 | - `subject_id` 条目 ID 124 | - `collect_id` 收藏 ID 125 | - `collect_comment` 收藏时的吐槽,需要进行 html 转义 126 | - `collect_rate` 收藏时的评分 127 | 128 | 如: 129 | 130 | ```json 131 | { 132 | "subject_id": 2, 133 | "collect_id": 12346, 134 | "collect_comment": "Amazing", 135 | "collect_rate": 1 136 | } 137 | ``` 138 | 139 | **同类收藏合并** 140 | 141 | 如用户 10 分钟内有同样的收藏类型与动作,则相同类型与动作的 Timeline `tml_batch` 标记为 1,将 `tml_memo` 合并存储 142 | 143 | `{ #subject_id: {}, #subject_id: {} }` 结构。 144 | 145 | 如: 146 | 147 | ```json 148 | { 149 | "2":{ 150 | "subject_id": 2, 151 | "collect_id": 12346, 152 | "collect_comment": "Amazing", 153 | "collect_rate": 1 154 | }, 155 | "975":{ 156 | "subject_id": 975, 157 | "collect_id": 12347 158 | } 159 | } 160 | ``` 161 | 162 | ### CAT_BGM_PROGRESS 进度管理 163 | 164 | - TYPE_BGM_PROGRESS_BATCH 批量进度 165 | - `subject_id` 条目 ID 166 | - `eps_total` 总章节 167 | - `eps_update` 当前章节 168 | - `vols_total` 总卷数 169 | - `vols_update` 当前卷数 170 | - TYPE_BGM_PROGRESS_SINGLE 单条进度 171 | - `ep_id` 章节 ID 172 | - `subject_id` 条目 ID 173 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bangumi Private API 6 | 11 | 16 | 17 | 18 |
19 | 20 | 21 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /人物.md: -------------------------------------------------------------------------------- 1 | ## 基础信息 2 | 3 | ```sql 4 | CREATE TABLE IF NOT EXISTS `chii_persons` ( 5 | `prsn_id` mediumint(8) unsigned NOT NULL, 6 | `prsn_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 7 | `prsn_type` tinyint(4) unsigned NOT NULL COMMENT '个人,公司,组合', 8 | `prsn_infobox` mediumtext COLLATE utf8_unicode_ci NOT NULL, 9 | `prsn_producer` tinyint(1) NOT NULL, 10 | `prsn_mangaka` tinyint(1) NOT NULL, 11 | `prsn_artist` tinyint(1) NOT NULL, 12 | `prsn_seiyu` tinyint(1) NOT NULL, 13 | `prsn_writer` tinyint(4) NOT NULL DEFAULT '0' COMMENT '作家', 14 | `prsn_illustrator` tinyint(4) NOT NULL DEFAULT '0' COMMENT '绘师', 15 | `prsn_actor` tinyint(1) NOT NULL COMMENT '演员', 16 | `prsn_summary` mediumtext COLLATE utf8_unicode_ci NOT NULL, 17 | `prsn_img` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 18 | `prsn_img_anidb` varchar(255) CHARACTER SET utf8 NOT NULL, 19 | `prsn_comment` mediumint(9) unsigned NOT NULL, 20 | `prsn_collects` mediumint(8) unsigned NOT NULL, 21 | `prsn_dateline` int(10) unsigned NOT NULL, 22 | `prsn_lastpost` int(11) unsigned NOT NULL, 23 | `prsn_lock` tinyint(4) NOT NULL, 24 | `prsn_anidb_id` mediumint(8) unsigned NOT NULL, 25 | `prsn_ban` tinyint(3) unsigned NOT NULL DEFAULT '0', 26 | `prsn_redirect` int(10) unsigned NOT NULL DEFAULT '0', 27 | `prsn_nsfw` tinyint(1) unsigned NOT NULL 28 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='(现实)人物表'; 29 | ``` 30 | 31 | `prsn_img_anidb` 为废弃字段,`prsn_dateline`没有使用。 32 | 33 | `prsn_producer`,`prsn_mangaka`,`prsn_artist`,`prsn_seiyu`,`prsn_writer`,`prsn_illustrator`,`prsn_actor` 字段为编辑页面的职业勾选框。 34 | 35 | `prsn_lastpost` 为最近的用户评论日期。 36 | 37 | ## 关联条目 38 | 39 | 人物参与的条目在`chii_person_cs_index`表中。 40 | 41 | ```sql 42 | CREATE TABLE IF NOT EXISTS `chii_person_cs_index` ( 43 | `prsn_type` enum('prsn','crt') COLLATE utf8_unicode_ci NOT NULL, 44 | `prsn_id` mediumint(9) unsigned NOT NULL, 45 | `prsn_position` smallint(5) unsigned NOT NULL COMMENT '监督,原案,脚本,..', 46 | `subject_id` mediumint(9) unsigned NOT NULL, 47 | `subject_type_id` tinyint(4) unsigned NOT NULL, 48 | `summary` mediumtext COLLATE utf8_unicode_ci NOT NULL, 49 | `prsn_appear_eps` mediumtext COLLATE utf8_unicode_ci NOT NULL COMMENT '可选,人物参与的章节' 50 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='subjects'' credits/creator & staff (c&s)index'; 51 | ``` 52 | 53 | 此表中的`prsn_type`必定为`"prsn"`可以忽略。 54 | 55 | 需要从此表中查出 `subject_type_id` 和 `prsn_position`,然后在预先定义的变量中查找具体职位内容。https://github.com/bangumi/server/blob/c72c7a4704565500af54d411550ce15af92fa2ed/pol/db/_const.py#L11 56 | 57 | ## 额外字段 58 | 59 | `chii_person_fields`表为现实人物和虚拟角色的 wiki 解析字段。 60 | 61 | ```sql 62 | CREATE TABLE IF NOT EXISTS `chii_person_fields` ( 63 | `prsn_cat` enum('prsn','crt') COLLATE utf8_unicode_ci NOT NULL, 64 | `prsn_id` int(8) unsigned NOT NULL, 65 | `gender` tinyint(4) unsigned NOT NULL, 66 | `bloodtype` tinyint(4) unsigned NOT NULL, 67 | `birth_year` year(4) NOT NULL, 68 | `birth_mon` tinyint(2) unsigned NOT NULL, 69 | `birth_day` tinyint(2) unsigned NOT NULL 70 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 71 | ``` 72 | 73 | 表的主键为`('prsn_cat', 'prsn_id')` 74 | 75 | 此表中的`prsn_cat`可能为`"prsn"`或`"crt"`。查询时通过`psrn_cat`和`prsn_id`进行查询 76 | -------------------------------------------------------------------------------- /图片.md: -------------------------------------------------------------------------------- 1 | 数据库中保存了图片的基础路径,类似于 `a6/e8/1_prsn_ZdFfp.jpg?r=1597241889` 2 | 3 | 不同分类,不同尺寸的图片有不同的前缀,前缀+尺寸+图片基础路径拼接成了最终的 HTTP URL 4 | 5 | 人物的图片前缀为 `https://lain.bgm.tv/pic/crt/` 有`l`,`m`,`s`和`g`四种尺寸,一共有四种尺寸的图片 6 | 7 | ```json 8 | { 9 | "images": { 10 | "large": "https://lain.bgm.tv/pic/crt/l/a6/e8/1_prsn_ZdFfp.jpg?r=1597241889", 11 | "medium": "https://lain.bgm.tv/pic/crt/m/a6/e8/1_prsn_ZdFfp.jpg?r=1597241889", 12 | "small": "https://lain.bgm.tv/pic/crt/s/a6/e8/1_prsn_ZdFfp.jpg?r=1597241889", 13 | "grid": "https://lain.bgm.tv/pic/crt/g/a6/e8/1_prsn_ZdFfp.jpg?r=1597241889" 14 | } 15 | } 16 | ``` 17 | 18 | 条目的图片前缀为 `https://lain.bgm.tv/pic/cover/`, 有 `l`,`m`,`s`,`c`和`g`五种尺寸。 19 | 20 | ```json 21 | { 22 | "images": { 23 | "large": "https://lain.bgm.tv/pic/cover/l/a8/7f/4_cMMK5.jpg", 24 | "common": "https://lain.bgm.tv/pic/cover/c/a8/7f/4_cMMK5.jpg", 25 | "medium": "https://lain.bgm.tv/pic/cover/m/a8/7f/4_cMMK5.jpg", 26 | "small": "https://lain.bgm.tv/pic/cover/s/a8/7f/4_cMMK5.jpg", 27 | "grid": "https://lain.bgm.tv/pic/cover/g/a8/7f/4_cMMK5.jpg" 28 | } 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /条目.md: -------------------------------------------------------------------------------- 1 | # 条目 2 | 3 | 条目目前用到的有三个表 (还有`chii_subject_alias`表,但是因为目前没有提供搜索功能,所以没有用到) 4 | 5 | ```sql 6 | CREATE TABLE IF NOT EXISTS `chii_subjects` ( 7 | `subject_id` mediumint(8) unsigned NOT NULL, 8 | `subject_type_id` smallint(6) unsigned NOT NULL DEFAULT '0', 9 | `subject_name` varchar(80) NOT NULL, 10 | `subject_name_cn` varchar(80) NOT NULL, 11 | `subject_uid` varchar(20) NOT NULL COMMENT 'isbn / imdb', 12 | `subject_creator` mediumint(8) unsigned NOT NULL, 13 | `subject_dateline` int(10) unsigned NOT NULL DEFAULT '0', 14 | `subject_image` varchar(255) NOT NULL, 15 | `subject_platform` smallint(6) unsigned NOT NULL DEFAULT '0', 16 | `field_infobox` mediumtext NOT NULL, 17 | `field_summary` mediumtext NOT NULL COMMENT 'summary', 18 | `field_5` mediumtext NOT NULL COMMENT 'author summary', 19 | `field_volumes` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '卷数', 20 | `field_eps` mediumint(8) unsigned NOT NULL DEFAULT '0', 21 | `subject_wish` mediumint(8) unsigned NOT NULL DEFAULT '0', 22 | `subject_collect` mediumint(8) unsigned NOT NULL DEFAULT '0', 23 | `subject_doing` mediumint(8) unsigned NOT NULL DEFAULT '0', 24 | `subject_on_hold` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '搁置人数', 25 | `subject_dropped` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '抛弃人数', 26 | `subject_series` tinyint(1) unsigned NOT NULL DEFAULT '0', 27 | `subject_series_entry` mediumint(8) unsigned NOT NULL DEFAULT '0', 28 | `subject_idx_cn` varchar(1) NOT NULL, 29 | `subject_airtime` tinyint(1) unsigned NOT NULL, 30 | `subject_nsfw` tinyint(1) NOT NULL, 31 | `subject_ban` tinyint(1) unsigned NOT NULL DEFAULT '0' 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 33 | ``` 34 | 35 | 条目主表。 36 | 37 | `subject_series` 和 `subject_series_entry` 用于书籍条目的主系列功能。其他的基本上通过字段名就能判断出来。单行本和系列的信息在条目关联表中也有保存。 38 | 39 | `subject_idx_cn` 是中文名的第一个字的拼音首字母。 40 | 41 | ```sql 42 | CREATE TABLE IF NOT EXISTS `chii_subject_fields` ( 43 | `field_sid` mediumint(8) unsigned NOT NULL, 44 | `field_tid` smallint(6) unsigned NOT NULL DEFAULT '0', 45 | `field_tags` mediumtext NOT NULL, 46 | `field_rate_1` mediumint(8) unsigned NOT NULL DEFAULT '0', 47 | `field_rate_2` mediumint(8) unsigned NOT NULL DEFAULT '0', 48 | `field_rate_3` mediumint(8) unsigned NOT NULL DEFAULT '0', 49 | `field_rate_4` mediumint(8) unsigned NOT NULL DEFAULT '0', 50 | `field_rate_5` mediumint(8) unsigned NOT NULL DEFAULT '0', 51 | `field_rate_6` mediumint(8) unsigned NOT NULL DEFAULT '0', 52 | `field_rate_7` mediumint(8) unsigned NOT NULL DEFAULT '0', 53 | `field_rate_8` mediumint(8) unsigned NOT NULL DEFAULT '0', 54 | `field_rate_9` mediumint(8) unsigned NOT NULL DEFAULT '0', 55 | `field_rate_10` mediumint(8) unsigned NOT NULL DEFAULT '0', 56 | `field_airtime` tinyint(1) unsigned NOT NULL, 57 | `field_rank` int(10) unsigned NOT NULL DEFAULT '0', 58 | `field_year` year(4) NOT NULL COMMENT '放送年份', 59 | `field_mon` tinyint(2) NOT NULL COMMENT '放送月份', 60 | `field_week_day` tinyint(1) NOT NULL COMMENT '放送日(星期X)', 61 | `field_date` date NOT NULL COMMENT '放送日期', 62 | `field_redirect` mediumint(8) unsigned NOT NULL DEFAULT '0' 63 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 64 | ``` 65 | 66 | `field_sid` 是条目 id。 67 | 68 | `field_rate_*` 是各个分数的打分人数。目前的最终分数计算为简单地平均值。 69 | 70 | `field_tags` 保存的是 php serlize 序列化过的 tag 信息,大概这样: 71 | 72 | ```python 73 | [ 74 | {"tag_name": Optional[str], "result": int}, 75 | {"tag_name": Optional[str], "result": int}, 76 | ] 77 | ``` 78 | 79 | ```sql 80 | CREATE TABLE IF NOT EXISTS `chii_subject_relations` ( 81 | `rlt_subject_id` mediumint(8) unsigned NOT NULL COMMENT '关联主 ID', 82 | `rlt_subject_type_id` tinyint(3) unsigned NOT NULL, 83 | `rlt_relation_type` smallint(5) unsigned NOT NULL COMMENT '关联类型', 84 | `rlt_related_subject_id` mediumint(8) unsigned NOT NULL COMMENT '关联目标 ID', 85 | `rlt_related_subject_type_id` tinyint(3) unsigned NOT NULL COMMENT '关联目标类型', 86 | `rlt_vice_versa` tinyint(1) unsigned NOT NULL, 87 | `rlt_order` tinyint(3) unsigned NOT NULL COMMENT '关联排序' 88 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='条目关联表'; 89 | ``` 90 | 91 | 对于 `改编` 关联,会 fallback 到对应条目的类型。比如 `动画 改编 书籍` 对应的关联信息为书籍。 92 | 93 | # 章节 94 | 95 | 章节定义在 `chii_episodes` 表中。 96 | 97 | ```sql 98 | CREATE TABLE IF NOT EXISTS `chii_episodes` ( 99 | `ep_id` mediumint(8) unsigned NOT NULL, 100 | `ep_subject_id` mediumint(8) unsigned NOT NULL, 101 | `ep_sort` float unsigned NOT NULL DEFAULT '0', 102 | `ep_type` tinyint(1) unsigned NOT NULL, 103 | `ep_disc` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '碟片数', 104 | `ep_name` varchar(80) NOT NULL, 105 | `ep_name_cn` varchar(80) NOT NULL, 106 | `ep_rate` tinyint(3) NOT NULL, 107 | `ep_duration` varchar(80) NOT NULL, 108 | `ep_airdate` varchar(80) NOT NULL, 109 | `ep_online` mediumtext NOT NULL, 110 | `ep_comment` mediumint(8) unsigned NOT NULL, 111 | `ep_resources` mediumint(8) unsigned NOT NULL, 112 | `ep_desc` mediumtext NOT NULL, 113 | `ep_dateline` int(10) unsigned NOT NULL, 114 | `ep_lastpost` int(10) unsigned NOT NULL, 115 | `ep_lock` tinyint(3) unsigned NOT NULL DEFAULT '0', 116 | `ep_ban` tinyint(3) unsigned NOT NULL DEFAULT '0' 117 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 118 | ``` 119 | 120 | `ep_desc` 章节简介。 121 | 122 | `ep_disc` 仅在此表中出现,为音乐条目的碟片数,条目表中没有总碟片数。 123 | 124 | `ep_online` `ep_resources` 是废弃字段,曾经存相关网站的资源,后来放弃了。 125 | 126 | `ep_ban` 表示章节被锁定,在 api 响应中应当隐藏。 127 | -------------------------------------------------------------------------------- /用户.md: -------------------------------------------------------------------------------- 1 | 用户有几个相关的表: 2 | 3 | ```SQL 4 | CREATE TABLE IF NOT EXISTS chii_members 5 | ( 6 | uid mediumint unsigned auto_increment primary key, 7 | username char(15) charset utf8 default '' not null, 8 | nickname varchar(30) not null, 9 | avatar varchar(255) charset utf8 not null, 10 | groupid smallint(6) unsigned default 0 not null, # 用户权限组 11 | regdate int unsigned default 0 not null, # 注册日期 12 | lastvisit int unsigned default 0 not null, # 最后访问 13 | lastactivity int unsigned default 0 not null, # 最后活动 14 | lastpost int unsigned default 0 not null, # 最后发帖 15 | dateformat char(10) charset utf8 default '' not null, # 没用 16 | timeformat tinyint(1) default 0 not null, # 没用 17 | timeoffset char(4) charset utf8 default '' not null, # 没用 18 | newpm tinyint(1) default 0 not null, 19 | new_notify smallint(6) unsigned default 0 not null comment '新提醒', 20 | sign varchar(255) charset utf8 not null, 21 | constraint username unique (username) 22 | ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; 23 | ``` 24 | 25 | `dateformat` `timeformat`,`timeoffset` 都是废弃字段。 26 | 27 | ```SQL 28 | CREATE TABLE IF NOT EXISTS `chii_oauth_access_tokens` ( 29 | `access_token` varchar(40) COLLATE utf8_unicode_ci NOT NULL, 30 | `client_id` varchar(80) COLLATE utf8_unicode_ci NOT NULL, 31 | `user_id` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL, 32 | `expires` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 33 | `scope` varchar(4000) COLLATE utf8_unicode_ci DEFAULT NULL 34 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 35 | ``` 36 | 37 | `user_id` 记得转成 int 再作为`uid`查询 38 | 39 | 目前数据库中 `scope` 为 null 40 | 41 | 存储具体权限的表 usr_grp_id 为用户表中的 group id 42 | 43 | ```SQL 44 | CREATE TABLE IF NOT EXISTS `chii_usergroup` ( 45 | `usr_grp_id` mediumint(8) unsigned NOT NULL, 46 | `usr_grp_name` varchar(255) CHARACTER SET utf8 NOT NULL, 47 | `usr_grp_perm` mediumtext CHARACTER SET utf8 NOT NULL, 48 | `usr_grp_dateline` int(10) unsigned NOT NULL 49 | ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 50 | ``` 51 | -------------------------------------------------------------------------------- /用户收藏.md: -------------------------------------------------------------------------------- 1 | # 条目收藏 2 | 3 | https://github.com/bangumi/dev-env/blob/master/sql/schema/chii_subject_interests.sql 4 | 5 | ```SQL 6 | CREATE TABLE IF NOT EXISTS `chii_subject_interests` ( 7 | `interest_id` int(10) unsigned NOT NULL, 8 | `interest_uid` mediumint(8) unsigned NOT NULL, 9 | `interest_subject_id` mediumint(8) unsigned NOT NULL, 10 | `interest_subject_type` smallint(6) unsigned NOT NULL DEFAULT '0', 11 | `interest_rate` tinyint(3) unsigned NOT NULL DEFAULT '0', 12 | `interest_type` tinyint(1) unsigned NOT NULL DEFAULT '0', 13 | `interest_has_comment` tinyint(1) unsigned NOT NULL, 14 | `interest_comment` mediumtext NOT NULL, 15 | `interest_tag` mediumtext NOT NULL, 16 | `interest_ep_status` mediumint(8) unsigned NOT NULL DEFAULT '0', 17 | `interest_vol_status` mediumint(8) unsigned NOT NULL COMMENT '卷数', 18 | `interest_wish_dateline` int(10) unsigned NOT NULL, 19 | `interest_doing_dateline` int(10) unsigned NOT NULL, 20 | `interest_collect_dateline` int(10) unsigned NOT NULL, 21 | `interest_on_hold_dateline` int(10) unsigned NOT NULL, 22 | `interest_dropped_dateline` int(10) unsigned NOT NULL, 23 | `interest_lasttouch` int(10) unsigned NOT NULL DEFAULT '0', 24 | `interest_private` tinyint(1) unsigned NOT NULL 25 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 26 | ``` 27 | 28 | # 章节收藏 29 | 30 | https://github.com/bangumi/dev-env/blob/master/sql/schema/chii_ep_status.sql 31 | 32 | ```SQL 33 | CREATE TABLE IF NOT EXISTS `chii_ep_status` ( 34 | `ep_stt_id` mediumint(8) unsigned NOT NULL, 35 | `ep_stt_uid` mediumint(8) unsigned NOT NULL, 36 | `ep_stt_sid` mediumint(8) unsigned NOT NULL, 37 | `ep_stt_on_prg` tinyint(1) unsigned NOT NULL DEFAULT '0', 38 | `ep_stt_status` mediumtext NOT NULL, 39 | `ep_stt_lasttouch` int(10) unsigned NOT NULL 40 | ) ENGINE = MyISAM DEFAULT CHARSET = utf8; 41 | ``` 42 | 43 | `ep_stt_status` 字段经过了 php 序列化。 44 | 45 | 数据结构,解析后的数据结构大约如下:(使用 TypeScript 表示) 46 | 47 | ```golang 48 | type EpisodeID = number 49 | enum EpisodeCollectionType { 50 | watched = 1, // 想看 51 | done = 2, // 看过 52 | dropped = 3, // 抛弃 53 | } 54 | 55 | type EpStatus = { 56 | [episode_id: EpisodeID]: { 57 | eid: string // EpisodeID in string 58 | stat: EpisodeCollectionType 59 | } 60 | } 61 | ``` 62 | 63 | # 人物收藏 64 | 65 | https://github.com/bangumi/dev-env/blob/master/sql/schema/chii_person_collects.sql 66 | 67 | ```SQL 68 | CREATE TABLE IF NOT EXISTS 69 | `chii_person_collects` ( 70 | `prsn_clt_id` MEDIUMINT(8) UNSIGNED NOT NULL, 71 | `prsn_clt_cat` ENUM('prsn', 'crt') NOT NULL, 72 | `prsn_clt_mid` MEDIUMINT(8) UNSIGNED NOT NULL, 73 | `prsn_clt_uid` MEDIUMINT(8) UNSIGNED NOT NULL, 74 | `prsn_clt_dateline` INT(10) UNSIGNED NOT NULL 75 | ) ENGINE = MyISAM DEFAULT CHARSET = utf8 COMMENT = '人物收藏'; 76 | ``` 77 | -------------------------------------------------------------------------------- /编辑历史.md: -------------------------------------------------------------------------------- 1 | # 人物与角色的编辑历史 2 | 3 | ```sql 4 | CREATE TABLE IF NOT EXISTS `chii_rev_history` ( 5 | `rev_id` mediumint(8) unsigned NOT NULL, 6 | `rev_type` tinyint(3) unsigned NOT NULL COMMENT '条目,角色,人物', 7 | `rev_mid` mediumint(8) unsigned NOT NULL COMMENT '对应条目,人物的ID', 8 | `rev_text_id` mediumint(9) unsigned NOT NULL, 9 | `rev_dateline` int(10) unsigned NOT NULL, 10 | `rev_creator` mediumint(8) unsigned NOT NULL, 11 | `rev_edit_summary` varchar(200) COLLATE utf8_unicode_ci NOT NULL 12 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 13 | ``` 14 | `rev_text_id`:编辑信息的`id` 15 | `rev_edit_summary`:编辑注释 16 | `rev_creator`:编辑用户的`id` 17 | `rev_dateline`:编辑时间 18 | 19 | ## 编辑信息 20 | 21 | ```sql 22 | CREATE TABLE IF NOT EXISTS `chii_rev_text` ( 23 | `rev_text_id` mediumint(9) unsigned NOT NULL, 24 | `rev_text` mediumblob NOT NULL 25 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 26 | ``` 27 | 28 | `rev_text`:经`DEFLATE`算法压缩的`PHP`序列化的字符串,解序列化后为以`rev_id`为`key`,人物与角色各字段的更新数据为`value`的`Map` 29 | 30 | # 条目编辑历史 31 | 32 | ```sql 33 | CREATE TABLE IF NOT EXISTS `chii_subject_revisions` ( 34 | `rev_id` mediumint(8) unsigned NOT NULL, 35 | `rev_type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '修订类型', 36 | `rev_subject_id` mediumint(8) unsigned NOT NULL, 37 | `rev_type_id` smallint(6) unsigned NOT NULL DEFAULT '0', 38 | `rev_creator` mediumint(8) unsigned NOT NULL, 39 | `rev_dateline` int(10) unsigned NOT NULL DEFAULT '0', 40 | `rev_name` varchar(80) NOT NULL, 41 | `rev_name_cn` varchar(80) NOT NULL, 42 | `rev_field_infobox` mediumtext NOT NULL, 43 | `rev_field_summary` mediumtext NOT NULL, 44 | `rev_vote_field` mediumtext NOT NULL, 45 | `rev_field_eps` mediumint(8) unsigned NOT NULL, 46 | `rev_edit_summary` varchar(200) NOT NULL, 47 | `rev_platform` smallint(6) unsigned NOT NULL 48 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 49 | ``` 50 | 51 | `rev_type_id`:条目类型 52 | `rev_field_summary`:条目概述 53 | `rev_field_infobox`:[`Infobox`格式](https://en.wikipedia.org/wiki/Infobox)的条目信息 -------------------------------------------------------------------------------- /角色.md: -------------------------------------------------------------------------------- 1 | ## 基础信息 2 | 3 | ```sql 4 | CREATE TABLE IF NOT EXISTS `chii_characters` ( 5 | `crt_id` mediumint(8) unsigned NOT NULL, 6 | `crt_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 7 | `crt_role` tinyint(4) unsigned NOT NULL COMMENT '角色,机体,组织。。', 8 | `crt_infobox` mediumtext COLLATE utf8_unicode_ci NOT NULL, 9 | `crt_summary` mediumtext COLLATE utf8_unicode_ci NOT NULL, 10 | `crt_img` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 11 | `crt_comment` mediumint(9) unsigned NOT NULL DEFAULT '0', 12 | `crt_collects` mediumint(8) unsigned NOT NULL, 13 | `crt_dateline` int(10) unsigned NOT NULL, 14 | `crt_lastpost` int(11) unsigned NOT NULL, 15 | `crt_lock` tinyint(4) NOT NULL DEFAULT '0', 16 | `crt_img_anidb` varchar(255) CHARACTER SET utf8 NOT NULL, 17 | `crt_anidb_id` mediumint(8) unsigned NOT NULL, 18 | `crt_ban` tinyint(3) unsigned NOT NULL DEFAULT '0', 19 | `crt_redirect` int(10) unsigned NOT NULL DEFAULT '0', 20 | `crt_nsfw` tinyint(1) unsigned NOT NULL 21 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 22 | ``` 23 | 24 | 角色主表 25 | 26 | `crt_img_anidb` 为废弃字段。 27 | 28 | `crt_lastpost` 为最近的用户评论日期。 29 | 30 | ## 关联条目 31 | 32 | 角色参与的条目在`chii_crt_subject_index`表中。 33 | 34 | ```sql 35 | CREATE TABLE IF NOT EXISTS `chii_crt_subject_index` ( 36 | `crt_id` mediumint(9) unsigned NOT NULL, 37 | `subject_id` mediumint(9) unsigned NOT NULL, 38 | `subject_type_id` tinyint(4) unsigned NOT NULL, 39 | `crt_type` tinyint(4) unsigned NOT NULL COMMENT '主角,配角', 40 | `ctr_appear_eps` mediumtext COLLATE utf8_unicode_ci NOT NULL COMMENT '可选,角色出场的的章节', 41 | `crt_order` tinyint(3) unsigned NOT NULL 42 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 43 | ``` 44 | 45 | `ctr_appear_eps` 目前为空,没用到。 46 | 47 | `crt_type` 只有三种,跟条目类型无关。 48 | 49 | ```php 50 | $typeList = array( 51 | 1 => '主角', 52 | 2 => '配角', 53 | 3 => '客串', 54 | ); 55 | ``` 56 | 57 | ## 额外字段 58 | 59 | `chii_person_fields`表为现实人物和虚拟角色的 wiki 解析字段。 60 | 61 | ```sql 62 | CREATE TABLE IF NOT EXISTS `chii_person_fields` ( 63 | `prsn_cat` enum('prsn','crt') COLLATE utf8_unicode_ci NOT NULL, 64 | `prsn_id` int(8) unsigned NOT NULL, 65 | `gender` tinyint(4) unsigned NOT NULL, 66 | `bloodtype` tinyint(4) unsigned NOT NULL, 67 | `birth_year` year(4) NOT NULL, 68 | `birth_mon` tinyint(2) unsigned NOT NULL, 69 | `birth_day` tinyint(2) unsigned NOT NULL 70 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 71 | ``` 72 | 73 | 表的主键为`('prsn_cat', 'prsn_id')` 74 | 75 | 此表中的`prsn_cat`可能为`"prsn"`或`"crt"`。查询时通过`psrn_cat`和`prsn_id`进行查询。查询角色信息的时候使用`prsn_cat = "crt"` 76 | -------------------------------------------------------------------------------- /讨论贴.md: -------------------------------------------------------------------------------- 1 | 以小组为例,条目讨论贴和小组评论几乎相同。 2 | 3 | 小组帖子: 4 | 5 | ```sql 6 | CREATE TABLE IF NOT EXISTS `chii_group_topics` ( 7 | `grp_tpc_id` MEDIUMINT(8) UNSIGNED NOT NULL, 8 | `grp_tpc_gid` MEDIUMINT(8) UNSIGNED NOT NULL, 9 | `grp_tpc_uid` MEDIUMINT(8) UNSIGNED NOT NULL, 10 | `grp_tpc_title` VARCHAR(80) NOT NULL, 11 | `grp_tpc_dateline` INT(10) UNSIGNED NOT NULL DEFAULT '0', 12 | `grp_tpc_lastpost` INT(10) UNSIGNED NOT NULL DEFAULT '0', 13 | `grp_tpc_replies` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', 14 | `grp_tpc_state` TINYINT(1) UNSIGNED NOT NULL, 15 | `grp_tpc_display` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' 16 | ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; 17 | ``` 18 | 19 | ```sql 20 | CREATE TABLE IF NOT EXISTS `chii_group_posts` ( 21 | `grp_pst_id` MEDIUMINT(8) UNSIGNED NOT NULL, 22 | `grp_pst_mid` MEDIUMINT(8) UNSIGNED NOT NULL, 23 | `grp_pst_uid` MEDIUMINT(8) UNSIGNED NOT NULL, 24 | `grp_pst_related` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' COMMENT '关联回复ID', 25 | `grp_pst_content` MEDIUMTEXT NOT NULL, 26 | `grp_pst_state` TINYINT(1) UNSIGNED NOT NULL, 27 | `grp_pst_dateline` INT(10) UNSIGNED NOT NULL DEFAULT '0' 28 | ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; 29 | ``` 30 | 31 | `_tpc_state` 是一个 enum,不一定是用户评论,可能是管理员操作了 32 | 33 | ``` 34 | StateNone = 0 // 正常 35 | StateClosed = 1 // 管理员关闭主题 https://bgm.tv/subject/topic/12629#post_108127 36 | StateReopen = 2 // 重开 37 | StatePin = 3 // 置顶 38 | StateMerge = 4 // 合并 39 | StateSilent = 5 // 管理员下沉主题 https://bgm.tv/subject/topic/18784#post_160402 40 | StateDelete = 6 // 自行删除 41 | StatePrivate = 7 // 管理员删除 42 | ``` 43 | 44 | 管理员的 `1` `5` 操作会添加一条相同 state 的评论,同时把帖子的 `grp_tpc_state` 设置为对应的值。 45 | 46 | `grp_pst_mid` 是帖子的 id。 47 | 48 | `grp_pst_related` 决定帖子是否二级回复。 49 | --------------------------------------------------------------------------------