Skip to content

Commit 6fcbf5f

Browse files
zcoderrclaude
andcommitted
feat: replace avatar pool config with local avatar files and update illustrations
- Remove avatars.pool config from env.ts, use randomAvatarUrl() from local avatar images - Add 10 avatar images and blender-rendered report images - Update all 12 zodiac daily illustrations to higher resolution - Add daily-scribe API docs and blender image download script Co-authored-by: Claude <noreply@anthropic.com>
1 parent ef5f2fe commit 6fcbf5f

211 files changed

Lines changed: 1087 additions & 19 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/src/libs/env.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -482,22 +482,6 @@ function parseConfigFromPreferences() {
482482
return this._database;
483483
},
484484

485-
avatars: {
486-
_pool: undefined as string[] | undefined,
487-
get pool() {
488-
if (!this._pool) {
489-
const old = tryParse(process.env.AVATARS_POOL);
490-
const { error, value } = Joi.array<string[]>()
491-
.items(Joi.string())
492-
.required()
493-
.validate((preferences.avatars_pool || old?.join('\n') || '').split(/\s+/).filter(Boolean));
494-
if (error) throw new Error(`validate avatars pool configuration error: ${error.message}`);
495-
this._pool = value;
496-
}
497-
return this._pool;
498-
},
499-
},
500-
501485
_predictReportTemplate: undefined as ReturnType<typeof parseReportTemplateConfiguration> | undefined,
502486
get predictReportTemplate() {
503487
if (!this._predictReportTemplate) {

api/src/routes/ai/handlers/auth.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { omit, sample } from 'lodash';
1+
import { omit } from 'lodash';
22
import { Op } from 'sequelize';
33

4+
import { randomAvatarUrl } from '../../../ai/image';
45
import { authService, generateUserDid, getAppleUserInfo, getGoogleUserInfo } from '../../../libs/auth';
5-
import { config } from '../../../libs/env';
66
import Message, { MessageType } from '../../../store/models/message';
77
import User from '../../../store/models/user';
88
import { getTranslation } from '../translations';
@@ -25,7 +25,7 @@ export const handleLogin: ChatHandle<MessageType.Login> = async ({ stream, userI
2525
: await getGoogleUserInfo(googleIdToken)
2626
: await getAppleUserInfo(appleIdToken);
2727

28-
const avatar = thirdUser.avatar || sample(config.avatars.pool);
28+
const avatar = thirdUser.avatar || randomAvatarUrl();
2929

3030
const username =
3131
thirdUser.name || thirdUser.email?.split('@')[0] || `User-${Math.random().toString(36).slice(2, 10)}`;

docs/daily-scribe-api.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Daily Scribe API
2+
3+
每日运势 / 年度运势内容 API,为 12 个星座提供 AI 生成的多语言运势内容。
4+
5+
## 基础信息
6+
7+
- **基础路径**: `/api/daily`
8+
- **兼容路径**: `/daily/api`(通过 Blocklet Server rewrite 转发,兼容旧客户端)
9+
- **内容生成**: 每天 UTC 00:00 由 cron 自动为 12 个星座生成;首次请求未生成的内容时也会触发按需生成
10+
11+
## 星座列表
12+
13+
| key | 名称 | 符号 | 日期范围 |
14+
|-----|------|------|----------|
15+
| `aquarius` | Aquarius || 01-21 ~ 02-19 |
16+
| `pisces` | Pisces || 02-20 ~ 03-20 |
17+
| `aries` | Aries || 03-21 ~ 04-19 |
18+
| `taurus` | Taurus || 04-20 ~ 05-20 |
19+
| `gemini` | Gemini || 05-21 ~ 06-21 |
20+
| `cancer` | Cancer || 06-22 ~ 07-22 |
21+
| `leo` | Leo || 07-23 ~ 08-22 |
22+
| `virgo` | Virgo || 08-23 ~ 09-22 |
23+
| `libra` | Libra || 09-23 ~ 10-23 |
24+
| `scorpio` | Scorpio || 10-24 ~ 11-21 |
25+
| `sagittarius` | Sagittarius || 11-22 ~ 12-20 |
26+
| `capricorn` | Capricorn || 12-21 ~ 01-20 |
27+
28+
## 支持的语言
29+
30+
| locale | 语言 |
31+
|--------|------|
32+
| `en` | English |
33+
| `zh` | 简体中文 |
34+
| `zh-t` | 繁體中文 |
35+
| `ja` | 日本語 |
36+
37+
---
38+
39+
## API 端点
40+
41+
### 1. 获取每日运势
42+
43+
```
44+
GET /api/daily/content/:key
45+
```
46+
47+
**权限**: 公开,无需认证
48+
49+
**路径参数**:
50+
51+
| 参数 | 类型 | 必填 | 说明 |
52+
|------|------|------|------|
53+
| `key` | string || 星座标识,如 `aries``leo` |
54+
55+
**Query 参数**:
56+
57+
| 参数 | 类型 | 必填 | 说明 |
58+
|------|------|------|------|
59+
| `locale` | string || 语言代码,默认从 cookie `nf_lang` 读取,兜底 `en` |
60+
| `date` | string || 日期 `YYYY-MM-DD`,不传则获取最新记录 |
61+
62+
**成功响应** (200):
63+
64+
```json
65+
{
66+
"code": 0,
67+
"msg": "get content success",
68+
"data": {
69+
"id": "694073960970584064",
70+
"createdAt": "2026-03-31T06:42:07.566Z",
71+
"updatedAt": "2026-03-31T06:42:07.566Z",
72+
"title": "在自我与和谐之间,找寻平衡的力量",
73+
"content": "在坚守个性的同时拥抱合作,将一时的冲动转化为深邃的智慧。",
74+
"pageKey": "aries",
75+
"bg": "https://xxx.did.abtnet.io/aistro/daily/bg/aries.png",
76+
"smallBg": "https://xxx.did.abtnet.io/aistro/daily/small-bg/aries.png",
77+
"locale": "zh",
78+
"illustration": "https://xxx.did.abtnet.io/aistro/daily/illustration/aries.png",
79+
"date": "2026-03-31",
80+
"horoscope": "勇敢的白羊座,随着太阳继续在你的星座展开...",
81+
"symbol": "",
82+
"star": "Aries"
83+
}
84+
}
85+
```
86+
87+
**失败响应** (200):
88+
89+
```json
90+
{
91+
"code": 1,
92+
"msg": "get content fail"
93+
}
94+
```
95+
96+
**行为说明**:
97+
- 数据库已有记录 → 直接返回(毫秒级)
98+
- 数据库无记录 → 触发 AI 生成,每 5 秒轮询一次,最多等待 60 秒
99+
- 超时仍未生成 → 返回 `code: 1`
100+
101+
**curl 示例**:
102+
103+
```bash
104+
curl "https://xxx.did.abtnet.io/aistro/api/daily/content/aries?locale=zh"
105+
curl "https://xxx.did.abtnet.io/aistro/api/daily/content/leo?locale=en&date=2026-03-31"
106+
```
107+
108+
---
109+
110+
### 2. 获取年度运势
111+
112+
```
113+
GET /api/daily/content/year/:key
114+
```
115+
116+
**权限**: 公开,无需认证
117+
118+
**路径参数**:
119+
120+
| 参数 | 类型 | 必填 | 说明 |
121+
|------|------|------|------|
122+
| `key` | string || 星座标识 |
123+
124+
**Query 参数**:
125+
126+
| 参数 | 类型 | 必填 | 说明 |
127+
|------|------|------|------|
128+
| `locale` | string || 语言代码,默认 `en` |
129+
| `year` | string || 年份 `YYYY`,不传则获取最新记录 |
130+
131+
**响应**: 结构与每日运势相同,`date` 字段替换为 `year`
132+
133+
**curl 示例**:
134+
135+
```bash
136+
curl "https://xxx.did.abtnet.io/aistro/api/daily/content/year/aries?locale=zh"
137+
curl "https://xxx.did.abtnet.io/aistro/api/daily/content/year/leo?locale=ja&year=2026"
138+
```
139+
140+
---
141+
142+
### 3. 重新生成每日运势
143+
144+
```
145+
GET /api/daily/regenerate-content/:key
146+
```
147+
148+
**权限**: 需要 `admin``owner` 角色
149+
150+
**路径参数**:
151+
152+
| 参数 | 类型 | 必填 | 说明 |
153+
|------|------|------|------|
154+
| `key` | string || 星座标识 |
155+
156+
**Query 参数**:
157+
158+
| 参数 | 类型 | 必填 | 说明 |
159+
|------|------|------|------|
160+
| `locale` | string || 语言代码 |
161+
| `date` | string || 日期 `YYYY-MM-DD` |
162+
163+
**行为说明**:
164+
1. 删除该星座该日期的任务标记(Task Flag)
165+
2. 删除该星座该日期的所有语言记录
166+
3. 重新触发 AI 生成并返回新内容
167+
168+
**curl 示例**:
169+
170+
```bash
171+
curl "https://xxx.did.abtnet.io/aistro/api/daily/regenerate-content/aries?date=2026-03-31&locale=zh"
172+
```
173+
174+
---
175+
176+
### 4. 重新生成年度运势
177+
178+
```
179+
GET /api/daily/regenerate-content/year/:key
180+
```
181+
182+
**权限**: 需要 `admin``owner` 角色
183+
184+
**路径参数**:
185+
186+
| 参数 | 类型 | 必填 | 说明 |
187+
|------|------|------|------|
188+
| `key` | string || 星座标识 |
189+
190+
**Query 参数**:
191+
192+
| 参数 | 类型 | 必填 | 说明 |
193+
|------|------|------|------|
194+
| `locale` | string || 语言代码 |
195+
| `year` | string || 年份 `YYYY` |
196+
197+
**curl 示例**:
198+
199+
```bash
200+
curl "https://xxx.did.abtnet.io/aistro/api/daily/regenerate-content/year/aries?year=2026&locale=zh"
201+
```
202+
203+
---
204+
205+
## 响应字段说明
206+
207+
| 字段 | 类型 | 说明 |
208+
|------|------|------|
209+
| `id` | string | 记录唯一 ID |
210+
| `title` | string | AI 生成的标题(对应 locale 语言) |
211+
| `content` | string | AI 生成的短文(1-3 句话的每日座右铭) |
212+
| `pageKey` | string | 星座标识 |
213+
| `bg` | string | 大背景图完整 URL(540px) |
214+
| `smallBg` | string | 小背景图完整 URL(200px) |
215+
| `illustration` | string | 插图完整 URL(540px) |
216+
| `locale` | string | 语言代码 |
217+
| `date` / `year` | string | 日期 `YYYY-MM-DD` 或年份 `YYYY` |
218+
| `horoscope` | string | AI 生成的详细运势文本(对应 locale 语言) |
219+
| `symbol` | string | 星座符号(如 ♈) |
220+
| `star` | string | 星座英文名(如 Aries) |
221+
222+
## 旧客户端兼容
223+
224+
通过 Blocklet Server URL rewrite 规则 `daily/* → aistro/daily/*`,旧客户端的请求路径无需修改:
225+
226+
| 旧路径 | 实际转发到 |
227+
|--------|-----------|
228+
| `daily/api/content/:key` | `aistro/daily/api/content/:key` |
229+
| `daily/api/content/year/:key` | `aistro/daily/api/content/year/:key` |
230+
| `daily/api/regenerate-content/:key` | `aistro/daily/api/regenerate-content/:key` |
231+
| `daily/api/regenerate-content/year/:key` | `aistro/daily/api/regenerate-content/year/:key` |
232+
233+
服务端同时挂载了 `/api/daily/*`(新路径)和 `/daily/api/*`(兼容路径),两者指向同一个 handler。

0 commit comments

Comments
 (0)