@candriajs/karin-plugin-git 1.1.1

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.
@@ -0,0 +1,3 @@
1
+ cron: '0 */5 * * * *'
2
+ proxy: ''
3
+ token: ''
@@ -0,0 +1,3 @@
1
+ cron: '0 */5 * * * *'
2
+ proxy: ''
3
+ token: ''
@@ -0,0 +1,3 @@
1
+ cron: '0 */5 * * * *'
2
+ proxy: ''
3
+ token: ''
@@ -0,0 +1 @@
1
+ import"../root-C9I_RrRd.js";import{i as e,n as t,o as n,r,s as i}from"../db-D0PoPjmA.js";import{o as a}from"../common-OZlZxDcC.js";import{t as o}from"../types-BuMDb1Mk.js";import s from"node-karin";const c=s.command(/^#?git(?:添加|add)([^\s]+)?订阅仓库([^/\s]+)\/([^:\s]+)(?::([^/\s]+))?$/i,async i=>{let[,a,s,l,u]=i.msg.match(c.reg),d=i.selfId,f=i.groupId,p=o.GitHub;a?.toLowerCase()===`gitcode`?p=o.GitCode:a?.toLowerCase()===`gitee`?p=o.Gitee:a?.toLowerCase()===`cnb`&&(p=o.Cnb);let m=u||`main`,h=await r(d,f,s,l);if(h||=(await t(d,f,s,l),await r(d,f,s,l)),!h)return await i.reply(`添加仓库失败,请重试`);await n(o.GitHub,h.id,m)?await i.reply(`仓库 ${s}/${l} 的推送订阅已存在,平台: ${p}, 分支: ${m}`):(await e(p,h.id,m),await i.reply(`添加订阅仓库成功, 平台: ${p}, 仓库: ${s}/${l}, 分支: ${m}`))},{name:`karin-plugin-git:addRepo`,priority:500,event:`message.group`,permission:`master`}),l=s.command(/^#?git(?:移除|删除|remove)([^\s]+)?订阅仓库([^/\s]+)\/([^:\s]+)(?::([^/\s]+))?$/i,async e=>{let[,t,a,s,c]=e.msg.match(l.reg),u=e.selfId,d=e.groupId,f=o.GitHub;t?.toLowerCase()===`gitcode`?f=o.GitCode:t?.toLowerCase()===`gitee`?f=o.Gitee:t?.toLowerCase()===`cnb`&&(f=o.Cnb);let p=c||`main`,m=await r(u,d,a,s);if(!m)return await e.reply(`仓库不存在,删除失败`);if(!await n(o.GitHub,m.id,p))return await e.reply(`推送订阅不存在,删除失败`);await i(f,m.id,p),await e.reply(`删除订阅仓库成功, 平台: ${f}, 仓库: ${a}/${s}, 分支: ${p}`)},{name:`karin-plugin-git:removeRepo`,priority:500,event:`message.group`,permission:`master`}),u=s.command(/^#?git(?:设置|set)([^\s]+)?(?:token|访问令牌)([\s\S]+)$/i,async e=>{let[,t,n]=e.msg.match(u.reg),r=o.GitHub;t?.toLowerCase()===`gitcode`?r=o.GitCode:t?.toLowerCase()===`gitee`?r=o.Gitee:t?.toLowerCase()===`cnb`&&(r=o.Cnb),a.Modify(r,`token`,n),await e.reply(`设置${r}访问令牌成功`)},{name:`karin-plugin-git:SetToken`,priority:500,event:`message.friend`,permission:`master`});export{c as AddRepo,l as RemoveRepo,u as SetToken};
@@ -0,0 +1 @@
1
+ import{t as e}from"../root-C9I_RrRd.js";import{a as t}from"../common-OZlZxDcC.js";import n,{requireFile as r}from"node-karin";import i from"markdown-it";const a=n.command(/^#?(?:(git))(?:命令|帮助|菜单|help|说明|功能|指令|使用说明)$/i,async e=>{let n=e.isMaster?`master`:`member`,r=await t.render(`help/index`,{role:n});return await e.reply(r),!0},{name:`karin-plugin-git:help`,priority:500,event:`message`,permission:`all`}),o=n.command(/^#?(?:(git))(?:版本|版本信息|version|versioninfo)$/i,async n=>{let a=new i({html:!0}).render(await r(`${e.Plugin_Path}/CHANGELOG.md`)),o=await t.render(`help/version-info`,{Markdown:a});return await n.reply(o),!0},{name:`karin-plugin-git:version`,priority:500,event:`message`,permission:`all`});export{a as help,o as version};
@@ -0,0 +1,5 @@
1
+ import"../root-C9I_RrRd.js";import{a as e,c as t,r as n}from"../db-D0PoPjmA.js";import{a as r,i,n as a,o,r as s,t as c}from"../common-OZlZxDcC.js";import{t as l}from"../types-BuMDb1Mk.js";import u,{common as d,contactGroup as f,getBot as p,logger as m}from"node-karin";import{isEmpty as h}from"es-toolkit/compat";import g from"dayjs";import _ from"dayjs/plugin/relativeTime.js";import"dayjs/locale/zh-cn.js";const v=e=>(g.extend(_),g.locale(`zh-cn`),g(e).fromNow()),y=u.task(`karin-plugin-git:push:github`,o.github.cron||`0 */5 * * * *`,async()=>{let e=o.github.token;if(h(e))return m.warn(`未配置GitHub Token, 跳过任务`);try{await w(i(),l.GitHub)}catch(e){m.error(e)}}),b=u.task(`karin-plugin-git:push:gitee`,o.gitee.cron||`0 */5 * * * *`,async()=>{let e=o.gitee.token;if(h(e))return m.warn(`Gitee Token, 跳过任务`);try{await w(s(),l.Gitee)}catch(e){m.error(e)}}),x=u.task(`karin-plugin-git:push:gitee`,o.gitcode.cron||`0 */5 * * * *`,async()=>{let e=o.gitcode.token;if(h(e))return m.warn(`GitCode Token, 跳过任务`);try{await w(a(),l.GitCode)}catch(e){m.error(e)}}),S=u.task(`karin-plugin-git:push:cnb`,o.cnb.cron||`0 */5 * * * *`,async()=>{let e=o.cnb.token;if(h(e))return m.warn(`未配置CNB Token, 跳过任务`);try{await w(c(),l.Cnb)}catch(e){m.error(e)}}),C=u.command(/^#?git(?:推送|push)订阅仓库$/i,async t=>{try{let u=t.selfId,d=t.groupId,f=await e(),p,g=[];for(let e of f){let f=await n(e.repoId);if(!f||f.botId!=u||f.groupId!=d)continue;if(e.platform==l.Gitee){if(h(o.gitee.token))return await t.reply(`未配置Gitee Token, 请先配置Gitee Token`);p=s()}else if(e.platform==l.GitCode){if(h(o.gitcode.token))return await t.reply(`未配置GitCode Token, 请先配置GitCode Token`);p=a()}else if(e.platform==l.Cnb){if(h(o.cnb.token))return await t.reply(`Cnb Token, 请先配置Cnb Token`);p=c()}else{if(h(o.github.token))return await t.reply(`未配置GitHub Token, 请先配置GitHub Token`);p=i()}let _;try{_=await p.getCommitInfo(f.owner,f.repo,e.branch)}catch(t){m.warn(`获取仓库 ${f.owner}/${f.repo} 分支 ${e.branch} 提交信息失败:`,t);continue}let y=_.commit.message.split(`
2
+ `),b={..._,owner:f.owner,repo:f.repo,branch:e.branch,botId:u,groupId:d,title:await r.markdown(y[0]),body:await r.markdown(y.slice(1).join(`
3
+ `)),commitDate:v(_.commit.committer.date)},x=await r.render(`commit/index`,{commit:b});g.push(x)}g.length>0&&await T(u,d,g)}catch(e){m.error(e)}},{name:`karin-plugin-git:pushRepo`,priority:500,event:`message.group`,permission:`master`}),w=async(i,a)=>{let o=await e();if(h(o))return;let s=o.filter(e=>e.platform===a),c=new Map;for(let e of s){let t=await n(e.repoId);if(!t)continue;let r=await i.getCommitInfo(t.owner,t.repo,e.branch);if(r.sha===e.commitSha)continue;let a=`${t.botId}-${t.groupId}`;c.has(a)||c.set(a,[]),c.get(a).push({pushRepo:e,pushRepoInfo:t,commitInfo:r})}for(let[e,n]of c.entries()){let[i,o]=e.split(`-`),s=[];for(let e of n){let n=e.commitInfo.commit.message.split(`
4
+ `),i={...e.commitInfo,owner:e.pushRepoInfo.owner,repo:e.pushRepoInfo.repo,branch:e.pushRepo.branch,botId:e.pushRepoInfo.botId,groupId:e.pushRepoInfo.groupId,title:await r.markdown(n[0]),body:await r.markdown(n.slice(1).join(`
5
+ `)),commitDate:v(e.commitInfo.commit.committer.date)},o=await r.render(`commit/index`,{commit:i});s.push(o),await t(a,e.pushRepo.repoId,e.pushRepo.branch,e.commitInfo.sha)}s.length>0&&await T(i,o,s)}},T=async(e,t,n)=>{let r=p(e),i=await f(t);if(n.length>1){let t=await d.makeForward(n,e,r?.account.name);await r?.sendForwardMsg(i,t,{source:`仓库推送合集`,summary:`查看${t.length}张仓库推送消息`,prompt:`Gitub仓库推送结果`,news:[{text:`点击查看推送结果`}]})}else await r?.sendMsg(i,n)};export{S as cnb,x as gitcode,b as gitee,y as github,C as push};
@@ -0,0 +1 @@
1
+ import{t as e}from"./root-C9I_RrRd.js";import t,{YamlEditor as n,copyConfigSync as r,filesByExt as i,getFiles as a,karinPathBase as o,requireFileSync as s,segment as c,watch as l}from"node-karin";import u from"node:path";import{full as d}from"markdown-it-emoji";import{tasklist as f}from"@mdit/plugin-tasklist";import p from"markdown-it";import{isEmpty as m}from"es-toolkit/compat";import{CnbClient as h,GitCodeClient as g,GiteeClient as _,GithubClient as v}from"nipaw";var y=class{dirCfgPath;defCfgPath;constructor(){this.dirCfgPath=`${o}/${e.Plugin_Name}/config/`,this.defCfgPath=`${e.Plugin_Path}/config/defSet/`}initCfg(){r(this.defCfgPath,this.dirCfgPath);let e=i(this.dirCfgPath,`.yaml`,`name`);for(let t of e){let e=new n(`${this.dirCfgPath}/${t}`),r=new n(`${this.defCfgPath}/${t}`),{differences:i,result:a}=this.mergeObjectsWithPriority(e,r);i&&a.save()}return i(this.dirCfgPath,`.yaml`,`abs`).forEach(e=>l(e,(e,t)=>{})),this}getDefOrConfig(e){let t=this.getYaml(`defSet`,e),n=this.getYaml(`config`,e);return{...t,...n}}All(){let e={};return a(this.defCfgPath,[`.yaml`]).forEach(t=>{let n=u.basename(t,`.yaml`);e[n]=this.getDefOrConfig(n)??{}}),e}getYaml(e,t){return s(e===`config`?`${this.dirCfgPath}/${t}.yaml`:`${this.defCfgPath}/${t}.yaml`,{force:!0})}Modify(e,t,r,i=`config`){let a=new n(i===`config`?`${this.dirCfgPath}/${e}.yaml`:`${this.defCfgPath}/${e}.yaml`);a.set(t,r),a.save()}mergeObjectsWithPriority(e,t){let n=!1;return((t,r)=>{let i=r.get(t),a=e.get(t);if(typeof a==`object`&&typeof i==`object`)for(let r in i)r in a||(n=!0,e.set(`${t?`${t}.`:``}${r}`,i[r]))})(``,t),{differences:n,result:e}}};const b=new Proxy(Object.assign(new y().initCfg(),{}),{get(e,t){return t in e?Reflect.get(e,t):e.getDefOrConfig(t)}});function x(e=1){return e*=1.5,`style=transform:scale(${e})`}const S={async render(n,r={}){n=n.replace(/.html$/,``);let i=`${e.Plugin_Path}/resources`,a=await t.render({type:`jpeg`,encoding:`base64`,name:u.basename(n),file:`${i}/${n}.html`,data:{_res_path:`${e.Plugin_Path}/resources`.replace(/\\/g,`/`),defaultLayout:`${e.Plugin_Path}/resources/common/layout/default.html`.replace(/\\/g,`/`),sys:{scale:x(r.scale??1)},copyright:`${e.Bot_Name}<span class="version"> ${e.Bot_Version}</span> & ${e.Plugin_Name}<span class="version"> ${e.Plugin_Version}`,...r},screensEval:`#containter`,multiPage:12e3,pageGotoParams:{waitUntil:`networkidle0`,timeout:6e4}});return c.image(`${a.includes(`base64://`)?a:`base64://${a}`}`)},async markdown(e){let t=new p({html:!0,breaks:!0});return t.use(d),t.use(f),t.renderer.rules.bullet_list_open=()=>`<ul style="list-style: none;">`,Promise.resolve(t.render(e))}},C=()=>{let e=new v;return m(b.github.proxy)||e.setProxy(b.github.proxy),m(b.github.token)||e.setToken(b.github.token),e},w=()=>{let e=new _;return m(b.gitee.proxy)||e.setProxy(b.gitee.proxy),m(b.gitee.token)||e.setToken(b.gitee.token),e},T=()=>{let e=new g;return m(b.gitcode.proxy)||e.setProxy(b.gitcode.proxy),m(b.gitcode.token)||e.setToken(b.gitcode.token),e},E=()=>{let e=new h;return m(b.cnb.proxy)||e.setProxy(b.cnb.proxy),m(b.cnb.token)||e.setToken(b.cnb.token),e};export{S as a,C as i,T as n,b as o,w as r,E as t};
@@ -0,0 +1,23 @@
1
+ import{t as e}from"./root-C9I_RrRd.js";import{karinPathBase as t}from"node-karin";import n from"node-karin/sqlite3";async function r(e,t,n){await(await d()).run(`INSERT INTO push (platform,repoId, branch) VALUES (?, ?, ?)`,[e,t,n])}async function i(){let e=await d();return await new Promise((t,n)=>{e.all(`SELECT * FROM push`,[],(e,r)=>{e?n(e):t(r)})})}async function a(e,t,n){let r=await d();return await new Promise((i,a)=>{r.get(`SELECT * FROM push WHERE platform = ? AND repoId = ? AND branch = ?`,[e,t,n],(e,t)=>{e?a(e):i(t)})})}async function o(e,t,n){let r=await d();await new Promise((i,a)=>{r.run(`DELETE FROM push WHERE platform = ? AND repoId = ? AND branch = ?`,[e,t,n],e=>{e?a(e):i()})})}async function s(e,t,n,r){await(await d()).run(`UPDATE push SET commitSha = ? WHERE platform = ? AND repoId = ? AND branch = ?`,[r,e,t,n])}async function c(e,t,n,r){await(await d()).run(`INSERT INTO repo (owner, repo, botId, groupId) VALUES (?, ?, ?, ?)`,[n,r,e,t])}async function l(...e){let t=await d();if(e.length===1){let[n]=e;return await new Promise((e,r)=>{t.get(`SELECT * FROM repo WHERE id = ?`,[n],(t,n)=>{t?r(t):e(n)})})}else{let[n,r,i,a]=e;return await new Promise((e,o)=>{t.get(`SELECT * FROM repo WHERE owner = ? AND repo = ? AND botId = ? AND groupId = ?`,[i,a,n,r],(t,n)=>{t?o(t):e(n)})})}}let u=null;const d=async()=>{if(!u){let r=`${t}/${e.Plugin_Name}/data`;u=new n.Database(`${r}/data.db`)}return u},f=async()=>{let e=await d();e.exec(`
2
+ CREATE TABLE IF NOT EXISTS repo (
3
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ owner TEXT NOT NULL,
5
+ repo TEXT NOT NULL,
6
+ botId TEXT NOT NULL,
7
+ groupId TEXT NOT NULL,
8
+ createdAt DATETIME DEFAULT (datetime('now', 'localtime')),
9
+ updatedAt DATETIME DEFAULT (datetime('now', 'localtime')),
10
+ UNIQUE(owner, repo, botId, groupId)
11
+ )
12
+ `),e.exec(`
13
+ CREATE TABLE IF NOT EXISTS push (
14
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
15
+ repoId INTEGER NOT NULL,
16
+ platform TEXT NOT NULL,
17
+ branch TEXT NOT NULL,
18
+ commitSha TEXT,
19
+ createdAt DATETIME DEFAULT (datetime('now', 'localtime')),
20
+ updatedAt DATETIME DEFAULT (datetime('now', 'localtime')),
21
+ FOREIGN KEY (repoId) REFERENCES repo(id) ON DELETE CASCADE
22
+ )
23
+ `),e.exec(`CREATE INDEX IF NOT EXISTS idx_repo_lookup ON repo(botId, groupId)`),e.exec(`CREATE INDEX IF NOT EXISTS idx_push_repo ON push(repoId)`),e.exec(`CREATE INDEX IF NOT EXISTS idx_push_platform ON push(platform)`)};export{i as a,s as c,r as i,c as n,a as o,l as r,o as s,f as t};
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ import{t as e}from"./root-C9I_RrRd.js";import{t}from"./db-D0PoPjmA.js";import{logger as n}from"node-karin";import r from"node-karin/axios";const i=async()=>{let i=`加载失败`;try{i=(await r.get(`https://api.wuliya.cn/api/image/count?name=${e.Plugin_Name}&type=json`,{timeout:500})).data.data.count}catch{n.error(n.chalk.red.bold(`⚠️ 访问统计数据失败,超时或网络错误`))}await t(),n.info(n.chalk.bold.rgb(0,255,0)(`========= 🌟🌟🌟 =========`)),n.info(n.chalk.bold.blue(`🌍 当前运行环境: `)+n.chalk.bold.white(`${e.Bot_Name}`)+n.chalk.gray(` | `)+n.chalk.bold.green(`🏷️ 运行版本: `)+n.chalk.bold.white(`V${e.Bot_Version}`)+n.chalk.gray(` | `)+n.chalk.bold.yellow(`📊 运行插件总访问/运行次数: `)+n.chalk.bold.cyan(i)),n.info(n.chalk.bold.rgb(255,215,0)(`✨ ${e.Plugin_Name} `)+n.chalk.bold.rgb(255,165,0).italic(e.Plugin_Version)+n.chalk.rgb(255,215,0).bold(` 载入成功 ^_^`)),n.info(n.chalk.green.bold(`=========================`))};export{i as KARIN_PLUGIN_INIT};
@@ -0,0 +1 @@
1
+ import{config as e,requireFileSync as t}from"node-karin";import n from"node:path";import{fileURLToPath as r}from"node:url";const i=r(import.meta.url).replace(/\\/g,`/`),a=n.resolve(i,`../../`).replace(/\\/g,`/`),o=n.basename(a),s=t(`${a}/package.json`),c=Object.freeze(a.includes(`node_modules`)),l={get Bot_Name(){return e.pkg().name===`node-karin`?`Karin`:e.pkg().name},get Bot_Version(){return e.pkg().version},get Bot_Path(){return process.cwd().replace(/\\/g,`/`)},get Plugin_Path(){return a},get Plugin_Name(){return c||process.env.NODE_ENV===`development`?s.name:o},get Plugin_Version(){return s.version},get Plugin_Anthor(){return s.author}};export{l as t};
@@ -0,0 +1 @@
1
+ let e=function(e){return e.GitHub=`github`,e.Gitee=`gitee`,e.GitCode=`gitcode`,e.Cnb=`cnb`,e}({});export{e as t};
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@candriajs/karin-plugin-git",
3
+ "version": "1.1.1",
4
+ "description": "一个karin的git平台仓库订阅推送",
5
+ "keywords": [
6
+ "karin-plugin",
7
+ "karin-plugin-git"
8
+ ],
9
+ "homepage": "https://github.com/CandriaJS/karin-plugin-git",
10
+ "bugs": {
11
+ "url": "https://github.com/CandriaJS/karin-plugin-git/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/CandriaJS/karin-plugin-git.git"
16
+ },
17
+ "license": "GNU General Public License v3.0",
18
+ "author": "CandriaJS",
19
+ "type": "module",
20
+ "main": "lib/index.js",
21
+ "files": [
22
+ "config/",
23
+ "lib/",
24
+ "resources/",
25
+ "LICENSE",
26
+ "package.json",
27
+ "README.md",
28
+ "CHANGELOG.md"
29
+ ],
30
+ "scripts": {
31
+ "app": "node --import tsx src/app.ts",
32
+ "build": "tsc --noEmit && tsdown",
33
+ "dev": "cross-env EBV_FILE=\"development.env\" node --import tsx src/app.ts",
34
+ "lint": "eslint .",
35
+ "lint:fix": "eslint . --fix",
36
+ "pub": "npm publish --access public",
37
+ "sort": "sort-package-json",
38
+ "watch": "cross-env EBV_FILE=\"development.env\" tsx watch --include \"src/**/*.ts\" src/app.ts"
39
+ },
40
+ "dependencies": {
41
+ "@mdit/plugin-tasklist": "^0.22.2",
42
+ "dayjs": "^1.11.19",
43
+ "es-toolkit": "^1.41.0",
44
+ "markdown-it": "^14.1.0",
45
+ "markdown-it-emoji": "^3.0.0",
46
+ "nipaw": "npm:@puniyu/nipaw@^1.6.1"
47
+ },
48
+ "devDependencies": {
49
+ "@karinjs/plugin-puppeteer": "^1.0.21",
50
+ "@prettier/plugin-oxc": "^0.0.4",
51
+ "@types/express": "^5.0.5",
52
+ "@types/markdown-it": "^14.1.2",
53
+ "@types/markdown-it-emoji": "^3.0.1",
54
+ "@types/node": "^22.15.3",
55
+ "cross-env": "^7.0.3",
56
+ "node-karin": "^1.12.2",
57
+ "oxlint": "^1.26.0",
58
+ "prettier": "^3.6.2",
59
+ "tsc-alias": "1.8.13",
60
+ "tsdown": "^0.15.12",
61
+ "tsx": "^4.19.4",
62
+ "typescript": "^5.8.3"
63
+ },
64
+ "karin": {
65
+ "main": "src/index.ts",
66
+ "web": "./lib/web.config.js",
67
+ "ts-web": "./src/web.config.ts",
68
+ "apps": [
69
+ "lib/apps"
70
+ ],
71
+ "ts-apps": [
72
+ "src/apps"
73
+ ],
74
+ "static": [
75
+ "resources"
76
+ ],
77
+ "files": [
78
+ "config",
79
+ "data",
80
+ "resources"
81
+ ],
82
+ "engines": {
83
+ "karin": ">=1.9.1"
84
+ }
85
+ },
86
+ "packageManager": "pnpm@10.14.0"
87
+ }
@@ -0,0 +1,293 @@
1
+ @font-face {
2
+ font-family: 'Noto Color Emoji';
3
+ src: url('../fonts/NotoColorEmoji-Regular.woff2') format('woff2');
4
+ }
5
+
6
+ @font-face {
7
+ font-family: 'Smiley Sans';
8
+ src: url('../fonts/SmileySans-Oblique.woff2') format('woff2');
9
+ font-display: swap;
10
+ }
11
+
12
+ @font-face {
13
+ font-family: 'Douyin Sans';
14
+ src: url('../fonts/DouyinSansBold.woff2') format('woff2');
15
+ font-display: swap;
16
+ }
17
+
18
+ * {
19
+ margin: 0;
20
+ padding: 0;
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ .container {
25
+ font-family: 'Douyin Sans', 'Smiley Sans', 'Noto Color Emoji', sans-serif;
26
+ display: flex;
27
+ justify-content: center;
28
+ align-items: flex-start;
29
+ min-height: 100vh;
30
+ min-width: 800px;
31
+ width: 100%;
32
+ padding: 20px;
33
+ background: rgba(200, 200, 200, 0.85);
34
+ }
35
+
36
+ .info-section {
37
+ display: flex;
38
+ flex-direction: column;
39
+ width: 100%;
40
+ max-width: 800px;
41
+ padding: 50px;
42
+ margin: 0 auto;
43
+ }
44
+
45
+ .platform-name {
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ gap: 12px;
50
+ margin-bottom: 32px;
51
+ color: #4b5563;
52
+ }
53
+
54
+ .header h2 {
55
+ font-size: 32px;
56
+ font-weight: 700;
57
+ letter-spacing: -0.5px;
58
+ }
59
+
60
+ .commit-card {
61
+ width: 100%;
62
+ background: rgba(248, 250, 255, 0.8);
63
+ border: 1px solid rgba(255, 255, 255, 0.4);
64
+ border-radius: 16px;
65
+ padding: 24px;
66
+ margin-bottom: 24px;
67
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
68
+ }
69
+
70
+ .repo-header {
71
+ display: flex;
72
+ align-items: center;
73
+ gap: 16px;
74
+ width: 100%;
75
+ margin-bottom: 20px;
76
+ }
77
+
78
+ .repo-info {
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: 8px;
82
+ }
83
+
84
+ .platform-icon img {
85
+ width: 50px;
86
+ height: 50px;
87
+ padding-left: 5px;
88
+ }
89
+
90
+ .repo-name {
91
+ font-size: 25px;
92
+ font-weight: 800;
93
+ color: #0f0f23;
94
+ letter-spacing: -0.3px;
95
+ }
96
+
97
+ .commit-sha-info {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 6px;
101
+ color: #666;
102
+ background: rgba(158, 158, 158, 0.2);
103
+ border-radius: 15px;
104
+ font-size: 14px;
105
+ padding: 5px 10px;
106
+ }
107
+
108
+ .commit-sha-info img {
109
+ width: 24px;
110
+ height: 24px;
111
+ opacity: 0.7;
112
+ }
113
+
114
+ .branch-info {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 6px;
118
+ color: #666;
119
+ font-size: 14px;
120
+ background: rgba(158, 158, 158, 0.2);
121
+ padding: 5px 15px;
122
+ border-radius: 20px;
123
+ white-space: nowrap;
124
+ margin-left: auto;
125
+ }
126
+
127
+ .commit-info {
128
+ background: rgba(59, 130, 246, 0.1);
129
+ border: 1px solid rgba(59, 130, 246, 0.2);
130
+ border-radius: 12px;
131
+ padding: 16px;
132
+ margin-top: 16px;
133
+ display: flex;
134
+ align-items: flex-start;
135
+ gap: 12px;
136
+ flex-direction: column;
137
+ overflow: hidden;
138
+ backdrop-filter: blur(10px);
139
+ }
140
+
141
+ .avatar-info {
142
+ display: flex;
143
+ align-items: center;
144
+ gap: 8px;
145
+ flex-wrap: wrap;
146
+ width: 100%;
147
+ }
148
+
149
+ .avatar-group {
150
+ display: flex;
151
+ position: relative;
152
+ margin-right: 8px;
153
+ flex-shrink: 0;
154
+ }
155
+
156
+ .author-avatar img,
157
+ .committer-avatar img {
158
+ width: 40px;
159
+ height: 40px;
160
+ border-radius: 50%;
161
+ border: 3px solid rgba(255, 255, 255, 0.9);
162
+ object-fit: cover;
163
+ background-color: #fff;
164
+ display: block;
165
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
166
+ }
167
+
168
+ .dual-avatars {
169
+ display: flex;
170
+ position: relative;
171
+ margin-right: 10px;
172
+ position: relative;
173
+ }
174
+
175
+ .author-info > span {
176
+ white-space: nowrap;
177
+ overflow: hidden;
178
+ text-overflow: ellipsis;
179
+ color: #2d3748;
180
+ font-size: 14px;
181
+ }
182
+
183
+ .committer-avatar {
184
+ margin-left: -14px;
185
+ z-index: 1;
186
+ }
187
+
188
+ .author-info .author-avatar img {
189
+ border: 3px solid rgba(255, 255, 255, 0.9);
190
+ }
191
+
192
+ .time-info {
193
+ color: #718096;
194
+ background: rgba(158, 158, 158, 0.2);
195
+ font-size: 13px;
196
+ margin-left: auto;
197
+ white-space: nowrap;
198
+ flex-shrink: 0;
199
+ padding: 6px 12px;
200
+ border-radius: 15px;
201
+ text-align: right;
202
+ }
203
+
204
+ .commit-icon img {
205
+ width: 24px;
206
+ height: 24px;
207
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
208
+ }
209
+
210
+ .commit-message {
211
+ margin-top: 16px;
212
+ background: rgba(34, 197, 94, 0.08);
213
+ border-left: 4px solid #22c55e;
214
+ border-radius: 12px;
215
+ padding: 18px;
216
+ backdrop-filter: blur(10px);
217
+ border: 1px solid rgba(34, 197, 94, 0.2);
218
+ }
219
+
220
+ .commit-title {
221
+ display: flex;
222
+ align-items: center;
223
+ gap: 12px;
224
+ min-width: 0;
225
+ width: 100%;
226
+ color: #1f2937;
227
+ font-size: 15px;
228
+ font-weight: 600;
229
+ }
230
+
231
+ .commit-title > span:first-child {
232
+ flex: 1 1 auto;
233
+ min-width: 0;
234
+ width: auto;
235
+ text-overflow: ellipsis;
236
+ padding-right: 16px;
237
+ word-break: break-word;
238
+ color: #0f0f23;
239
+ }
240
+
241
+ .code-changes {
242
+ display: flex;
243
+ align-items: center;
244
+ flex-shrink: 0;
245
+ gap: 12px;
246
+ margin-left: auto;
247
+ padding-left: 16px;
248
+ white-space: nowrap;
249
+ background: rgba(255, 255, 255, 0.5);
250
+ padding: 8px 12px;
251
+ border-radius: 8px;
252
+ font-size: 13px;
253
+ }
254
+
255
+ .code-changes span {
256
+ font-size: 14px;
257
+ line-height: 1.5;
258
+ font-weight: 600;
259
+ }
260
+
261
+ .changes-added {
262
+ color: #16a34a;
263
+ }
264
+
265
+ .changes-deleted {
266
+ color: #dc2626;
267
+ }
268
+
269
+ .changes-divider {
270
+ color: #cbd5e1;
271
+ }
272
+
273
+ .commit-icon {
274
+ display: inline-flex;
275
+ flex-shrink: 0;
276
+ }
277
+
278
+ .commit-divider {
279
+ height: 1px;
280
+ background: rgba(0, 0, 0, 0.2);
281
+ width: 100%;
282
+ margin-top: 12px;
283
+ margin-bottom: 12px;
284
+ }
285
+
286
+ .commit-content {
287
+ padding-left: 0;
288
+ padding-top: 8px;
289
+ white-space: pre-line;
290
+ color: #4b5563;
291
+ font-size: 14px;
292
+ line-height: 1.6;
293
+ }
@@ -0,0 +1,122 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="utf-8" />
4
+ <meta name="viewport" content="width=device-width" />
5
+ <link
6
+ href="{{_res_path}}/commit/index.css"
7
+ rel="stylesheet"
8
+ type="text/css"
9
+ />
10
+ </head>
11
+
12
+ <body>
13
+ <div class="container" id="container">
14
+ <div class="info-section">
15
+ <div class="platform-name">
16
+ {{if platform === 'github'}}
17
+ <h2>GitHub 仓库更新推送</h2>
18
+ {{else if platform === 'gitee'}}
19
+ <h2>Gitee 仓库更新推送</h2>
20
+ {{else if platform === 'gitcode'}}
21
+ <h2>GitCode 仓库更新推送</h2>
22
+ {{else if platform === 'cnb'}}
23
+ <h2>Cnb 仓库更新推送</h2>
24
+ {{else}}
25
+ <h2>GitHub 仓库更新推送</h2>
26
+ {{/if}}
27
+ </div>
28
+
29
+ <div class="commit-card">
30
+ <div class="repo-header">
31
+ <div class="platform-icon">
32
+ {{if platform === 'github'}}
33
+ <img src="{{_res_path}}/icons/github.svg" alt="GitHub Logo" />
34
+ {{else if platform === 'gitee'}}
35
+ <img src="{{_res_path}}/icons/gitee.svg" alt="Gitee Logo" />
36
+ {{else if platform === 'gitcode'}}
37
+ <img src="{{_res_path}}/icons/gitcode.svg" alt="Gitcode Logo" />
38
+ {{else if platform === 'gitcode'}}
39
+ <img src="{{_res_path}}/icons/cnb.svg" alt="Cnb Logo" />
40
+ {{else}}
41
+ <img src="{{_res_path}}/icons/github.svg" alt="GitHub Logo" />
42
+ {{/if}}
43
+ </div>
44
+ <div class="repo-info">
45
+ <div class="repo-name">{{commit.owner}}/{{commit.repo}}</div>
46
+ <div class="commit-sha-info">
47
+ <div class="commit-sha-icon">
48
+ <img src="{{_res_path}}/icons/commit.svg" alt="Commit Icon" />
49
+ </div>
50
+ <span class="commit-sha">{{ commit.sha }}</span>
51
+ </div>
52
+ </div>
53
+ <div class="branch-info">
54
+ <div class="branch-icon">
55
+ <img src="{{_res_path}}/icons/branch.svg" alt="Branch Icon" />
56
+ </div>
57
+ <span class="branch-name">{{ commit.branch }}</span>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="commit-info">
62
+ <div class="avatar-info">
63
+ {{if commit.commit.author.name === commit.commit.committer.name }}
64
+ <div class="author-avatar">
65
+ <img
66
+ src="{{ commit.commit.author.avatarUrl }}"
67
+ alt="Author Avatar"
68
+ />
69
+ </div>
70
+ <span>由 {{ commit.commit.author.name }} 提交</span>
71
+ <span class="time-info">{{ commit.commitDate }}</span>
72
+ {{else}}
73
+ <div class="avatar-group">
74
+ <div class="author-avatar">
75
+ <img
76
+ src="{{ commit.commit.author.avatarUrl }}"
77
+ alt="Author Avatar"
78
+ title="作者"
79
+ />
80
+ </div>
81
+ <div class="committer-avatar">
82
+ <img
83
+ src="{{ commit.commit.committer.avatarUrl }}"
84
+ alt="Committer Avatar"
85
+ title="提交者"
86
+ />
87
+ </div>
88
+ </div>
89
+ <span
90
+ >由 {{ commit.commit.author.name }} 编写,并由 {{
91
+ commit.commit.committer.name }} 提交</span
92
+ >
93
+ <span class="time-info">{{ commit.commitDate }}</span>
94
+ {{/if}}
95
+ </div>
96
+ </div>
97
+
98
+ <div class="commit-message">
99
+ <div class="commit-title">
100
+ <div class="commit-icon">
101
+ <img src="{{_res_path}}/icons/commit.svg" alt="Commit Icon" />
102
+ </div>
103
+ <span>{{@commit.title}}</span>
104
+ <div class="code-changes">
105
+ <span class="changes-added">+{{ commit.stats.additions }}</span>
106
+ <span class="changes-deleted"
107
+ >-{{ commit.stats.deletions }}</span
108
+ >
109
+ <span class="changes-divider">•</span>
110
+ <span>{{ commit.changeFiles }} 个文件被更改</span>
111
+ </div>
112
+ </div>
113
+ <div class="commit-divider"></div>
114
+ {{if commit.body }}
115
+ <div class="commit-content">{{@commit.body}}</div>
116
+ {{/if}}
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </body>
122
+ </html>