Files
n8n-nodes-gwezz-changdunovel/nodes/GwezzChangdunovel/GwezzChangdunovel.node.ts
2025-10-29 21:37:00 +08:00

129 lines
3.2 KiB
TypeScript

import { createHash } from 'crypto';
import {
type INodeType,
type INodeTypeDescription,
IExecuteFunctions,
INodeExecutionData,
} from 'n8n-workflow';
import { distributionDescription } from './resources/distribution';
/**
* 生成 MD5 签名
* @param params 参数数组
* @returns MD5 签名字符串
*/
function getSign(params: (string | number)[]): string {
const paramStr = params.join('');
return createHash('md5').update(paramStr).digest('hex');
}
/**
* 创建认证参数
* @param distributorId 分销商 ID
* @param secretKey 签名密钥
* @returns
*/
function createAuthParams(
distributorId: string,
secretKey: string,
): Record<string, string | number> {
const timeStamp = Math.floor(Date.now() / 1000);
return {
distributor_id: distributorId,
ts: timeStamp,
sign: getSign([distributorId, secretKey, timeStamp]),
};
}
export class GwezzChangdunovel implements INodeType {
description: INodeTypeDescription = {
displayName: 'Gwezz 常读分销',
name: 'gwezzChangdunovel',
icon: { light: 'file:../../icons/gwezz.svg', dark: 'file:../../icons/gwezz.dark.svg' },
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with the Changdunovel API',
defaults: {
name: 'Gwezz 常读分销',
},
usableAsTool: true,
inputs: ['main'],
outputs: ['main'],
credentials: [{ name: 'gwezzChangdunovelApi', required: true }],
requestDefaults: {
baseURL: 'https://www.changdunovel.com/novelsale/openapi',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: '资源',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: '分销',
value: 'distribution',
},
],
default: 'distribution',
},
...distributionDescription,
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
const credentials = await this.getCredentials('gwezzChangdunovelApi');
const distributorId = credentials.distributor_id as string;
const secretKey = credentials.secret_key as string;
for (let i = 0; i < items.length; i++) {
try {
let responseData;
if (resource === 'distribution') {
if (operation === 'contentBookMetaV1') {
const bookId = this.getNodeParameter('book_id', i) as string;
const authParams = createAuthParams(distributorId, secretKey);
const qs = {
...authParams,
book_id: bookId,
};
responseData = await this.helpers.httpRequest({
method: 'GET',
url: '/v1/content/book/meta',
qs,
});
}
}
returnData.push({ json: responseData, itemIndex: i });
} catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: (error as Error).message,
},
itemIndex: i,
});
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}