Commit 99ae47b6 authored by nanahira's avatar nanahira

multi pic source

parent d21c4229
......@@ -57,7 +57,7 @@ export class PicSource {
```ts
import { Context } from "koishi";
import { DefinePlugin, RegisterSchema, SchemaProperty, LifecycleEvents } from "koishi-thirdeye";
import { PicSource, PicsContainer, PicSourceConfig } from "koishi-plugin-pics";
import { PicSourcePlugin, PicsContainer, PicSourceConfig } from "koishi-plugin-pics";
@RegisterSchema()
export class Config extends PicSourceConfig {
......@@ -72,58 +72,59 @@ export default class MyPicSource extends PicSourcePlugin<Config> {
return { url: `https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${this.config.code}.jpg`, description: `${this.config.code}` };
}
}
// 加载图源插件
ctx.plugin(MyPicSource, {
code: 10000,
name: 'my-picsource',
description: 'my-picsource'
});
```
#### 多图源
使用 `DefineMultiSourcePlugin` 方法创建多图源插件。该插件的配置具有 `instances` 数组属性,每一项都是一个图源的配置。
```ts
import { Context } from "koishi";
import { DefinePlugin, RegisterSchema, SchemaProperty, LifecycleEvents } from "koishi-thirdeye";
import { PicSource, PicsContainer, PicSourceConfig } from "koishi-plugin-pics";
import { PicSourcePlugin, PicsContainer, PicSourceConfig } from "koishi-plugin-pics";
@RegisterSchema()
export class InstanceConfig extends PicSourceConfig {
export class Config extends PicSourceConfig {
@SchemaProperty({ default: 10000 })
code: number;
}
@RegisterSchema()
export class Config {
constructor(config: Partial<InstanceConfig>[]) {}
@SchemaProperty({ type: InstanceConfig })
instances: InstanceConfig[];
}
export class MyPicSourceInstance extends PicSource {
constructor(ctx: Context, config: Partial<Config>) {
super(ctx);
config.applyTo(this);
}
// 不 default
@DefinePlugin({ name: 'my-picsource', schema: Config })
export class MyPicSource extends PicSourcePlugin<Config> {
async randomPic(tags: string[]) {
return { url: `https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${this.config.code}.jpg`, description: `${this.config.code}` };
}
}
@DefinePlugin({ name: 'my-picsource', schema: Config })
export default class MyPicSource extends BasePlugin<Config> implements LifecycleEvents {
@InjectConfig()
private config: Config;
@Inject(true)
private pics: PicsContainer;
onApply() {
for (const instanceConfig of this.config.instances) {
const instance = new MyPicSourceInstance(this.ctx, instanceConfig);
this.pics.addSource(instance);
}
}
}
// 在这里 default 加载插件
export default class MyMultiPicSource extends DefineMultiSourcePlugin(
MyPicSource,
PicSourceConfig,
) {}
// 加载图源插件
ctx.plugin(MyMultiPicSource, {
instances: [
{
code: 10000,
name: 'my-picsource1',
description: 'my-picsource1',
},
{
code: 10001,
name: 'my-picsource2',
description: 'my-picsource2',
},
].
});
```
### 开箱即用的 Schema 定义
......
import { Schema } from 'koishi';
import { Awaitable, Context } from 'koishi';
import { DefinePlugin } from 'koishi-thirdeye';
import { PicResult, PicSourceConfig, PicSourcePlugin } from '../src';
import {
DefineMultiSourcePlugin,
PicResult,
PicSourceConfig,
PicSourcePlugin,
} from '../src';
@DefinePlugin({ schema: PicSourceConfig })
class TestPicsource extends PicSourcePlugin {
@DefinePlugin({ name: 'test-source', schema: PicSourceConfig })
class TestPicSourcePlugin extends PicSourcePlugin {
randomPic(picTags: string[]): Awaitable<PicResult> {
return {
url: `https://cdn02.moecube.com:444/images/ygopro-images-${this.name}/${
......@@ -14,9 +20,18 @@ class TestPicsource extends PicSourcePlugin {
}
}
export class TestMultiPicSourcePlugin extends DefineMultiSourcePlugin(
TestPicSourcePlugin,
PicSourceConfig,
) {}
console.log((TestMultiPicSourcePlugin['Config'] as Schema).dict.instances.type);
export default class ExtrasInDev {
constructor(ctx: Context) {
ctx.plugin(TestPicsource, { name: 'zh-CN', isDefault: true });
ctx.plugin(TestMultiPicSourcePlugin, {
instances: [{ name: 'zh-CN', isDefault: true }, { name: 'en-US' }],
});
}
static using = ['pics'] as const;
......
import { Awaitable } from 'koishi';
import { ClassType, SchemaProperty } from 'koishi-thirdeye';
import { ClassType, SchemaClass, SchemaProperty } from 'koishi-thirdeye';
import { Context } from 'vm';
export interface PicSourceInfo {
tags?: string[];
......@@ -29,7 +30,6 @@ export interface Instances<T> {
instances: T[];
}
export function ToInstancesConfig<T>(
instanceConfig: ClassType<T>,
): new () => Instances<T> {
......@@ -37,9 +37,33 @@ export function ToInstancesConfig<T>(
instances: T[];
};
SchemaProperty({ type: instanceConfig, default: [] })(
instanceConfigClass.prototype,
'instances',
);
SchemaProperty({
type: SchemaClass(instanceConfig),
default: [],
array: true,
})(instanceConfigClass.prototype, 'instances');
return instanceConfigClass;
}
export function ClonePlugin<P extends { new (...args: any[]): any }>(
target: P,
name: string,
): P {
const pluginName = target.name;
const clonedPlugin = class extends target {};
for (const property of ['Config', 'schema', 'using']) {
Object.defineProperty(clonedPlugin, property, {
enumerable: true,
configurable: true,
writable: true,
value: target[property],
});
}
Object.defineProperty(clonedPlugin, 'name', {
enumerable: true,
configurable: true,
writable: true,
value: pluginName,
});
return clonedPlugin;
}
import { Context, Awaitable, Logger } from 'koishi';
import { Context, Awaitable, Logger, Plugin } from 'koishi';
import {
PartialDeep,
InjectConfig,
Inject,
InjectLogger,
BasePlugin,
ClassType,
DefinePlugin,
LifecycleEvents,
} from 'koishi-thirdeye';
import PicsContainer from '.';
import { PicSourceConfig } from './config';
import { PicSourceInfo, PicResult, Instances } from './def';
import {
PicSourceInfo,
PicResult,
Instances,
ToInstancesConfig,
ClonePlugin,
} from './def';
export class PicSource implements PicSourceInfo {
constructor(protected ctx: Context) {}
......@@ -62,16 +71,55 @@ export class PicSourcePlugin<
}
}
export class MultiPicSourcePlugin<
C extends PicSourceConfig = PicSourceConfig,
> extends BasePlugin<Instances<C>> {
export class MultiPicSourcePlugin<C extends PicSourceConfig>
extends BasePlugin<Instances<C>>
implements LifecycleEvents
{
@Inject(true)
protected pics: PicsContainer;
@InjectLogger()
protected logger: Logger;
getSourcePlugin(): new (ctx: Context, config: any) => PicSourcePlugin<C> {
throw new Error(`Not implemented`);
}
registerSourceInstances() {
const sourcePlugin = this.getSourcePlugin();
for (const instanceConfig of this.config.instances) {
const clonedSourcePlugin = ClonePlugin(
sourcePlugin,
`${instanceConfig.name}-${instanceConfig.name}`,
);
this.ctx.plugin(clonedSourcePlugin, instanceConfig);
}
}
onApply() {
const { instances } = this.config;
this.registerSourceInstances();
}
}
export function DefineMultiSourcePlugin<
C extends PicSourceConfig,
P extends PicSourcePlugin<C>,
>(
SourcePlugin: new (ctx: Context, config: C) => P,
SourceConfig: ClassType<C>,
name = SourcePlugin.name,
): new (
context: Context,
config: Instances<PartialDeep<C>>,
) => MultiPicSourcePlugin<C> {
const pluginClass = class SpecificMultiPicSourcePlugin extends MultiPicSourcePlugin<C> {
getSourcePlugin() {
return SourcePlugin;
}
};
return DefinePlugin({
name,
schema: ToInstancesConfig(SourceConfig),
})(pluginClass);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment