mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
Merge branch 'main' into upmain
This commit is contained in:
commit
0081000ef0
@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "3.1.0",
|
"version": "3.1.3",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "3.1.0",
|
"version": "3.1.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:framework": "vite build --mode framework",
|
"build:framework": "vite build --mode framework",
|
||||||
"build:shell": "vite build --mode shell",
|
"build:shell": "vite build --mode shell",
|
||||||
@ -37,7 +37,7 @@
|
|||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"async-mutex": "^0.5.0",
|
"async-mutex": "^0.5.0",
|
||||||
"file-type": "^19.0.0",
|
"file-type": "^19.0.0",
|
||||||
"json-schema-to-ts": "^3.1.0",
|
"json-schema-to-ts": "^3.1.1",
|
||||||
"image-size": "^1.1.1",
|
"image-size": "^1.1.1",
|
||||||
"cors": "^2.8.5"
|
"cors": "^2.8.5"
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
export const napCatVersion = '3.1.0';
|
export const napCatVersion = '3.1.3';
|
||||||
|
@ -30,7 +30,7 @@ export class NTQQFileApi {
|
|||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
rkeyManager: RkeyManager;
|
rkeyManager: RkeyManager;
|
||||||
packetRkey: Array<{ rkey: string; time: number; type: number; }> | undefined;
|
packetRkey: Array<{ rkey: string; time: number; type: number; ttl: bigint }> | undefined;
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -378,10 +378,12 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
if (this.core.apis.PacketApi.available) {
|
if (this.core.apis.PacketApi.available) {
|
||||||
if ((!this.packetRkey || this.packetRkey[0].time > Date.now() / 1000)) {
|
let rkey_expired_private = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||||
|
let rkey_expired_group = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||||
|
if (rkey_expired_private || rkey_expired_group) {
|
||||||
this.packetRkey = await this.core.apis.PacketApi.sendRkeyPacket();
|
this.packetRkey = await this.core.apis.PacketApi.sendRkeyPacket();
|
||||||
}
|
}
|
||||||
if (this.packetRkey.length > 0) {
|
if (this.packetRkey && this.packetRkey.length > 0) {
|
||||||
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6);
|
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6);
|
||||||
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
|
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
|
||||||
rkeyData.online_rkey = true;
|
rkeyData.online_rkey = true;
|
||||||
|
@ -338,4 +338,12 @@ export class NTQQWebApi {
|
|||||||
}
|
}
|
||||||
return (hash & 0x7FFFFFFF).toString();
|
return (hash & 0x7FFFFFFF).toString();
|
||||||
}
|
}
|
||||||
|
public getBknFromSKey(sKey: string) {
|
||||||
|
let hash = 5381;
|
||||||
|
for (let i = 0; i < sKey.length; i++) {
|
||||||
|
const code = sKey.charCodeAt(i);
|
||||||
|
hash = hash + (hash << 5) + code;
|
||||||
|
}
|
||||||
|
return (hash & 0x7FFFFFFF).toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ export const OidbSvcTrpcTcp0X9067_202Key = {
|
|||||||
//Rsp
|
//Rsp
|
||||||
export const OidbSvcTrpcTcp0X9067_202_RkeyList = {
|
export const OidbSvcTrpcTcp0X9067_202_RkeyList = {
|
||||||
rkey: ProtoField(1, ScalarType.STRING),
|
rkey: ProtoField(1, ScalarType.STRING),
|
||||||
|
ttl: ProtoField(2, ScalarType.UINT64),
|
||||||
time: ProtoField(4, ScalarType.UINT32),
|
time: ProtoField(4, ScalarType.UINT32),
|
||||||
type: ProtoField(5, ScalarType.UINT32),
|
type: ProtoField(5, ScalarType.UINT32),
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { GroupNotifyMsgStatus } from '@/core';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
|
|
||||||
@ -11,18 +12,22 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
|
|||||||
actionName = ActionName.GetGroupIgnoreAddRequest;
|
actionName = ActionName.GetGroupIgnoreAddRequest;
|
||||||
|
|
||||||
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
||||||
// const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
|
const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10);
|
||||||
// log(data);
|
const retData: any = {
|
||||||
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
|
join_requests: await Promise.all(
|
||||||
// const returnData: OB11GroupRequestNotify[] = [];
|
ignoredNotifies
|
||||||
// for (const notify of notifies) {
|
.filter(notify => notify.type === 7)
|
||||||
// const uin = || (await NTQQUserApi.getUserDetailInfo(notify.user1.uid))?.uin;
|
.map(async SSNotify => ({
|
||||||
// returnData.push({
|
request_id: SSNotify.seq,
|
||||||
// group_id: parseInt(notify.group.groupCode),
|
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||||
// user_id: parseInt(uin),
|
requester_nick: SSNotify.user1?.nickName,
|
||||||
// flag: notify.seq
|
group_id: SSNotify.group?.groupCode,
|
||||||
// });
|
group_name: SSNotify.group?.groupName,
|
||||||
// }
|
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
|
||||||
return null;
|
actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||||
|
}))),
|
||||||
|
};
|
||||||
|
|
||||||
|
return retData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ import { ActionName } from '../types';
|
|||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
|
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
|
||||||
|
|
||||||
export interface GetFilePayload {
|
// interface GetFilePayload {
|
||||||
file: string; // 文件名或者fileUuid
|
// file: string; // 文件名或者fileUuid
|
||||||
}
|
// }
|
||||||
|
|
||||||
export interface GetFileResponse {
|
export interface GetFileResponse {
|
||||||
file?: string; // path
|
file?: string; // path
|
||||||
@ -16,19 +16,25 @@ export interface GetFileResponse {
|
|||||||
file_name?: string;
|
file_name?: string;
|
||||||
base64?: string;
|
base64?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetFileBase_PayloadSchema = {
|
const GetFileBase_PayloadSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
file: { type: 'string' },
|
file: { type: 'string' },
|
||||||
|
file_id: { type: 'string' }
|
||||||
},
|
},
|
||||||
required: ['file'],
|
oneOf: [
|
||||||
|
{ required: ['file'] },
|
||||||
|
{ required: ['file_id'] }
|
||||||
|
]
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
export type GetFilePayload = FromSchema<typeof GetFileBase_PayloadSchema>;
|
||||||
|
|
||||||
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
||||||
payloadSchema: any = GetFileBase_PayloadSchema;
|
payloadSchema = GetFileBase_PayloadSchema;
|
||||||
|
|
||||||
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
|
payload.file ||= payload.file_id || '';
|
||||||
//接收消息标记模式
|
//接收消息标记模式
|
||||||
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
|
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
|
||||||
if (contextMsgFile) {
|
if (contextMsgFile) {
|
||||||
@ -115,27 +121,6 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetFile_PayloadSchema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
file_id: { type: 'string' },
|
|
||||||
file: { type: 'string' },
|
|
||||||
},
|
|
||||||
required: ['file_id'],
|
|
||||||
} as const satisfies JSONSchema;
|
|
||||||
|
|
||||||
type GetFile_Payload_Internal = FromSchema<typeof GetFile_PayloadSchema>;
|
|
||||||
|
|
||||||
interface GetFile_Payload extends GetFile_Payload_Internal {
|
|
||||||
file: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class GetFile extends GetFileBase {
|
export default class GetFile extends GetFileBase {
|
||||||
actionName = ActionName.GetFile;
|
actionName = ActionName.GetFile;
|
||||||
payloadSchema = GetFile_PayloadSchema;
|
|
||||||
|
|
||||||
async _handle(payload: GetFile_Payload): Promise<GetFileResponse> {
|
|
||||||
payload.file = payload.file_id;
|
|
||||||
return super._handle(payload);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ import { GetGroupMemberList } from './group/GetGroupMemberList';
|
|||||||
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
|
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
|
||||||
import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus";
|
import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus";
|
||||||
import { FriendPoke } from "@/onebot/action/user/FriendPoke";
|
import { FriendPoke } from "@/onebot/action/user/FriendPoke";
|
||||||
|
import { GetCredentials } from './system/GetCredentials';
|
||||||
|
|
||||||
|
|
||||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||||
@ -180,6 +181,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new SetModelShow(obContext, core),
|
new SetModelShow(obContext, core),
|
||||||
new SetInputStatus(obContext, core),
|
new SetInputStatus(obContext, core),
|
||||||
new GetCSRF(obContext, core),
|
new GetCSRF(obContext, core),
|
||||||
|
new GetCredentials(obContext, core),
|
||||||
new DelGroupNotice(obContext, core),
|
new DelGroupNotice(obContext, core),
|
||||||
new DeleteGroupFile(obContext, core),
|
new DeleteGroupFile(obContext, core),
|
||||||
new CreateGroupFileFolder(obContext, core),
|
new CreateGroupFileFolder(obContext, core),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ChatType, Peer } from '@/core/entities';
|
import { ChatType, Peer } from '@/core/entities';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@ -49,23 +49,14 @@ export class MarkGroupMsgAsRead extends MarkMsgAsRead {
|
|||||||
actionName = ActionName.MarkGroupMsgAsRead;
|
actionName = ActionName.MarkGroupMsgAsRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class GoCQHTTPMarkMsgAsRead extends MarkMsgAsRead {
|
||||||
interface Payload {
|
|
||||||
message_id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GoCQHTTPMarkMsgAsRead extends BaseAction<Payload, null> {
|
|
||||||
actionName = ActionName.GoCQHTTP_MarkMsgAsRead;
|
actionName = ActionName.GoCQHTTP_MarkMsgAsRead;
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MarkAllMsgAsRead extends BaseAction<Payload, null> {
|
export class MarkAllMsgAsRead extends BaseAction<any, null> {
|
||||||
actionName = ActionName._MarkAllMsgAsRead;
|
actionName = ActionName._MarkAllMsgAsRead;
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(): Promise<null> {
|
||||||
await this.core.apis.MsgApi.markAllMsgAsRead();
|
await this.core.apis.MsgApi.markAllMsgAsRead();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,12 @@ export class GetCSRF extends BaseAction<any, any> {
|
|||||||
actionName = ActionName.GetCSRF;
|
actionName = ActionName.GetCSRF;
|
||||||
|
|
||||||
async _handle(payload: any) {
|
async _handle(payload: any) {
|
||||||
|
const sKey = await this.core.apis.UserApi.getSKey();
|
||||||
|
if (!sKey) {
|
||||||
|
throw new Error('SKey is undefined');
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
token: '',
|
token: +this.core.apis.WebApi.getBknFromSKey(sKey),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
src/onebot/action/system/GetCredentials.ts
Normal file
31
src/onebot/action/system/GetCredentials.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
interface Response {
|
||||||
|
cookies: string,
|
||||||
|
token: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
domain: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['domain'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class GetCredentials extends BaseAction<Payload, Response> {
|
||||||
|
actionName = ActionName.GetCredentials;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
const cookiesObject = await this.core.apis.UserApi.getCookies(payload.domain);
|
||||||
|
//把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起
|
||||||
|
const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||||
|
const bkn = cookiesObject?.skey ? this.core.apis.WebApi.getBknFromCookie(cookiesObject) : '';
|
||||||
|
return { cookies: cookies, token: +bkn };
|
||||||
|
}
|
||||||
|
}
|
@ -43,8 +43,8 @@ export enum ActionName {
|
|||||||
GetGroupMemberList = 'get_group_member_list',
|
GetGroupMemberList = 'get_group_member_list',
|
||||||
GetGroupHonorInfo = 'get_group_honor_info',
|
GetGroupHonorInfo = 'get_group_honor_info',
|
||||||
GetCookies = 'get_cookies',
|
GetCookies = 'get_cookies',
|
||||||
// GetCSRF = 'get_csrf_token',
|
GetCSRF = 'get_csrf_token',
|
||||||
// GetCredentials = 'get_credentials',
|
GetCredentials = 'get_credentials',
|
||||||
GetRecord = 'get_record',
|
GetRecord = 'get_record',
|
||||||
GetImage = 'get_image',
|
GetImage = 'get_image',
|
||||||
CanSendImage = 'can_send_image',
|
CanSendImage = 'can_send_image',
|
||||||
@ -59,7 +59,7 @@ export enum ActionName {
|
|||||||
// QidianGetAccountInfo = 'qidian_get_account_info',
|
// QidianGetAccountInfo = 'qidian_get_account_info',
|
||||||
// GetModelShow = '_get_model_show',
|
// GetModelShow = '_get_model_show',
|
||||||
// SetModelShow = '_set_model_show',
|
// SetModelShow = '_set_model_show',
|
||||||
// GetOnlineClient = 'get_online_clients',
|
GetOnlineClient = 'get_online_clients',
|
||||||
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
|
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
|
||||||
// DeleteFriend = 'delete_friend',
|
// DeleteFriend = 'delete_friend',
|
||||||
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
|
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
|
||||||
@ -105,11 +105,6 @@ export enum ActionName {
|
|||||||
ForwardFriendSingleMsg = 'forward_friend_single_msg',
|
ForwardFriendSingleMsg = 'forward_friend_single_msg',
|
||||||
ForwardGroupSingleMsg = 'forward_group_single_msg',
|
ForwardGroupSingleMsg = 'forward_group_single_msg',
|
||||||
TranslateEnWordToZn = 'translate_en2zh',
|
TranslateEnWordToZn = 'translate_en2zh',
|
||||||
GetGroupFileCount = 'get_group_file_count',
|
|
||||||
GetGroupFileList = 'get_group_file_list',
|
|
||||||
SetGroupFileFolder = 'set_group_file_folder',
|
|
||||||
DelGroupFile = 'del_group_file',
|
|
||||||
DelGroupFileFolder = 'del_group_file_folder',
|
|
||||||
SetMsgEmojiLike = 'set_msg_emoji_like',
|
SetMsgEmojiLike = 'set_msg_emoji_like',
|
||||||
GoCQHTTP_SendForwardMsg = 'send_forward_msg',
|
GoCQHTTP_SendForwardMsg = 'send_forward_msg',
|
||||||
MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
|
MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
|
||||||
@ -125,7 +120,7 @@ export enum ActionName {
|
|||||||
FetchEmojiLike = 'fetch_emoji_like',
|
FetchEmojiLike = 'fetch_emoji_like',
|
||||||
SetInputStatus = 'set_input_status',
|
SetInputStatus = 'set_input_status',
|
||||||
GetGroupInfoEx = 'get_group_info_ex',
|
GetGroupInfoEx = 'get_group_info_ex',
|
||||||
GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
|
GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
|
||||||
DelGroupNotice = '_del_group_notice',
|
DelGroupNotice = '_del_group_notice',
|
||||||
FetchUserProfileLike = 'fetch_user_profile_like',
|
FetchUserProfileLike = 'fetch_user_profile_like',
|
||||||
FriendPoke = 'friend_poke',
|
FriendPoke = 'friend_poke',
|
||||||
@ -135,12 +130,9 @@ export enum ActionName {
|
|||||||
GetRkey = 'nc_get_rkey',
|
GetRkey = 'nc_get_rkey',
|
||||||
GetGroupShutList = 'get_group_shut_list',
|
GetGroupShutList = 'get_group_shut_list',
|
||||||
|
|
||||||
// GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
|
GetGuildList = 'get_guild_list',
|
||||||
// GetConfig = 'get_config',
|
GetGuildProfile = 'get_guild_service_profile',
|
||||||
// SetConfig = 'set_config',
|
|
||||||
// Debug = 'debug',
|
GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
|
||||||
// GetGuildList = 'get_guild_list',
|
|
||||||
// TestApi01 = 'test_api_01',
|
|
||||||
// GetGuildProfile = 'get_guild_service_profile',
|
|
||||||
// UploadForwardMsg = "upload_forward_msg",
|
// UploadForwardMsg = "upload_forward_msg",
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
undefined,
|
undefined,
|
||||||
SettingButton('V3.1.0', 'napcat-update-button', 'secondary'),
|
SettingButton('V3.1.3', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V3.1.0", "napcat-update-button", "secondary")
|
SettingButton("V3.1.3", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Loading…
x
Reference in New Issue
Block a user