Skip to content

Commit 039af9a

Browse files
committed
Merge remote-tracking branch 'origin/main' into copilot/fix-83
2 parents 26e37e6 + e6d4a5a commit 039af9a

File tree

9 files changed

+743
-587
lines changed

9 files changed

+743
-587
lines changed

.github/scripts/deno.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"nodeModulesDir": "none"
3+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { components } from 'npm:@octokit/openapi-types';
2+
import { stdin } from 'npm:zx';
3+
4+
type GitHubSchema = components['schemas'];
5+
6+
type GitHubUser = GitHubSchema['simple-user'];
7+
8+
interface GitHubAction
9+
extends Record<'event_name' | 'actor' | 'server_url' | 'repository', string> {
10+
action?: string;
11+
ref?: string;
12+
ref_name?: string;
13+
event: {
14+
head_commit?: GitHubSchema['git-commit'];
15+
issue?: GitHubSchema['webhook-issues-opened']['issue'];
16+
pull_request?: GitHubSchema['pull-request'];
17+
discussion?: GitHubSchema['discussion'];
18+
comment?: GitHubSchema['issue-comment'];
19+
release?: GitHubSchema['release'];
20+
};
21+
}
22+
23+
// Helper functions
24+
const getActionText = (action?: string) =>
25+
action === 'closed' ? '关闭' : action?.includes('open') ? '打开' : '编辑';
26+
27+
const createLink = (href: string, text = href) => ({ tag: 'a', href, text });
28+
29+
const createText = (text: string) => ({ tag: 'text', text });
30+
31+
// create user link
32+
const createUserLink = (user: GitHubUser) =>
33+
user ? createLink(user.html_url, user.login) : createText('无');
34+
35+
const createContentItem = (label: string, value?: string | { tag: string; text: string }) =>
36+
[
37+
createText(label),
38+
typeof value === 'string' ? createText(value || '无') : value || createText('无'),
39+
] as [object, object];
40+
41+
type EventHandler = (
42+
event: GitHubAction,
43+
actionText: string,
44+
) => {
45+
title: string;
46+
content: [object, object][];
47+
};
48+
49+
// Event handlers
50+
const eventHandlers: Record<string, EventHandler> = {
51+
push: ({ event: { head_commit }, ref, ref_name, server_url, repository, actor }) => ({
52+
title: 'GitHub 代码提交',
53+
content: [
54+
[createText('提交链接:'), createLink(head_commit!.url)],
55+
[createText('代码分支:'), createLink(`${server_url}/${repository}/tree/${ref_name}`, ref)],
56+
[createText('提交作者:'), createLink(`${server_url}/${actor}`, actor)],
57+
[createText('提交信息:'), createText(head_commit!.message)],
58+
],
59+
}),
60+
61+
issues: ({ event: { issue } }, actionText) => ({
62+
title: `GitHub issue ${actionText}${issue?.title}`,
63+
content: [
64+
[createText('链接:'), createLink(issue!.html_url)],
65+
[createText('作者:'), createLink(issue!.user!.html_url!, issue!.user!.login)],
66+
[
67+
createText('指派:'),
68+
issue?.assignee
69+
? createLink(issue.assignee.html_url!, issue.assignee.login)
70+
: createText('无'),
71+
],
72+
[createText('标签:'), createText(issue?.labels?.map(({ name }) => name).join(', ') || '无')],
73+
[createText('里程碑:'), createText(issue?.milestone?.title || '无')],
74+
[createText('描述:'), createText(issue?.body || '无')],
75+
],
76+
}),
77+
78+
pull_request: ({ event: { pull_request } }, actionText) => ({
79+
title: `GitHub PR ${actionText}${pull_request?.title}`,
80+
content: [
81+
[createText('链接:'), createLink(pull_request!.html_url)],
82+
[createText('作者:'), createLink(pull_request!.user.html_url, pull_request!.user.login)],
83+
[
84+
createText('指派:'),
85+
pull_request?.assignee
86+
? createLink(pull_request.assignee.html_url, pull_request.assignee.login)
87+
: createText('无'),
88+
],
89+
[
90+
createText('标签:'),
91+
createText(pull_request?.labels?.map(({ name }) => name).join(', ') || '无'),
92+
],
93+
[createText('里程碑:'), createText(pull_request?.milestone?.title || '无')],
94+
[createText('描述:'), createText(pull_request?.body || '无')],
95+
],
96+
}),
97+
98+
discussion: ({ event: { discussion } }, actionText) => ({
99+
title: `GitHub 讨论 ${actionText}${discussion?.title || '无'}`,
100+
content: [
101+
createContentItem('链接:', discussion?.html_url),
102+
createContentItem('作者:', createUserLink(discussion!.user as GitHubUser)),
103+
createContentItem('描述:', discussion?.body || '无'),
104+
],
105+
}),
106+
107+
issue_comment: ({ event: { comment, issue } }) => ({
108+
title: `GitHub issue 评论:${issue?.title || '未知 issue'}`,
109+
content: [
110+
createContentItem('链接:', comment?.html_url),
111+
createContentItem('作者:', createUserLink(comment!.user!)),
112+
createContentItem('描述:', comment?.body || '无'),
113+
],
114+
}),
115+
116+
discussion_comment: ({ event: { comment, discussion } }) => ({
117+
title: `GitHub 讨论评论:${discussion?.title || '无'}`,
118+
content: [
119+
createContentItem('链接:', comment?.html_url),
120+
createContentItem('作者:', createUserLink(comment!.user!)),
121+
createContentItem('描述:', comment?.body || '无'),
122+
],
123+
}),
124+
125+
release: ({ event: { release } }) => ({
126+
title: `GitHub Release 发布:${release!.name || release!.tag_name}`,
127+
content: [
128+
createContentItem('链接:', release!.html_url),
129+
createContentItem('作者:', createUserLink(release!.author)),
130+
createContentItem('描述:', release!.body!),
131+
],
132+
}),
133+
};
134+
135+
// Main processor
136+
const processEvent = (event: GitHubAction) => {
137+
const { event_name, action } = event;
138+
const actionText = getActionText(action);
139+
const handler = eventHandlers[event_name];
140+
141+
if (!handler) throw new Error(`No handler found for event: ${event_name}`);
142+
143+
try {
144+
return handler(event, actionText);
145+
} catch (cause) {
146+
throw new Error(`Error processing ${event_name} event: ${(cause as Error).message}`, { cause });
147+
}
148+
};
149+
150+
// Main execution:Processing GitHub Events and Outputting Results
151+
const event = JSON.parse((await stdin()) || '{}') as GitHubAction;
152+
const zh_cn = processEvent(event);
153+
154+
if (zh_cn) console.log(JSON.stringify({ post: { zh_cn } }));
155+
else throw new Error(`Unsupported ${event.event_name} event & ${event.action} action`);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Lark notification
2+
3+
# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows
4+
on:
5+
push:
6+
issues:
7+
pull_request:
8+
discussion:
9+
issue_comment:
10+
discussion_comment:
11+
release:
12+
types:
13+
- published
14+
15+
jobs:
16+
send-Lark-message:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- uses: denoland/setup-deno@v2
22+
with:
23+
deno-version: v2.x
24+
25+
- name: Event Message serialization
26+
id: message
27+
run: |
28+
YAML=$(echo '${{ toJSON(github) }}' | deno --allow-all .github/scripts/transform-message.ts)
29+
{
30+
echo 'content<<EOF'
31+
echo $YAML
32+
echo 'EOF'
33+
} >> $GITHUB_OUTPUT
34+
35+
- name: Send message to Lark
36+
if: ${{ contains(steps.message.outputs.content, ':') }}
37+
uses: foxundermoon/feishu-action@v2
38+
with:
39+
url: ${{ secrets.LARK_CHATBOT_HOOK_URL }}
40+
msg_type: post
41+
content: |
42+
${{ steps.message.outputs.content }}

components/User/SessionBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ export class SessionBox extends Component<SessionBoxProps> {
5959
<Drawer
6060
anchor="right"
6161
open={this.modalShown}
62-
onClose={() => (this.modalShown = false)}
6362
PaperProps={{
6463
className: 'p-4',
6564
style: { width: '400px' },
6665
}}
66+
onClose={() => (this.modalShown = false)}
6767
>
6868
<SessionForm onSignIn={() => window.location.reload()} />
6969
</Drawer>

components/User/SessionForm.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { Button, Tab, Tabs, TextField, InputAdornment, IconButton } from '@mui/material';
1+
import { Button, IconButton,InputAdornment, Tab, Tabs, TextField } from '@mui/material';
22
import { observable } from 'mobx';
33
import { observer } from 'mobx-react';
44
import { ObservedComponent } from 'mobx-react-helper';
5-
import React, { FormEvent, MouseEvent, ChangeEvent } from 'react';
5+
import React, { ChangeEvent,FormEvent, MouseEvent } from 'react';
66
import { formToJSON } from 'web-utility';
77

8-
import { SymbolIcon } from '../Icon';
9-
import userStore from '../../models/User';
108
import { I18nContext } from '../../models/Translation';
9+
import userStore from '../../models/User';
10+
import { SymbolIcon } from '../Icon';
1111

1212
export interface SessionFormProps {
1313
onSignIn?: (data?: SignInData) => any;
@@ -69,9 +69,9 @@ export class SessionForm extends ObservedComponent<SessionFormProps, typeof I18n
6969
>
7070
<Tabs
7171
value={signType}
72-
onChange={(_, newValue: 'up' | 'in') => (this.signType = newValue)}
7372
variant="fullWidth"
7473
className="mb-4"
74+
onChange={(_, newValue: 'up' | 'in') => (this.signType = newValue)}
7575
>
7676
<Tab label={t('register')} value="up" />
7777
<Tab label={t('login')} value="in" />

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,29 @@
1818
"@mui/material": "^7.3.1",
1919
"@mui/material-nextjs": "^7.3.0",
2020
"@passwordless-id/webauthn": "^2.3.1",
21-
"@sentry/nextjs": "^10.5.0",
21+
"@sentry/nextjs": "^10.8.0",
2222
"file-type": "^21.0.0",
2323
"idb-keyval": "^6.2.2",
2424
"jsonwebtoken": "^9.0.2",
2525
"koa": "^3.0.1",
2626
"koa-jwt": "^4.0.4",
2727
"koajax": "^3.1.2",
2828
"lodash": "^4.17.21",
29-
"marked": "^16.2.0",
29+
"marked": "^16.2.1",
3030
"mime": "^4.0.7",
3131
"mobx": "^6.13.7",
32-
"mobx-github": "^0.3.11",
32+
"mobx-github": "^0.4.0",
3333
"mobx-i18n": "^0.7.1",
3434
"mobx-lark": "^2.4.0",
3535
"mobx-react": "^9.2.0",
3636
"mobx-react-helper": "^0.5.1",
3737
"mobx-restful": "^2.1.0",
38-
"next": "^15.5.0",
38+
"next": "^15.5.2",
3939
"next-pwa": "~5.6.0",
4040
"next-ssr-middleware": "^1.0.2",
4141
"react": "^19.1.1",
4242
"react-dom": "^19.1.1",
43-
"web-utility": "^4.5.1",
43+
"web-utility": "^4.5.3",
4444
"webpack": "^5.101.3"
4545
},
4646
"devDependencies": {
@@ -49,8 +49,8 @@
4949
"@babel/preset-react": "^7.27.1",
5050
"@cspell/eslint-plugin": "^9.2.0",
5151
"@eslint/compat": "^1.3.2",
52-
"@eslint/js": "^9.33.0",
53-
"@next/eslint-plugin-next": "^15.5.0",
52+
"@eslint/js": "^9.34.0",
53+
"@next/eslint-plugin-next": "^15.5.2",
5454
"@stylistic/eslint-plugin": "^5.2.3",
5555
"@tailwindcss/postcss": "^4.1.12",
5656
"@tailwindcss/typography": "^0.5.16",
@@ -60,14 +60,14 @@
6060
"@types/koa__router": "^12.0.4",
6161
"@types/lodash": "^4.17.20",
6262
"@types/next-pwa": "^5.6.9",
63-
"@types/node": "^22.17.2",
64-
"@types/react": "^19.1.11",
65-
"eslint": "^9.33.0",
66-
"eslint-config-next": "^15.5.0",
63+
"@types/node": "^22.18.0",
64+
"@types/react": "^19.1.12",
65+
"eslint": "^9.34.0",
66+
"eslint-config-next": "^15.5.2",
6767
"eslint-config-prettier": "^10.1.8",
6868
"eslint-plugin-react": "^7.37.5",
6969
"eslint-plugin-simple-import-sort": "^12.1.1",
70-
"get-git-folder": "^0.1.2",
70+
"git-utility": "^0.2.0",
7171
"globals": "^16.3.0",
7272
"husky": "^9.1.7",
7373
"jiti": "^2.5.1",
@@ -78,7 +78,7 @@
7878
"prettier-plugin-tailwindcss": "^0.6.14",
7979
"tailwindcss": "^4.1.12",
8080
"typescript": "~5.9.2",
81-
"typescript-eslint": "^8.40.0"
81+
"typescript-eslint": "^8.41.0"
8282
},
8383
"resolutions": {
8484
"next": "$next"
@@ -107,7 +107,7 @@
107107
},
108108
"scripts": {
109109
"prepare": "husky || true",
110-
"install": "get-git-folder https://github.com/idea2app/key-vault main idea2app.github.io || true",
110+
"install": "xgit download https://github.com/idea2app/key-vault main idea2app.github.io || true",
111111
"dev": "next dev",
112112
"build": "next build",
113113
"export": "next build && next export",

pages/dashboard/index.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ interface DashboardPageProps extends JWTProps {
1313

1414
export const getServerSideProps = compose<{}, DashboardPageProps>(
1515
jwtVerifier(),
16-
async () => {
17-
return { props: {} };
18-
},
16+
async () => ({ props: {} }),
1917
);
2018

2119
const DashboardPage: FC<DashboardPageProps> = observer(({ jwtPayload }) => {

pages/wiki/[node_token].tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Block, renderBlocks, WikiNode } from 'mobx-lark';
22
import { GetStaticPaths, GetStaticProps } from 'next';
33
import { FC } from 'react';
4+
import { Minute, Second } from 'web-utility';
45

56
import { PageHead } from '../../components/PageHead';
67
import documentStore from '../../models/Document';
@@ -25,12 +26,18 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
2526

2627
if (node?.obj_type !== 'docx') return { notFound: true };
2728

28-
const blocks = await documentStore.getOneBlocks(
29-
node.obj_token,
30-
token => `/api/Lark/file/${token}`,
31-
);
29+
try {
30+
const blocks = await documentStore.getOneBlocks(
31+
node.obj_token,
32+
token => `/api/Lark/file/${token}`,
33+
);
3234

33-
return { props: { node, blocks } };
35+
return { props: { node, blocks } };
36+
} catch (error) {
37+
console.error(error);
38+
39+
return { notFound: true, revalidate: Minute / Second };
40+
}
3441
};
3542

3643
interface WikiDocumentPageProps {

0 commit comments

Comments
 (0)