Code Rebase - 1.0.0 by itzdrli

This commit is contained in:
Letian Li 2025-05-03 16:24:53 +02:00
parent 50cba9e6be
commit db1a9e33e6
6 changed files with 84 additions and 53 deletions

View File

@ -1,6 +0,0 @@
pull_request_title: 'i18n: update translations'
pull_request_labels:
- i18n
files:
- source: /src/locales/zh-CN.yml
translation: /src/locales/%locale%.yml

View File

@ -1,25 +1,25 @@
{
"name": "koishi-plugin-market-info",
"name": "koishi-plugin-market-info-plus",
"description": "Koishi plugin market information",
"version": "2.1.0",
"version": "1.0.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"files": [
"lib",
"dist"
],
"author": "Shigma <shigma10826@gmail.com>",
"author": "itzdrli <itzdrli@proton.me>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/koishijs/koishi-plugin-market-info.git"
"url": "git+https://github.com/itzdrli/koishi-plugin-market-info-plus.git"
},
"bugs": {
"url": "https://github.com/koishijs/koishi-plugin-market-info/issues"
"url": "https://github.com/itzdrli/koishi-plugin-market-info-plus/issues"
},
"homepage": "https://github.com/koishijs/koishi-plugin-market-info#readme",
"homepage": "https://github.com/itzdrli/koishi-plugin-market-info-plus#readme",
"scripts": {
"build": "atsc -b"
"build": "yakumo build"
},
"koishi": {
"description": {
@ -39,13 +39,14 @@
"manager"
],
"peerDependencies": {
"koishi": "^4.15.0"
"koishi": "^4.17.0"
},
"devDependencies": {
"@koishijs/registry": "^6.0.4",
"@types/node": "^20.8.10",
"atsc": "^1.2.2",
"koishi": "^4.15.0",
"koishi-plugin-puppeteer": "^3.9.0",
"typescript": "^5.2.2"
}
}

View File

@ -1,8 +1,10 @@
import { Context, Dict, Schema, Time, deepEqual, pick, sleep } from 'koishi'
import {} from '@koishijs/plugin-market'
import type { SearchObject, SearchResult } from '@koishijs/registry'
import { } from 'koishi-plugin-puppeteer'
import { renderMarketUpdate } from './renderImage'
export const name = 'market-info'
export const name = 'market-info-plus'
interface Receiver {
platform: string
@ -11,6 +13,8 @@ interface Receiver {
guildId?: string
}
export const inject = ["puppeteer"]
const Receiver: Schema<Receiver> = Schema.object({
platform: Schema.string().required().description('平台名称。'),
selfId: Schema.string().required().description('机器人 ID。'),
@ -30,7 +34,7 @@ export interface Config {
export const Config: Schema<Config> = Schema.object({
rules: Schema.array(Receiver).role('table').description('推送规则列表。'),
endpoint: Schema.string().default('https://registry.koishi.chat/index.json').description('插件市场地址。'),
endpoint: Schema.string().default('https://kp.itzdrli.cc').description('插件市场地址。'),
interval: Schema.number().default(Time.minute * 30).description('轮询间隔 (毫秒)。'),
showHidden: Schema.boolean().default(false).description('是否显示隐藏的插件。'),
showDeletion: Schema.boolean().default(false).description('是否显示删除的插件。'),
@ -39,9 +43,7 @@ export const Config: Schema<Config> = Schema.object({
})
export function apply(ctx: Context, config: Config) {
ctx.i18n.define('zh', require('./locales/zh-CN'))
const logger = ctx.logger('market')
const logger = ctx.logger('market-info-plus')
const makeDict = (result: SearchResult) => {
const dict: Dict<SearchObject> = {}
@ -72,24 +74,25 @@ export function apply(ctx: Context, config: Config) {
)
})
if (options.receive) {
if (index >= 0) return session.text('.not-modified')
if (index >= 0) return `未修改订阅信息。`
config.rules.push(pick(session, ['platform', 'selfId', 'channelId', 'guildId']))
} else {
if (index < 0) return session.text('.not-modified')
if (index < 0) return `未修改订阅信息。`
config.rules.splice(index, 1)
}
ctx.scope.update(config, false)
return session.text('.updated')
return `已更新订阅信息。`
}
if (!name) {
const objects = Object.values(previous).filter(data => !data.manifest.hidden)
return session.text('.overview', [objects.length])
return `当前共有 ${objects.length} 个插件`
}
const data = previous[name]
if (!data) return session.text('.not-found', [name])
return session.text('.detail', data)
if (!data) `未找到插件 ${name}`
return `${data.shortname} (${data.package.version})\n\n` +
`发布者:@${data.package.publisher.username}`
})
ctx.setInterval(async () => {
@ -97,10 +100,12 @@ export function apply(ctx: Context, config: Config) {
const diff = Object.keys({ ...previous, ...current }).map((name) => {
const version1 = previous[name]?.package.version
const version2 = current[name]?.package.version
if (version1 === version2) return
if (version1 === version2) {
return
}
if (!version1) {
let output = <p><i18n path="market-info.created"></i18n></p>
let output = `新增:${name} (${version2})`
if (config.showPublisher) output += ` (@${current[name].package.publisher.username})`
if (config.showDescription) {
const { description } = current[name].manifest
@ -126,13 +131,19 @@ export function apply(ctx: Context, config: Config) {
const content = ['[插件市场更新]', ...diff].join('\n')
logger.info(content)
// Generate image
const image = await renderMarketUpdate(ctx, config, diff, previous)
const delay = ctx.root.config.delay.broadcast
for (let index = 0; index < config.rules.length; ++index) {
if (index && delay) await sleep(delay)
const { platform, selfId, channelId, guildId } = config.rules[index]
const bot = ctx.bots.find(bot => bot.platform === platform && bot.selfId === selfId)
bot.sendMessage(channelId, content, guildId)
// Send both text and image
await bot.sendMessage(channelId, content, guildId)
await bot.sendMessage(channelId, image, guildId)
}
}, config.interval)
})
}
}

View File

@ -1,21 +0,0 @@
commands:
market:
description: 插件市场信息
messages:
overview: 当前共有 {0} 个插件。
not-found: 未找到插件 {0}。
updated: 已更新订阅信息。
not-modified: 未修改订阅信息。
detail: |-
{name} ({version})
{manifest.description.zh || manifest.description.en}
options:
receive.true: 订阅到此频道
receive.false: 取消订阅到此频道
market-info:
header: '[插件市场更新]'
created: 新增:{0}
updated: 更新:{0} ({1} → {2})`
deleted: 移除:{0}

40
src/renderImage.ts Normal file
View File

@ -0,0 +1,40 @@
import { Context } from 'koishi'
import { Config } from './index'
// Dark theme colors
const dark = ['#2e3440', '#ffffff', '#434c5e']
export async function renderMarketUpdate(ctx: Context, config: Config, diff: string[], previous: any) {
const cardHtml = diff.map(item => {
return `
<div class="col-4 flex flex-col h-full w-full min-w-[250px] max-w-[350px]">
<div class="bg-[${dark[2]}] shadow-lg rounded-2xl p-4 flex flex-col justify-between h-full">
<h2 class="text-lg font-semibold mb-2 flex-grow break-words text-[${dark[1]}]">${item}</h2>
</div>
</div>
`
}).join('')
const html = `
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-[${dark[0]}] text-[${dark[1]}]">
<div class="max-w-7xl mx-auto p-4">
<div class="text-center mb-5">
<div class="bg-[${dark[2]}] shadow-lg rounded-2xl py-4 px-6">
<p class="text-2xl font-bold text-[${dark[1]}]">[]</p>
</div>
</div>
<div class="grid grid-cols-4 gap-3">
${cardHtml}
</div>
</div>
</body>
`
return await ctx.puppeteer.render(html)
}

View File

@ -2,16 +2,22 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
"target": "es2020",
"module": "commonjs",
"target": "es2022",
"module": "esnext",
"emitDeclarationOnly": true,
"declaration": true,
"composite": true,
"incremental": true,
"skipLibCheck": true,
"esModuleInterop": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"resolveJsonModule": true,
"jsxImportSource": "@satorijs/element",
"types": [
"node",
"yml-register/types"
]
},
"include": [
"src"