update at 2025-10-09 21:19:57

This commit is contained in:
douboer
2025-10-09 21:19:57 +08:00
parent 002feedbe1
commit 1309caddc3
15 changed files with 1126 additions and 209 deletions

213
src/wechat/weixin-api.ts Normal file
View File

@@ -0,0 +1,213 @@
/**
* 文件weixin-api.ts
* 功能:微信公众号相关 API 封装(占位或已实现逻辑)。
* - 登录 / 发布 / 图片上传(根据实现情况扩展)
* - 与预览/适配器协同
*/
import { requestUrl, RequestUrlParam, getBlobArrayBuffer } from "obsidian";
const PluginHost = 'https://obplugin.sunboshi.tech';
// 获取token
export async function wxGetToken(authkey:string, appid:string, secret:string) {
const url = PluginHost + '/v1/wx/token';
const body = {
authkey,
appid,
secret
}
const res = await requestUrl({
url,
method: 'POST',
throw: false,
contentType: 'application/json',
body: JSON.stringify(body)
});
return res;
}
export async function wxEncrypt(authkey:string, wechat:any[]) {
const url = PluginHost + '/v1/wx/encrypt';
const body = JSON.stringify({
authkey,
wechat
});
const res = await requestUrl({
url: url,
method: 'POST',
throw: false,
contentType: 'application/json',
body: body
});
return res
}
export async function wxKeyInfo(authkey:string) {
const url = PluginHost + '/v1/wx/info/' + authkey;
const res = await requestUrl({
url: url,
method: 'GET',
throw: false,
contentType: 'application/json',
});
return res
}
export async function wxWidget(authkey: string, params: string) {
const host = 'https://obplugin.sunboshi.tech';
const path = '/math/widget';
const url = `${host}${path}`;
try {
const res = await requestUrl({
url,
throw: false,
method: 'POST',
contentType: 'application/json',
headers: {
authkey
},
body: params
})
if (res.status === 200) {
return res.json.content;
}
return res.json.msg;
} catch (error) {
console.log(error);
return error.message;
}
}
// 上传图片
export async function wxUploadImage(data: Blob, filename: string, token: string, type?: string) {
let url = '';
if (type == null || type === '') {
url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=' + token;
} else {
url = `https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=${token}&type=${type}`
}
const N = 16 // The length of our random boundry string
const randomBoundryString = "djmangoBoundry" + Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
// Construct the form data payload as a string
const pre_string = `------${randomBoundryString}\r\nContent-Disposition: form-data; name="media"; filename="${filename}"\r\nContent-Type: "application/octet-stream"\r\n\r\n`;
const post_string = `\r\n------${randomBoundryString}--`
// Convert the form data payload to a blob by concatenating the pre_string, the file data, and the post_string, and then return the blob as an array buffer
const pre_string_encoded = new TextEncoder().encode(pre_string);
// const data = file;
const post_string_encoded = new TextEncoder().encode(post_string);
const concatenated = await new Blob([pre_string_encoded, await getBlobArrayBuffer(data), post_string_encoded]).arrayBuffer()
// Now that we have the form data payload as an array buffer, we can pass it to requestURL
// We also need to set the content type to multipart/form-data and pass in the boundry string
const options: RequestUrlParam = {
method: 'POST',
url: url,
contentType: `multipart/form-data; boundary=----${randomBoundryString}`,
body: concatenated
};
const res = await requestUrl(options);
const resData = await res.json;
return {
url: resData.url || '',
media_id: resData.media_id || '',
errcode: resData.errcode || 0,
errmsg: resData.errmsg || '',
}
}
// 新建草稿
export interface DraftArticle {
title: string;
author?: string;
digest?: string;
cover?: string;
content: string;
content_source_url?: string;
thumb_media_id: string;
need_open_comment?: number;
only_fans_can_comment?: number;
pic_crop_235_1?: string;
pic_crop_1_1?: string;
appid?: string;
theme?: string;
highlight?: string;
}
export async function wxAddDraft(token: string, data: DraftArticle) {
const url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token=' + token;
const body = {articles:[{
title: data.title,
content: data.content,
digest: data.digest,
thumb_media_id: data.thumb_media_id,
... data.pic_crop_235_1 && {pic_crop_235_1: data.pic_crop_235_1},
... data.pic_crop_1_1 && {pic_crop_1_1: data.pic_crop_1_1},
... data.content_source_url && {content_source_url: data.content_source_url},
... data.need_open_comment !== undefined && {need_open_comment: data.need_open_comment},
... data.only_fans_can_comment !== undefined && {only_fans_can_comment: data.only_fans_can_comment},
... data.author && {author: data.author},
}]};
const res = await requestUrl({
method: 'POST',
url: url,
throw: false,
body: JSON.stringify(body)
});
return res;
}
export interface DraftImageMediaId {
image_media_id: string;
}
export interface DraftImageInfo {
image_list: DraftImageMediaId[];
}
export interface DraftImages {
article_type: string;
title: string;
content: string;
need_open_commnet: number;
only_fans_can_comment: number;
image_info: DraftImageInfo;
}
export async function wxAddDraftImages(token: string, data: DraftImages) {
const url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token=' + token;
const body = {articles:[data]};
const res = await requestUrl({
method: 'POST',
url: url,
throw: false,
body: JSON.stringify(body)
});
return res;
}
export async function wxBatchGetMaterial(token: string, type: string, offset: number = 0, count: number = 10) {
const url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=' + token;
const body = {
type,
offset,
count
};
const res = await requestUrl({
method: 'POST',
url: url,
throw: false,
body: JSON.stringify(body)
});
return await res.json;
}