@dsh-plugin/dsh-synapse 0.1.0-dev.41044228975 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -661
- package/README.md +0 -14
- package/package.json +1 -1
- package/vendor/gugle-chat-bot/LICENSE +661 -661
- package/vendor/gugle-chat-bot/package.json +57 -57
- package/vendor/gugle-chat-bot/src/allow-rule.yml +9345 -9345
- package/vendor/gugle-chat-bot/src/api.json +4284 -4284
- package/vendor/gugle-chat-bot/src/command/index.ts +141 -141
- package/vendor/gugle-chat-bot/src/config/features.ts +547 -547
- package/vendor/gugle-chat-bot/src/config/index.ts +184 -184
- package/vendor/gugle-chat-bot/src/config/manager.ts +356 -356
- package/vendor/gugle-chat-bot/src/constants/index.ts +13 -13
- package/vendor/gugle-chat-bot/src/custom.ts +548 -548
- package/vendor/gugle-chat-bot/src/event/index.ts +118 -118
- package/vendor/gugle-chat-bot/src/features/admin/index.ts +414 -414
- package/vendor/gugle-chat-bot/src/features/bili/image/impl/video.ts +39 -39
- package/vendor/gugle-chat-bot/src/features/bili/image/index.ts +37 -37
- package/vendor/gugle-chat-bot/src/features/bili/index.ts +65 -65
- package/vendor/gugle-chat-bot/src/features/bili/template/style/video.css +97 -97
- package/vendor/gugle-chat-bot/src/features/bili/template/video.html +56 -56
- package/vendor/gugle-chat-bot/src/features/discord-bridge/index.ts +1128 -1128
- package/vendor/gugle-chat-bot/src/features/discord-bridge/markdown.ts +105 -105
- package/vendor/gugle-chat-bot/src/features/discord-bridge/slash.ts +355 -355
- package/vendor/gugle-chat-bot/src/features/discord-bridge/source.ts +96 -96
- package/vendor/gugle-chat-bot/src/features/discord-bridge/template/message.html +14 -14
- package/vendor/gugle-chat-bot/src/features/discord-bridge/template/style/message.css +144 -144
- package/vendor/gugle-chat-bot/src/features/github/api.ts +93 -93
- package/vendor/gugle-chat-bot/src/features/github/binding.ts +161 -161
- package/vendor/gugle-chat-bot/src/features/github/image/impl/issue.ts +132 -132
- package/vendor/gugle-chat-bot/src/features/github/image/impl/pr.ts +144 -144
- package/vendor/gugle-chat-bot/src/features/github/image/impl/release.ts +160 -160
- package/vendor/gugle-chat-bot/src/features/github/image/index.ts +310 -310
- package/vendor/gugle-chat-bot/src/features/github/index.ts +302 -302
- package/vendor/gugle-chat-bot/src/features/github/template/issue.html +118 -118
- package/vendor/gugle-chat-bot/src/features/github/template/pull_request.html +125 -125
- package/vendor/gugle-chat-bot/src/features/github/template/release.html +53 -53
- package/vendor/gugle-chat-bot/src/features/github/template/style/issue.css +468 -468
- package/vendor/gugle-chat-bot/src/features/github/template/style/pull_request.css +468 -468
- package/vendor/gugle-chat-bot/src/features/github/template/style/release.css +412 -412
- package/vendor/gugle-chat-bot/src/features/hermes/client.ts +184 -184
- package/vendor/gugle-chat-bot/src/features/hermes/config.ts +210 -210
- package/vendor/gugle-chat-bot/src/features/hermes/context.ts +67 -67
- package/vendor/gugle-chat-bot/src/features/hermes/history.ts +86 -86
- package/vendor/gugle-chat-bot/src/features/hermes/index.ts +1533 -1533
- package/vendor/gugle-chat-bot/src/features/hermes/message.ts +319 -319
- package/vendor/gugle-chat-bot/src/features/hermes/reaction.ts +181 -181
- package/vendor/gugle-chat-bot/src/features/hermes/render.ts +118 -118
- package/vendor/gugle-chat-bot/src/features/hermes/reply-units.ts +331 -331
- package/vendor/gugle-chat-bot/src/features/hermes/skills.ts +406 -406
- package/vendor/gugle-chat-bot/src/features/hermes/template/approval.html +30 -30
- package/vendor/gugle-chat-bot/src/features/hermes/template/progress.html +21 -21
- package/vendor/gugle-chat-bot/src/features/hermes/template/style/approval.css +81 -81
- package/vendor/gugle-chat-bot/src/features/hermes/template/style/progress.css +120 -120
- package/vendor/gugle-chat-bot/src/features/hermes/trigger.ts +86 -86
- package/vendor/gugle-chat-bot/src/features/hermes/types.ts +327 -327
- package/vendor/gugle-chat-bot/src/features/management/index.ts +156 -156
- package/vendor/gugle-chat-bot/src/features/minecraft/index.ts +127 -127
- package/vendor/gugle-chat-bot/src/features/modrinth/index.ts +71 -71
- package/vendor/gugle-chat-bot/src/features/parentheses/index.ts +117 -117
- package/vendor/gugle-chat-bot/src/features/peak-valley-timer/index.ts +451 -451
- package/vendor/gugle-chat-bot/src/features/poke/index.ts +24 -24
- package/vendor/gugle-chat-bot/src/features/version-tracker/index.ts +77 -77
- package/vendor/gugle-chat-bot/src/features/welcome/index.ts +57 -57
- package/vendor/gugle-chat-bot/src/github-ip.json +5814 -5814
- package/vendor/gugle-chat-bot/src/image/index.ts +278 -278
- package/vendor/gugle-chat-bot/src/index.ts +695 -695
- package/vendor/gugle-chat-bot/src/logger/index.ts +54 -54
- package/vendor/gugle-chat-bot/src/result.json +359 -359
- package/vendor/gugle-chat-bot/src/type/bili.d.ts +825 -825
- package/vendor/gugle-chat-bot/src/type/event.d.ts +146 -146
- package/vendor/gugle-chat-bot/src/type/github.d.ts +446 -446
- package/vendor/gugle-chat-bot/src/type/index.d.ts +254 -254
- package/vendor/gugle-chat-bot/tsconfig.json +46 -46
- package/scripts/dump-npm-latest.mjs +0 -30
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
import { Message as DiscordMessage, PermissionFlagsBits } from 'discord.js';
|
|
2
|
-
import { BotCommandSource } from '@/command';
|
|
3
|
-
import { isDiscordOperator } from '@/config/features';
|
|
4
|
-
import { QQBot } from '@/index';
|
|
5
|
-
|
|
6
|
-
const DISCORD_MESSAGE_LIMIT = 2000;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Discord 侧管理员判定:服务器拥有者、拥有「管理服务器」/「管理员」权限的成员,
|
|
10
|
-
* 或 management.json 里 `discordOperators` 白名单中的用户。
|
|
11
|
-
* 命令源(DiscordMsgCommandSource)与 Hermes AI(审批/技能门控)共用同一口径。
|
|
12
|
-
*/
|
|
13
|
-
export function isDiscordAdmin(message: DiscordMessage): boolean {
|
|
14
|
-
if (isDiscordOperator(message.author.id)) return true;
|
|
15
|
-
if (message.guild?.ownerId === message.author.id) return true;
|
|
16
|
-
const permissions = message.member?.permissions;
|
|
17
|
-
if (!permissions) return false;
|
|
18
|
-
return permissions.has(PermissionFlagsBits.Administrator) || permissions.has(PermissionFlagsBits.ManageGuild);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Discord 频道命令源:让 gugle-command 已注册的全部命令都能在 Discord 频道中执行,
|
|
23
|
-
* 命令回复(success/fail)以 Discord 回复的形式发回原频道。
|
|
24
|
-
*
|
|
25
|
-
* 身份与权限映射:
|
|
26
|
-
* - getUserId() 返回 `dc:<Discord用户ID>`(`dc:` 前缀保证与纯数字 QQ 号不冲突,
|
|
27
|
-
* GitHub 绑定等按用户持久化的数据可安全共用同一套存储);
|
|
28
|
-
* - getGroupId() 返回该频道桥接配置里的 QQ 群号(订阅类命令作用于对应 QQ 群);
|
|
29
|
-
* - isAdmin() / hasPermission():服务器拥有者视为 owner(2),
|
|
30
|
-
* 拥有「管理服务器」或「管理员」权限的成员视为 admin(1),其余为 0。
|
|
31
|
-
*/
|
|
32
|
-
export class DiscordMsgCommandSource implements BotCommandSource {
|
|
33
|
-
private readonly bot: QQBot;
|
|
34
|
-
private readonly message: DiscordMessage;
|
|
35
|
-
private readonly groupId: number | undefined;
|
|
36
|
-
|
|
37
|
-
public constructor(bot: QQBot, message: DiscordMessage, groupId?: number) {
|
|
38
|
-
this.bot = bot;
|
|
39
|
-
this.message = message;
|
|
40
|
-
this.groupId = groupId;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public getUserId(): string {
|
|
44
|
-
return `dc:${this.message.author.id}`;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public getGroupId(): number | undefined {
|
|
48
|
-
return this.groupId;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public isAdmin(): boolean {
|
|
52
|
-
return isDiscordAdmin(this.message);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public success(message: string): void {
|
|
56
|
-
this.reply(message);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public fail(message: string): void {
|
|
60
|
-
this.reply(message);
|
|
61
|
-
this.bot.logger?.error(`[Discord:${this.message.author.username}] ${message}: ${this.message.content}`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public getName(): string {
|
|
65
|
-
return this.message.member?.displayName ?? this.message.author.username;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public hasPermission(permission: string): boolean {
|
|
69
|
-
if (!permission) return true;
|
|
70
|
-
const getPermissionLevel = (text: string): number => {
|
|
71
|
-
const level = Number.parseInt(text);
|
|
72
|
-
if (Number.isNaN(level)) {
|
|
73
|
-
return text === 'owner' ? 2 : text === 'admin' ? 1 : 0;
|
|
74
|
-
}
|
|
75
|
-
return level;
|
|
76
|
-
};
|
|
77
|
-
const isOwner = this.message.guild?.ownerId === this.message.author.id;
|
|
78
|
-
const permissionLevel = isOwner ? 2 : this.isAdmin() ? 1 : 0;
|
|
79
|
-
return permissionLevel >= getPermissionLevel(permission);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** 命令回复发在 Discord 频道(回复原消息,不 @ 人,超长截断) */
|
|
83
|
-
private reply(content: string): void {
|
|
84
|
-
const text =
|
|
85
|
-
content.length <= DISCORD_MESSAGE_LIMIT
|
|
86
|
-
? content
|
|
87
|
-
: `${content.slice(0, DISCORD_MESSAGE_LIMIT - 16)}\n…(消息过长已截断)`;
|
|
88
|
-
this.message
|
|
89
|
-
.reply({ content: text, allowedMentions: { parse: [], repliedUser: false } })
|
|
90
|
-
.catch(error => {
|
|
91
|
-
this.bot.logger?.error(
|
|
92
|
-
`[DiscordBridge] Discord 命令回复失败: ${error instanceof Error ? error.message : String(error)}`
|
|
93
|
-
);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
1
|
+
import { Message as DiscordMessage, PermissionFlagsBits } from 'discord.js';
|
|
2
|
+
import { BotCommandSource } from '@/command';
|
|
3
|
+
import { isDiscordOperator } from '@/config/features';
|
|
4
|
+
import { QQBot } from '@/index';
|
|
5
|
+
|
|
6
|
+
const DISCORD_MESSAGE_LIMIT = 2000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Discord 侧管理员判定:服务器拥有者、拥有「管理服务器」/「管理员」权限的成员,
|
|
10
|
+
* 或 management.json 里 `discordOperators` 白名单中的用户。
|
|
11
|
+
* 命令源(DiscordMsgCommandSource)与 Hermes AI(审批/技能门控)共用同一口径。
|
|
12
|
+
*/
|
|
13
|
+
export function isDiscordAdmin(message: DiscordMessage): boolean {
|
|
14
|
+
if (isDiscordOperator(message.author.id)) return true;
|
|
15
|
+
if (message.guild?.ownerId === message.author.id) return true;
|
|
16
|
+
const permissions = message.member?.permissions;
|
|
17
|
+
if (!permissions) return false;
|
|
18
|
+
return permissions.has(PermissionFlagsBits.Administrator) || permissions.has(PermissionFlagsBits.ManageGuild);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Discord 频道命令源:让 gugle-command 已注册的全部命令都能在 Discord 频道中执行,
|
|
23
|
+
* 命令回复(success/fail)以 Discord 回复的形式发回原频道。
|
|
24
|
+
*
|
|
25
|
+
* 身份与权限映射:
|
|
26
|
+
* - getUserId() 返回 `dc:<Discord用户ID>`(`dc:` 前缀保证与纯数字 QQ 号不冲突,
|
|
27
|
+
* GitHub 绑定等按用户持久化的数据可安全共用同一套存储);
|
|
28
|
+
* - getGroupId() 返回该频道桥接配置里的 QQ 群号(订阅类命令作用于对应 QQ 群);
|
|
29
|
+
* - isAdmin() / hasPermission():服务器拥有者视为 owner(2),
|
|
30
|
+
* 拥有「管理服务器」或「管理员」权限的成员视为 admin(1),其余为 0。
|
|
31
|
+
*/
|
|
32
|
+
export class DiscordMsgCommandSource implements BotCommandSource {
|
|
33
|
+
private readonly bot: QQBot;
|
|
34
|
+
private readonly message: DiscordMessage;
|
|
35
|
+
private readonly groupId: number | undefined;
|
|
36
|
+
|
|
37
|
+
public constructor(bot: QQBot, message: DiscordMessage, groupId?: number) {
|
|
38
|
+
this.bot = bot;
|
|
39
|
+
this.message = message;
|
|
40
|
+
this.groupId = groupId;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public getUserId(): string {
|
|
44
|
+
return `dc:${this.message.author.id}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public getGroupId(): number | undefined {
|
|
48
|
+
return this.groupId;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public isAdmin(): boolean {
|
|
52
|
+
return isDiscordAdmin(this.message);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public success(message: string): void {
|
|
56
|
+
this.reply(message);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public fail(message: string): void {
|
|
60
|
+
this.reply(message);
|
|
61
|
+
this.bot.logger?.error(`[Discord:${this.message.author.username}] ${message}: ${this.message.content}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public getName(): string {
|
|
65
|
+
return this.message.member?.displayName ?? this.message.author.username;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public hasPermission(permission: string): boolean {
|
|
69
|
+
if (!permission) return true;
|
|
70
|
+
const getPermissionLevel = (text: string): number => {
|
|
71
|
+
const level = Number.parseInt(text);
|
|
72
|
+
if (Number.isNaN(level)) {
|
|
73
|
+
return text === 'owner' ? 2 : text === 'admin' ? 1 : 0;
|
|
74
|
+
}
|
|
75
|
+
return level;
|
|
76
|
+
};
|
|
77
|
+
const isOwner = this.message.guild?.ownerId === this.message.author.id;
|
|
78
|
+
const permissionLevel = isOwner ? 2 : this.isAdmin() ? 1 : 0;
|
|
79
|
+
return permissionLevel >= getPermissionLevel(permission);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** 命令回复发在 Discord 频道(回复原消息,不 @ 人,超长截断) */
|
|
83
|
+
private reply(content: string): void {
|
|
84
|
+
const text =
|
|
85
|
+
content.length <= DISCORD_MESSAGE_LIMIT
|
|
86
|
+
? content
|
|
87
|
+
: `${content.slice(0, DISCORD_MESSAGE_LIMIT - 16)}\n…(消息过长已截断)`;
|
|
88
|
+
this.message
|
|
89
|
+
.reply({ content: text, allowedMentions: { parse: [], repliedUser: false } })
|
|
90
|
+
.catch(error => {
|
|
91
|
+
this.bot.logger?.error(
|
|
92
|
+
`[DiscordBridge] Discord 命令回复失败: ${error instanceof Error ? error.message : String(error)}`
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="zh">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>{{header}}</title>
|
|
6
|
-
<link rel="stylesheet" href="./style/message.css">
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div class="container">
|
|
10
|
-
<div class="header">{{header}}</div>
|
|
11
|
-
<div class="content">{{content}}</div>
|
|
12
|
-
</div>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>{{header}}</title>
|
|
6
|
+
<link rel="stylesheet" href="./style/message.css">
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div class="container">
|
|
10
|
+
<div class="header">{{header}}</div>
|
|
11
|
+
<div class="content">{{content}}</div>
|
|
12
|
+
</div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -1,144 +1,144 @@
|
|
|
1
|
-
* {
|
|
2
|
-
margin: 0;
|
|
3
|
-
padding: 0;
|
|
4
|
-
box-sizing: border-box;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
body {
|
|
8
|
-
background: #313338;
|
|
9
|
-
color: #dbdee1;
|
|
10
|
-
font-family: "Segoe UI", "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", sans-serif;
|
|
11
|
-
font-size: 15px;
|
|
12
|
-
line-height: 1.45;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.container {
|
|
16
|
-
width: 640px;
|
|
17
|
-
padding: 16px 20px;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.header {
|
|
21
|
-
color: #949ba4;
|
|
22
|
-
font-size: 13px;
|
|
23
|
-
font-weight: 600;
|
|
24
|
-
margin-bottom: 8px;
|
|
25
|
-
padding-bottom: 8px;
|
|
26
|
-
border-bottom: 1px solid #3f4147;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.content {
|
|
30
|
-
word-wrap: break-word;
|
|
31
|
-
overflow-wrap: anywhere;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.content p {
|
|
35
|
-
margin: 4px 0;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.content h1,
|
|
39
|
-
.content h2,
|
|
40
|
-
.content h3 {
|
|
41
|
-
color: #f2f3f5;
|
|
42
|
-
margin: 10px 0 4px;
|
|
43
|
-
line-height: 1.3;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.content h1 {
|
|
47
|
-
font-size: 22px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.content h2 {
|
|
51
|
-
font-size: 19px;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.content h3 {
|
|
55
|
-
font-size: 16px;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.content code {
|
|
59
|
-
background: #1e1f22;
|
|
60
|
-
border-radius: 4px;
|
|
61
|
-
padding: 1px 4px;
|
|
62
|
-
font-family: Consolas, "Courier New", monospace;
|
|
63
|
-
font-size: 13px;
|
|
64
|
-
color: #e3e5e8;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.content pre {
|
|
68
|
-
background: #1e1f22;
|
|
69
|
-
border: 1px solid #2b2d31;
|
|
70
|
-
border-radius: 6px;
|
|
71
|
-
padding: 10px 12px;
|
|
72
|
-
margin: 6px 0;
|
|
73
|
-
overflow-x: auto;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.content pre code {
|
|
77
|
-
background: transparent;
|
|
78
|
-
padding: 0;
|
|
79
|
-
white-space: pre;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.content blockquote {
|
|
83
|
-
border-left: 4px solid #4e5058;
|
|
84
|
-
padding-left: 12px;
|
|
85
|
-
margin: 6px 0;
|
|
86
|
-
color: #b5bac1;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.content ul,
|
|
90
|
-
.content ol {
|
|
91
|
-
padding-left: 24px;
|
|
92
|
-
margin: 4px 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.content a {
|
|
96
|
-
color: #00a8fc;
|
|
97
|
-
text-decoration: none;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.content a:hover {
|
|
101
|
-
text-decoration: underline;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.content img {
|
|
105
|
-
max-width: 100%;
|
|
106
|
-
border-radius: 4px;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.content hr {
|
|
110
|
-
border: none;
|
|
111
|
-
border-top: 1px solid #3f4147;
|
|
112
|
-
margin: 10px 0;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.content table {
|
|
116
|
-
border-collapse: collapse;
|
|
117
|
-
margin: 6px 0;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.content th,
|
|
121
|
-
.content td {
|
|
122
|
-
border: 1px solid #4e5058;
|
|
123
|
-
padding: 4px 10px;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.mention {
|
|
127
|
-
color: #c9cdfb;
|
|
128
|
-
background: rgba(88, 101, 242, 0.3);
|
|
129
|
-
border-radius: 3px;
|
|
130
|
-
padding: 0 2px;
|
|
131
|
-
font-weight: 500;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.spoiler {
|
|
135
|
-
background: #1e1f22;
|
|
136
|
-
color: #1e1f22;
|
|
137
|
-
border-radius: 4px;
|
|
138
|
-
padding: 0 4px;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.emoji {
|
|
142
|
-
height: 1.2em;
|
|
143
|
-
vertical-align: -0.2em;
|
|
144
|
-
}
|
|
1
|
+
* {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body {
|
|
8
|
+
background: #313338;
|
|
9
|
+
color: #dbdee1;
|
|
10
|
+
font-family: "Segoe UI", "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", sans-serif;
|
|
11
|
+
font-size: 15px;
|
|
12
|
+
line-height: 1.45;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.container {
|
|
16
|
+
width: 640px;
|
|
17
|
+
padding: 16px 20px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.header {
|
|
21
|
+
color: #949ba4;
|
|
22
|
+
font-size: 13px;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
margin-bottom: 8px;
|
|
25
|
+
padding-bottom: 8px;
|
|
26
|
+
border-bottom: 1px solid #3f4147;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.content {
|
|
30
|
+
word-wrap: break-word;
|
|
31
|
+
overflow-wrap: anywhere;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content p {
|
|
35
|
+
margin: 4px 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.content h1,
|
|
39
|
+
.content h2,
|
|
40
|
+
.content h3 {
|
|
41
|
+
color: #f2f3f5;
|
|
42
|
+
margin: 10px 0 4px;
|
|
43
|
+
line-height: 1.3;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.content h1 {
|
|
47
|
+
font-size: 22px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.content h2 {
|
|
51
|
+
font-size: 19px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.content h3 {
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.content code {
|
|
59
|
+
background: #1e1f22;
|
|
60
|
+
border-radius: 4px;
|
|
61
|
+
padding: 1px 4px;
|
|
62
|
+
font-family: Consolas, "Courier New", monospace;
|
|
63
|
+
font-size: 13px;
|
|
64
|
+
color: #e3e5e8;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.content pre {
|
|
68
|
+
background: #1e1f22;
|
|
69
|
+
border: 1px solid #2b2d31;
|
|
70
|
+
border-radius: 6px;
|
|
71
|
+
padding: 10px 12px;
|
|
72
|
+
margin: 6px 0;
|
|
73
|
+
overflow-x: auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.content pre code {
|
|
77
|
+
background: transparent;
|
|
78
|
+
padding: 0;
|
|
79
|
+
white-space: pre;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.content blockquote {
|
|
83
|
+
border-left: 4px solid #4e5058;
|
|
84
|
+
padding-left: 12px;
|
|
85
|
+
margin: 6px 0;
|
|
86
|
+
color: #b5bac1;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.content ul,
|
|
90
|
+
.content ol {
|
|
91
|
+
padding-left: 24px;
|
|
92
|
+
margin: 4px 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.content a {
|
|
96
|
+
color: #00a8fc;
|
|
97
|
+
text-decoration: none;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.content a:hover {
|
|
101
|
+
text-decoration: underline;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.content img {
|
|
105
|
+
max-width: 100%;
|
|
106
|
+
border-radius: 4px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.content hr {
|
|
110
|
+
border: none;
|
|
111
|
+
border-top: 1px solid #3f4147;
|
|
112
|
+
margin: 10px 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.content table {
|
|
116
|
+
border-collapse: collapse;
|
|
117
|
+
margin: 6px 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.content th,
|
|
121
|
+
.content td {
|
|
122
|
+
border: 1px solid #4e5058;
|
|
123
|
+
padding: 4px 10px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.mention {
|
|
127
|
+
color: #c9cdfb;
|
|
128
|
+
background: rgba(88, 101, 242, 0.3);
|
|
129
|
+
border-radius: 3px;
|
|
130
|
+
padding: 0 2px;
|
|
131
|
+
font-weight: 500;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.spoiler {
|
|
135
|
+
background: #1e1f22;
|
|
136
|
+
color: #1e1f22;
|
|
137
|
+
border-radius: 4px;
|
|
138
|
+
padding: 0 4px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.emoji {
|
|
142
|
+
height: 1.2em;
|
|
143
|
+
vertical-align: -0.2em;
|
|
144
|
+
}
|