@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.
Files changed (74) hide show
  1. package/LICENSE +661 -661
  2. package/README.md +0 -14
  3. package/package.json +1 -1
  4. package/vendor/gugle-chat-bot/LICENSE +661 -661
  5. package/vendor/gugle-chat-bot/package.json +57 -57
  6. package/vendor/gugle-chat-bot/src/allow-rule.yml +9345 -9345
  7. package/vendor/gugle-chat-bot/src/api.json +4284 -4284
  8. package/vendor/gugle-chat-bot/src/command/index.ts +141 -141
  9. package/vendor/gugle-chat-bot/src/config/features.ts +547 -547
  10. package/vendor/gugle-chat-bot/src/config/index.ts +184 -184
  11. package/vendor/gugle-chat-bot/src/config/manager.ts +356 -356
  12. package/vendor/gugle-chat-bot/src/constants/index.ts +13 -13
  13. package/vendor/gugle-chat-bot/src/custom.ts +548 -548
  14. package/vendor/gugle-chat-bot/src/event/index.ts +118 -118
  15. package/vendor/gugle-chat-bot/src/features/admin/index.ts +414 -414
  16. package/vendor/gugle-chat-bot/src/features/bili/image/impl/video.ts +39 -39
  17. package/vendor/gugle-chat-bot/src/features/bili/image/index.ts +37 -37
  18. package/vendor/gugle-chat-bot/src/features/bili/index.ts +65 -65
  19. package/vendor/gugle-chat-bot/src/features/bili/template/style/video.css +97 -97
  20. package/vendor/gugle-chat-bot/src/features/bili/template/video.html +56 -56
  21. package/vendor/gugle-chat-bot/src/features/discord-bridge/index.ts +1128 -1128
  22. package/vendor/gugle-chat-bot/src/features/discord-bridge/markdown.ts +105 -105
  23. package/vendor/gugle-chat-bot/src/features/discord-bridge/slash.ts +355 -355
  24. package/vendor/gugle-chat-bot/src/features/discord-bridge/source.ts +96 -96
  25. package/vendor/gugle-chat-bot/src/features/discord-bridge/template/message.html +14 -14
  26. package/vendor/gugle-chat-bot/src/features/discord-bridge/template/style/message.css +144 -144
  27. package/vendor/gugle-chat-bot/src/features/github/api.ts +93 -93
  28. package/vendor/gugle-chat-bot/src/features/github/binding.ts +161 -161
  29. package/vendor/gugle-chat-bot/src/features/github/image/impl/issue.ts +132 -132
  30. package/vendor/gugle-chat-bot/src/features/github/image/impl/pr.ts +144 -144
  31. package/vendor/gugle-chat-bot/src/features/github/image/impl/release.ts +160 -160
  32. package/vendor/gugle-chat-bot/src/features/github/image/index.ts +310 -310
  33. package/vendor/gugle-chat-bot/src/features/github/index.ts +302 -302
  34. package/vendor/gugle-chat-bot/src/features/github/template/issue.html +118 -118
  35. package/vendor/gugle-chat-bot/src/features/github/template/pull_request.html +125 -125
  36. package/vendor/gugle-chat-bot/src/features/github/template/release.html +53 -53
  37. package/vendor/gugle-chat-bot/src/features/github/template/style/issue.css +468 -468
  38. package/vendor/gugle-chat-bot/src/features/github/template/style/pull_request.css +468 -468
  39. package/vendor/gugle-chat-bot/src/features/github/template/style/release.css +412 -412
  40. package/vendor/gugle-chat-bot/src/features/hermes/client.ts +184 -184
  41. package/vendor/gugle-chat-bot/src/features/hermes/config.ts +210 -210
  42. package/vendor/gugle-chat-bot/src/features/hermes/context.ts +67 -67
  43. package/vendor/gugle-chat-bot/src/features/hermes/history.ts +86 -86
  44. package/vendor/gugle-chat-bot/src/features/hermes/index.ts +1533 -1533
  45. package/vendor/gugle-chat-bot/src/features/hermes/message.ts +319 -319
  46. package/vendor/gugle-chat-bot/src/features/hermes/reaction.ts +181 -181
  47. package/vendor/gugle-chat-bot/src/features/hermes/render.ts +118 -118
  48. package/vendor/gugle-chat-bot/src/features/hermes/reply-units.ts +331 -331
  49. package/vendor/gugle-chat-bot/src/features/hermes/skills.ts +406 -406
  50. package/vendor/gugle-chat-bot/src/features/hermes/template/approval.html +30 -30
  51. package/vendor/gugle-chat-bot/src/features/hermes/template/progress.html +21 -21
  52. package/vendor/gugle-chat-bot/src/features/hermes/template/style/approval.css +81 -81
  53. package/vendor/gugle-chat-bot/src/features/hermes/template/style/progress.css +120 -120
  54. package/vendor/gugle-chat-bot/src/features/hermes/trigger.ts +86 -86
  55. package/vendor/gugle-chat-bot/src/features/hermes/types.ts +327 -327
  56. package/vendor/gugle-chat-bot/src/features/management/index.ts +156 -156
  57. package/vendor/gugle-chat-bot/src/features/minecraft/index.ts +127 -127
  58. package/vendor/gugle-chat-bot/src/features/modrinth/index.ts +71 -71
  59. package/vendor/gugle-chat-bot/src/features/parentheses/index.ts +117 -117
  60. package/vendor/gugle-chat-bot/src/features/peak-valley-timer/index.ts +451 -451
  61. package/vendor/gugle-chat-bot/src/features/poke/index.ts +24 -24
  62. package/vendor/gugle-chat-bot/src/features/version-tracker/index.ts +77 -77
  63. package/vendor/gugle-chat-bot/src/features/welcome/index.ts +57 -57
  64. package/vendor/gugle-chat-bot/src/github-ip.json +5814 -5814
  65. package/vendor/gugle-chat-bot/src/image/index.ts +278 -278
  66. package/vendor/gugle-chat-bot/src/index.ts +695 -695
  67. package/vendor/gugle-chat-bot/src/logger/index.ts +54 -54
  68. package/vendor/gugle-chat-bot/src/result.json +359 -359
  69. package/vendor/gugle-chat-bot/src/type/bili.d.ts +825 -825
  70. package/vendor/gugle-chat-bot/src/type/event.d.ts +146 -146
  71. package/vendor/gugle-chat-bot/src/type/github.d.ts +446 -446
  72. package/vendor/gugle-chat-bot/src/type/index.d.ts +254 -254
  73. package/vendor/gugle-chat-bot/tsconfig.json +46 -46
  74. package/scripts/dump-npm-latest.mjs +0 -30
@@ -1,132 +1,132 @@
1
- import { Issue, IssueEvent, OpenedIssueEvent, ReopenedIssueEvent, User } from '@/type/github';
2
- import { Logger } from 'winston';
3
- import { Template, tryGenerateImage } from '@/image';
4
- import dayjs from 'dayjs';
5
- import { renderIssueBody } from '@/features/github/image';
6
-
7
- function getRepositoryParts(repositoryUrl?: string, htmlUrl?: string): { owner: string; name: string } {
8
- const url = repositoryUrl || htmlUrl;
9
- if (!url) return { owner: 'GitHub', name: '' };
10
- const parts = url.split('/').filter(Boolean);
11
- const githubIndex = parts.indexOf('github.com');
12
- const repositoryParts = githubIndex >= 0 ? parts.slice(githubIndex + 1, githubIndex + 3) : parts.slice(-2);
13
- return repositoryParts.length === 2
14
- ? { owner: repositoryParts[0]!, name: repositoryParts[1]! }
15
- : { owner: 'GitHub', name: '' };
16
- }
17
-
18
- function getIssueState(issue: Issue): string {
19
- if (issue.state == 'open') {
20
- return `
21
- <div class="state_label" style="color:white; background-color: #347d39; box-shadow-color: #347d39;">
22
- <div style="display: flex; align-items: center;">
23
- <svg focusable="false" aria-label="Issue"
24
- class="octicon octicon-issue-opened prc-StateLabel-Icon-YICrR" role="img" viewBox="0 0 16 16"
25
- width="16" height="16" fill="currentColor" display="inline-block"
26
- overflow="visible" style="margin-right:4px; vertical-align:text-bottom">
27
- <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"/>
28
- <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"/>
29
- </svg>
30
- Open
31
- </div>
32
- </div>\n
33
- `;
34
- } else {
35
- if (issue.state_reason == 'completed') {
36
- return `
37
- <div class="state_label" style="color:white; background-color: #8256d0; box-shadow-color: #8256d0;">
38
- <div style="display: flex; align-items: center;">
39
- <svg focusable="false" aria-label="Issue" class="octicon octicon-issue-closed prc-StateLabel-Icon-YICrR"
40
- role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block"
41
- overflow="visible" style="margin-right:4px; vertical-align:text-bottom">
42
- <path d="M11.28 6.78a.75.75 0 0 0-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.06 0l3.5-3.5Z"/>
43
- <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 0 0 13 0Z"></path>
44
- </svg>
45
- Closed
46
- </div>
47
- </div>\n
48
- `;
49
- } else {
50
- return `
51
- <div class="state_label" style="color:white; background-color: #656c76; box-shadow-color: #656c76;">
52
- <div style="display: flex; align-items: center;">
53
- <svg focusable="false" aria-label="Issue, not planned" class="octicon octicon-skip prc-StateLabel-Icon-YICrR"
54
- role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block"
55
- overflow="visible" style="margin-right:4px; vertical-align: text-bottom;">
56
- <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13
57
- 0Zm9.78-2.22-5.5 5.5a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l5.5-5.5a.751.751 0 0 1
58
- 1.042.018.751.751 0 0 1 .018 1.042Z"/>
59
- </svg>
60
- Closed
61
- </div>
62
- </div>\n
63
- `;
64
- }
65
- }
66
- }
67
-
68
- export function issuesHandler(issue: Issue, logger?: Logger, operation?: string, sender?: User, extra?: string) {
69
- let labelsHtml = '';
70
- for (let label of issue.labels) {
71
- labelsHtml += `<div class="sidebar-label" style="color:#${label.color}ff; background-color: #${label.color}55; border:2px solid #${label.color}99">${label.name}</div>\n`;
72
- }
73
- let headerExtra: string | undefined = undefined;
74
- if (sender) {
75
- headerExtra = `<div class="message">用户<div class="user">${sender.login}</div>${operation}了 </div>`;
76
- }
77
- return new Promise<string>((resolve, reject) => {
78
- const repository = getRepositoryParts(issue.repository_url, issue.html_url);
79
- const repoFullName = `${repository.owner}/${repository.name}`;
80
- renderIssueBody(issue.body, repoFullName, logger)
81
- .then(bodyHtml => {
82
- const template = Template.load('issue', 'src/features/github/template')
83
- .arg('header extra', headerExtra || '')
84
- .arg('repository owner', repository.owner)
85
- .arg('repository name', repository.name)
86
- .arg('issue number', issue.number)
87
- .arg('state label', getIssueState(issue))
88
- .arg('issue title', issue.title)
89
- .arg('issue author', issue.user.login)
90
- .arg('issue body', bodyHtml)
91
- .arg('issue created at', dayjs(issue.created_at).format('YYYY-MM-DD HH:mm:ss'))
92
- .arg('issue labels', labelsHtml || 'No labels')
93
- .arg('extra', extra || '');
94
- const templateFile = template.file();
95
- template
96
- .handler()
97
- .then(issue => {
98
- logger?.debug(`Start process issue message...`);
99
- tryGenerateImage(resolve, reject, issue, 820, templateFile);
100
- })
101
- .catch(reject);
102
- })
103
- .catch(reject);
104
- });
105
- }
106
-
107
- export function issuesClosed(issue: IssueEvent, logger?: Logger): Promise<string> {
108
- let extra: string | undefined;
109
- if (issue.issue.state_reason) {
110
- extra = "<div class='h1'>关闭原因:</div>\n";
111
- }
112
- if (issue.issue.state_reason == 'completed') {
113
- extra += "<div class='body'>已完成</div>\n";
114
- } else if (issue.issue.state_reason == 'not_planned') {
115
- extra += "<div class='body'>未计划</div>\n";
116
- } else if (issue.issue.state_reason == 'duplicate') {
117
- extra += "<div class='body'>重复</div>\n";
118
- } else {
119
- extra += `<div class='body'>${issue.issue.state_reason}</div>\n`;
120
- }
121
- return issuesHandler(issue.issue, logger, '关闭', issue.sender, extra);
122
- }
123
-
124
- export function issuesOpened(issue: OpenedIssueEvent | ReopenedIssueEvent, logger?: Logger): Promise<string> {
125
- let operation: string;
126
- if (issue.action == 'reopened') {
127
- operation = '重新打开';
128
- } else {
129
- operation = '提交';
130
- }
131
- return issuesHandler(issue.issue, logger, operation, issue.sender);
132
- }
1
+ import { Issue, IssueEvent, OpenedIssueEvent, ReopenedIssueEvent, User } from '@/type/github';
2
+ import { Logger } from 'winston';
3
+ import { Template, tryGenerateImage } from '@/image';
4
+ import dayjs from 'dayjs';
5
+ import { renderIssueBody } from '@/features/github/image';
6
+
7
+ function getRepositoryParts(repositoryUrl?: string, htmlUrl?: string): { owner: string; name: string } {
8
+ const url = repositoryUrl || htmlUrl;
9
+ if (!url) return { owner: 'GitHub', name: '' };
10
+ const parts = url.split('/').filter(Boolean);
11
+ const githubIndex = parts.indexOf('github.com');
12
+ const repositoryParts = githubIndex >= 0 ? parts.slice(githubIndex + 1, githubIndex + 3) : parts.slice(-2);
13
+ return repositoryParts.length === 2
14
+ ? { owner: repositoryParts[0]!, name: repositoryParts[1]! }
15
+ : { owner: 'GitHub', name: '' };
16
+ }
17
+
18
+ function getIssueState(issue: Issue): string {
19
+ if (issue.state == 'open') {
20
+ return `
21
+ <div class="state_label" style="color:white; background-color: #347d39; box-shadow-color: #347d39;">
22
+ <div style="display: flex; align-items: center;">
23
+ <svg focusable="false" aria-label="Issue"
24
+ class="octicon octicon-issue-opened prc-StateLabel-Icon-YICrR" role="img" viewBox="0 0 16 16"
25
+ width="16" height="16" fill="currentColor" display="inline-block"
26
+ overflow="visible" style="margin-right:4px; vertical-align:text-bottom">
27
+ <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"/>
28
+ <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"/>
29
+ </svg>
30
+ Open
31
+ </div>
32
+ </div>\n
33
+ `;
34
+ } else {
35
+ if (issue.state_reason == 'completed') {
36
+ return `
37
+ <div class="state_label" style="color:white; background-color: #8256d0; box-shadow-color: #8256d0;">
38
+ <div style="display: flex; align-items: center;">
39
+ <svg focusable="false" aria-label="Issue" class="octicon octicon-issue-closed prc-StateLabel-Icon-YICrR"
40
+ role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block"
41
+ overflow="visible" style="margin-right:4px; vertical-align:text-bottom">
42
+ <path d="M11.28 6.78a.75.75 0 0 0-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.06 0l3.5-3.5Z"/>
43
+ <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 0 0 13 0Z"></path>
44
+ </svg>
45
+ Closed
46
+ </div>
47
+ </div>\n
48
+ `;
49
+ } else {
50
+ return `
51
+ <div class="state_label" style="color:white; background-color: #656c76; box-shadow-color: #656c76;">
52
+ <div style="display: flex; align-items: center;">
53
+ <svg focusable="false" aria-label="Issue, not planned" class="octicon octicon-skip prc-StateLabel-Icon-YICrR"
54
+ role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block"
55
+ overflow="visible" style="margin-right:4px; vertical-align: text-bottom;">
56
+ <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13
57
+ 0Zm9.78-2.22-5.5 5.5a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l5.5-5.5a.751.751 0 0 1
58
+ 1.042.018.751.751 0 0 1 .018 1.042Z"/>
59
+ </svg>
60
+ Closed
61
+ </div>
62
+ </div>\n
63
+ `;
64
+ }
65
+ }
66
+ }
67
+
68
+ export function issuesHandler(issue: Issue, logger?: Logger, operation?: string, sender?: User, extra?: string) {
69
+ let labelsHtml = '';
70
+ for (let label of issue.labels) {
71
+ labelsHtml += `<div class="sidebar-label" style="color:#${label.color}ff; background-color: #${label.color}55; border:2px solid #${label.color}99">${label.name}</div>\n`;
72
+ }
73
+ let headerExtra: string | undefined = undefined;
74
+ if (sender) {
75
+ headerExtra = `<div class="message">用户<div class="user">${sender.login}</div>${operation}了 </div>`;
76
+ }
77
+ return new Promise<string>((resolve, reject) => {
78
+ const repository = getRepositoryParts(issue.repository_url, issue.html_url);
79
+ const repoFullName = `${repository.owner}/${repository.name}`;
80
+ renderIssueBody(issue.body, repoFullName, logger)
81
+ .then(bodyHtml => {
82
+ const template = Template.load('issue', 'src/features/github/template')
83
+ .arg('header extra', headerExtra || '')
84
+ .arg('repository owner', repository.owner)
85
+ .arg('repository name', repository.name)
86
+ .arg('issue number', issue.number)
87
+ .arg('state label', getIssueState(issue))
88
+ .arg('issue title', issue.title)
89
+ .arg('issue author', issue.user.login)
90
+ .arg('issue body', bodyHtml)
91
+ .arg('issue created at', dayjs(issue.created_at).format('YYYY-MM-DD HH:mm:ss'))
92
+ .arg('issue labels', labelsHtml || 'No labels')
93
+ .arg('extra', extra || '');
94
+ const templateFile = template.file();
95
+ template
96
+ .handler()
97
+ .then(issue => {
98
+ logger?.debug(`Start process issue message...`);
99
+ tryGenerateImage(resolve, reject, issue, 820, templateFile);
100
+ })
101
+ .catch(reject);
102
+ })
103
+ .catch(reject);
104
+ });
105
+ }
106
+
107
+ export function issuesClosed(issue: IssueEvent, logger?: Logger): Promise<string> {
108
+ let extra: string | undefined;
109
+ if (issue.issue.state_reason) {
110
+ extra = "<div class='h1'>关闭原因:</div>\n";
111
+ }
112
+ if (issue.issue.state_reason == 'completed') {
113
+ extra += "<div class='body'>已完成</div>\n";
114
+ } else if (issue.issue.state_reason == 'not_planned') {
115
+ extra += "<div class='body'>未计划</div>\n";
116
+ } else if (issue.issue.state_reason == 'duplicate') {
117
+ extra += "<div class='body'>重复</div>\n";
118
+ } else {
119
+ extra += `<div class='body'>${issue.issue.state_reason}</div>\n`;
120
+ }
121
+ return issuesHandler(issue.issue, logger, '关闭', issue.sender, extra);
122
+ }
123
+
124
+ export function issuesOpened(issue: OpenedIssueEvent | ReopenedIssueEvent, logger?: Logger): Promise<string> {
125
+ let operation: string;
126
+ if (issue.action == 'reopened') {
127
+ operation = '重新打开';
128
+ } else {
129
+ operation = '提交';
130
+ }
131
+ return issuesHandler(issue.issue, logger, operation, issue.sender);
132
+ }
@@ -1,144 +1,144 @@
1
- import { OpenedPullRequestEvent, PullRequest, PullRequestEvent, ReopenedPullRequestEvent, User } from '@/type/github';
2
- import { Logger } from 'winston';
3
- import { Template, tryGenerateImage } from '@/image';
4
- import { renderIssueBody } from '@/features/github/image';
5
- import dayjs from 'dayjs';
6
-
7
- function getRepositoryParts(repositoryUrl?: string, htmlUrl?: string): { owner: string; name: string } {
8
- const url = repositoryUrl || htmlUrl;
9
- if (!url) return { owner: 'GitHub', name: '' };
10
- const parts = url.split('/').filter(Boolean);
11
- const githubIndex = parts.indexOf('github.com');
12
- const repositoryParts = githubIndex >= 0 ? parts.slice(githubIndex + 1, githubIndex + 3) : parts.slice(-2);
13
- return repositoryParts.length === 2
14
- ? { owner: repositoryParts[0]!, name: repositoryParts[1]! }
15
- : { owner: 'GitHub', name: '' };
16
- }
17
-
18
- export function getPullRequestState(pr: PullRequest): string {
19
- if (pr.state == 'open') {
20
- if (pr.draft) {
21
- return `
22
- <div class="state_label" style="color:white; background-color: #656c76; box-shadow-color: #656c76;">
23
- <div style="display: flex; align-items: center;">
24
- <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
25
- <path d="M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251
26
- 0 0 1 3.25 1Zm9.5 14a2.25 2.25 0 1 1 0-4.5 2.25 2.25 0 0 1 0 4.5ZM2.5 3.25a.75.75 0 1 0 1.5 0
27
- .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75
28
- 0 0 0 0-1.5ZM14 7.5a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Zm0-4.25a1.25 1.25 0 1 1-2.5 0
29
- 1.25 1.25 0 0 1 2.5 0Z"/>
30
- </svg>
31
- Draft
32
- </div>
33
- </div>\n
34
- `;
35
- } else {
36
- return `
37
- <div class="state_label" style="color:white; background-color: #347d39; box-shadow-color: #347d39;">
38
- <div style="display: flex; align-items: center;">
39
- <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
40
- <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25
41
- 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251
42
- 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1
43
- 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0
44
- 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"/>
45
- </svg>
46
- Open
47
- </div>
48
- </div>\n
49
- `;
50
- }
51
- } else {
52
- if (pr.merged) {
53
- return `
54
- <div class="state_label" style="color:white; background-color: #8256d0; box-shadow-color: #8256d0;">
55
- <div style="display: flex; align-items: center;">
56
- <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
57
- <path d="M5.45 5.154A4.25 4.25 0 0 0 9.25 7.5h1.378a2.251 2.251 0 1 1 0 1.5H9.25A5.734 5.734
58
- 0 0 1 5 7.123v3.505a2.25 2.25 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.95-.218ZM4.25 13.5a.75.75
59
- 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm8.5-4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM5 3.25a.75.75
60
- 0 1 0 0 .005V3.25Z"/>
61
- </svg>
62
- Merged
63
- </div>
64
- </div>\n
65
- `;
66
- } else {
67
- return `
68
- <div class="state_label" style="color:white; background-color: #c93c37; box-shadow-color: #c93c37;">
69
- <div style="display: flex; align-items: center;">
70
- <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
71
- <path d="M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251
72
- 0 0 1 3.25 1Zm9.5 5.5a.75.75 0 0 1 .75.75v3.378a2.251 2.251 0 1 1-1.5 0V7.25a.75.75
73
- 0 0 1 .75-.75Zm-2.03-5.273a.75.75 0 0 1 1.06 0l.97.97.97-.97a.748.748 0 0 1 1.265.332.75.75
74
- 0 0 1-.205.729l-.97.97.97.97a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-.97-.97-.97.97a.749.749
75
- 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l.97-.97-.97-.97a.75.75 0 0 1 0-1.06ZM2.5 3.25a.75.75
76
- 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1
77
- 0 0 1.5.75.75 0 0 0 0-1.5Z"/>
78
- </svg>
79
- Closed
80
- </div>
81
- </div>\n
82
- `;
83
- }
84
- }
85
- }
86
-
87
- export function prHandler(pr: PullRequest, logger?: Logger, operation?: string, sender?: User, extra?: string) {
88
- let labelsHtml = '';
89
- for (let label of pr.labels) {
90
- labelsHtml += `<div class="sidebar-label" style="color:#${label.color}ff; background-color: #${label.color}55; border:2px solid #${label.color}99">${label.name}</div>\n`;
91
- }
92
- let headerExtra: string | undefined = undefined;
93
- if (sender) {
94
- headerExtra = `<div class="message">用户<div class="user">${sender.login}</div>${operation}了 </div>`;
95
- }
96
- return new Promise<string>((resolve, reject) => {
97
- const repository = getRepositoryParts(pr.repository_url, pr.html_url);
98
- const repoFullName = `${repository.owner}/${repository.name}`;
99
- renderIssueBody(pr.body, repoFullName, logger)
100
- .then(bodyHtml => {
101
- const template = Template.load('pull_request', 'src/features/github/template')
102
- .arg('header extra', headerExtra || '')
103
- .arg('repository owner', repository.owner)
104
- .arg('repository name', repository.name)
105
- .arg('pr number', pr.number)
106
- .arg('pr title', pr.title)
107
- .arg('pr body', bodyHtml)
108
- .arg('pr labels', labelsHtml || 'No labels')
109
- .arg('pr author', pr.user.login)
110
- .arg('pr created at', dayjs(pr.created_at).format('YYYY-MM-DD HH:mm:ss'))
111
- .arg('state label', getPullRequestState(pr))
112
- .arg('extra', extra || '');
113
- const templateFile = template.file();
114
- template
115
- .handler()
116
- .then(pr => {
117
- logger?.debug(`Start process pull request message...`);
118
- tryGenerateImage(resolve, reject, pr, 820, templateFile);
119
- })
120
- .catch(reject);
121
- })
122
- .catch(reject);
123
- });
124
- }
125
-
126
- export function prClosed(pr: PullRequestEvent, logger?: Logger): Promise<string> {
127
- let operation: string;
128
- if (pr.pull_request.merged) {
129
- operation = '合并';
130
- } else {
131
- operation = '关闭';
132
- }
133
- return prHandler(pr.pull_request, logger, operation, pr.sender);
134
- }
135
-
136
- export function prOpened(pr: OpenedPullRequestEvent | ReopenedPullRequestEvent, logger?: Logger): Promise<string> {
137
- let operation: string;
138
- if (pr.action == 'reopened') {
139
- operation = '重新打开';
140
- } else {
141
- operation = '提交';
142
- }
143
- return prHandler(pr.pull_request, logger, operation, pr.sender);
144
- }
1
+ import { OpenedPullRequestEvent, PullRequest, PullRequestEvent, ReopenedPullRequestEvent, User } from '@/type/github';
2
+ import { Logger } from 'winston';
3
+ import { Template, tryGenerateImage } from '@/image';
4
+ import { renderIssueBody } from '@/features/github/image';
5
+ import dayjs from 'dayjs';
6
+
7
+ function getRepositoryParts(repositoryUrl?: string, htmlUrl?: string): { owner: string; name: string } {
8
+ const url = repositoryUrl || htmlUrl;
9
+ if (!url) return { owner: 'GitHub', name: '' };
10
+ const parts = url.split('/').filter(Boolean);
11
+ const githubIndex = parts.indexOf('github.com');
12
+ const repositoryParts = githubIndex >= 0 ? parts.slice(githubIndex + 1, githubIndex + 3) : parts.slice(-2);
13
+ return repositoryParts.length === 2
14
+ ? { owner: repositoryParts[0]!, name: repositoryParts[1]! }
15
+ : { owner: 'GitHub', name: '' };
16
+ }
17
+
18
+ export function getPullRequestState(pr: PullRequest): string {
19
+ if (pr.state == 'open') {
20
+ if (pr.draft) {
21
+ return `
22
+ <div class="state_label" style="color:white; background-color: #656c76; box-shadow-color: #656c76;">
23
+ <div style="display: flex; align-items: center;">
24
+ <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
25
+ <path d="M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251
26
+ 0 0 1 3.25 1Zm9.5 14a2.25 2.25 0 1 1 0-4.5 2.25 2.25 0 0 1 0 4.5ZM2.5 3.25a.75.75 0 1 0 1.5 0
27
+ .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75
28
+ 0 0 0 0-1.5ZM14 7.5a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Zm0-4.25a1.25 1.25 0 1 1-2.5 0
29
+ 1.25 1.25 0 0 1 2.5 0Z"/>
30
+ </svg>
31
+ Draft
32
+ </div>
33
+ </div>\n
34
+ `;
35
+ } else {
36
+ return `
37
+ <div class="state_label" style="color:white; background-color: #347d39; box-shadow-color: #347d39;">
38
+ <div style="display: flex; align-items: center;">
39
+ <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
40
+ <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25
41
+ 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251
42
+ 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1
43
+ 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0
44
+ 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"/>
45
+ </svg>
46
+ Open
47
+ </div>
48
+ </div>\n
49
+ `;
50
+ }
51
+ } else {
52
+ if (pr.merged) {
53
+ return `
54
+ <div class="state_label" style="color:white; background-color: #8256d0; box-shadow-color: #8256d0;">
55
+ <div style="display: flex; align-items: center;">
56
+ <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
57
+ <path d="M5.45 5.154A4.25 4.25 0 0 0 9.25 7.5h1.378a2.251 2.251 0 1 1 0 1.5H9.25A5.734 5.734
58
+ 0 0 1 5 7.123v3.505a2.25 2.25 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.95-.218ZM4.25 13.5a.75.75
59
+ 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm8.5-4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM5 3.25a.75.75
60
+ 0 1 0 0 .005V3.25Z"/>
61
+ </svg>
62
+ Merged
63
+ </div>
64
+ </div>\n
65
+ `;
66
+ } else {
67
+ return `
68
+ <div class="state_label" style="color:white; background-color: #c93c37; box-shadow-color: #c93c37;">
69
+ <div style="display: flex; align-items: center;">
70
+ <svg class="octicon" focusable="false" height="16" fill="currentColor" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true">
71
+ <path d="M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251
72
+ 0 0 1 3.25 1Zm9.5 5.5a.75.75 0 0 1 .75.75v3.378a2.251 2.251 0 1 1-1.5 0V7.25a.75.75
73
+ 0 0 1 .75-.75Zm-2.03-5.273a.75.75 0 0 1 1.06 0l.97.97.97-.97a.748.748 0 0 1 1.265.332.75.75
74
+ 0 0 1-.205.729l-.97.97.97.97a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-.97-.97-.97.97a.749.749
75
+ 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l.97-.97-.97-.97a.75.75 0 0 1 0-1.06ZM2.5 3.25a.75.75
76
+ 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1
77
+ 0 0 1.5.75.75 0 0 0 0-1.5Z"/>
78
+ </svg>
79
+ Closed
80
+ </div>
81
+ </div>\n
82
+ `;
83
+ }
84
+ }
85
+ }
86
+
87
+ export function prHandler(pr: PullRequest, logger?: Logger, operation?: string, sender?: User, extra?: string) {
88
+ let labelsHtml = '';
89
+ for (let label of pr.labels) {
90
+ labelsHtml += `<div class="sidebar-label" style="color:#${label.color}ff; background-color: #${label.color}55; border:2px solid #${label.color}99">${label.name}</div>\n`;
91
+ }
92
+ let headerExtra: string | undefined = undefined;
93
+ if (sender) {
94
+ headerExtra = `<div class="message">用户<div class="user">${sender.login}</div>${operation}了 </div>`;
95
+ }
96
+ return new Promise<string>((resolve, reject) => {
97
+ const repository = getRepositoryParts(pr.repository_url, pr.html_url);
98
+ const repoFullName = `${repository.owner}/${repository.name}`;
99
+ renderIssueBody(pr.body, repoFullName, logger)
100
+ .then(bodyHtml => {
101
+ const template = Template.load('pull_request', 'src/features/github/template')
102
+ .arg('header extra', headerExtra || '')
103
+ .arg('repository owner', repository.owner)
104
+ .arg('repository name', repository.name)
105
+ .arg('pr number', pr.number)
106
+ .arg('pr title', pr.title)
107
+ .arg('pr body', bodyHtml)
108
+ .arg('pr labels', labelsHtml || 'No labels')
109
+ .arg('pr author', pr.user.login)
110
+ .arg('pr created at', dayjs(pr.created_at).format('YYYY-MM-DD HH:mm:ss'))
111
+ .arg('state label', getPullRequestState(pr))
112
+ .arg('extra', extra || '');
113
+ const templateFile = template.file();
114
+ template
115
+ .handler()
116
+ .then(pr => {
117
+ logger?.debug(`Start process pull request message...`);
118
+ tryGenerateImage(resolve, reject, pr, 820, templateFile);
119
+ })
120
+ .catch(reject);
121
+ })
122
+ .catch(reject);
123
+ });
124
+ }
125
+
126
+ export function prClosed(pr: PullRequestEvent, logger?: Logger): Promise<string> {
127
+ let operation: string;
128
+ if (pr.pull_request.merged) {
129
+ operation = '合并';
130
+ } else {
131
+ operation = '关闭';
132
+ }
133
+ return prHandler(pr.pull_request, logger, operation, pr.sender);
134
+ }
135
+
136
+ export function prOpened(pr: OpenedPullRequestEvent | ReopenedPullRequestEvent, logger?: Logger): Promise<string> {
137
+ let operation: string;
138
+ if (pr.action == 'reopened') {
139
+ operation = '重新打开';
140
+ } else {
141
+ operation = '提交';
142
+ }
143
+ return prHandler(pr.pull_request, logger, operation, pr.sender);
144
+ }