mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
264cb6bbd2 | ||
![]() |
b7772e867b | ||
![]() |
cc0e77abfb | ||
![]() |
537d1c6f4f | ||
![]() |
80facadd67 | ||
![]() |
ba097dad23 | ||
![]() |
c13c15d046 | ||
![]() |
4f52128a06 | ||
![]() |
500b2d0e6d | ||
![]() |
e59d094feb | ||
![]() |
a8372f14f8 | ||
![]() |
5174ff422d | ||
![]() |
5c06751c3b | ||
![]() |
ac2b0118a6 | ||
![]() |
3eb8fd4abe | ||
![]() |
48b389ebe3 | ||
![]() |
065adeb2cd | ||
![]() |
269d0a06fe | ||
![]() |
8eca26b1a5 | ||
![]() |
3019ef7de4 | ||
![]() |
522311b547 | ||
![]() |
21061561ec | ||
![]() |
b83c41ad56 | ||
![]() |
e80a1cc64a |
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -10,6 +10,7 @@ body:
|
||||
在提交新的 Bug 反馈前,请确保您:
|
||||
* 已经搜索了现有的 issues,并且没有找到可以解决您问题的方法
|
||||
* 不与现有的某一 issue 重复
|
||||
* 不涉及[已经停止维护的特性](https://github.com/NapNeko/NapCatQQ?tab=readme-ov-file#挥别昨日),例如 CQ 码
|
||||
- type: input
|
||||
id: system-version
|
||||
attributes:
|
||||
|
@@ -9,7 +9,7 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
||||
## 猫猫技能
|
||||
- [x] **高性能**:1K+ 群聊数目、20 线程并行发送消息毫无压力
|
||||
- [x] **多种启动方式**:支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动
|
||||
- [x] **多平台支持**: 支持Windows/Linux(可选Docker)/Android Termux/MacOs覆盖全平台
|
||||
- [x] **多平台支持**: 覆盖 Windows / Linux (可选 Docker) / Android Termux / MacOS
|
||||
- [x] **安装简单**: 支持一键脚本/程序自动部署/镜像部署等多种覆盖范围
|
||||
- [x] **低占用**:无头模式占用资源极低,适合在服务器上运行
|
||||
- [x] **超多接口**:实现大部分 OneBot 和 go-cqhttp 接口,超多扩展 API
|
||||
@@ -28,10 +28,12 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
||||
[Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl)
|
||||
|
||||
## 猫猫朋友
|
||||
感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供初始版本基础
|
||||
感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供部分参考
|
||||
|
||||
感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持
|
||||
|
||||
不过最最重要的 还是需要感谢屏幕前的你哦~
|
||||
|
||||
---
|
||||
|
||||
## 约法三章
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -36,3 +36,5 @@ set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
||||
|
||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
@@ -37,3 +37,5 @@ set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
||||
|
||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
@@ -4,7 +4,7 @@
|
||||
"name": "NapCatQQ",
|
||||
"slug": "NapCat.Framework",
|
||||
"description": "高性能的 OneBot 11 协议实现",
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.7",
|
||||
"icon": "./logo.png",
|
||||
"authors": [
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.7",
|
||||
"scripts": {
|
||||
"build:framework": "vite build --mode framework",
|
||||
"build:shell": "vite build --mode shell",
|
||||
|
@@ -167,7 +167,8 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
||||
function msgElementToText(element: MessageElement) {
|
||||
if (element.textElement) {
|
||||
if (element.textElement.atType === AtType.notAt) {
|
||||
return element.textElement.content;
|
||||
const originalContentLines = element.textElement.content.split('\n');
|
||||
return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`;
|
||||
} else if (element.textElement.atType === AtType.atAll) {
|
||||
return `@全体成员`;
|
||||
} else if (element.textElement.atType === AtType.atUser) {
|
||||
@@ -189,7 +190,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
||||
}
|
||||
|
||||
if (element.picElement) {
|
||||
return `[图片 ${element.picElement.fileName}]`;
|
||||
return '[图片]';
|
||||
}
|
||||
|
||||
if (element.fileElement) {
|
||||
@@ -197,7 +198,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
||||
}
|
||||
|
||||
if (element.videoElement) {
|
||||
return `[视频 ${element.videoElement.fileName}]`;
|
||||
return '[视频]';
|
||||
}
|
||||
|
||||
if (element.pttElement) {
|
||||
@@ -205,7 +206,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
||||
}
|
||||
|
||||
if (element.arkElement) {
|
||||
return `[卡片消息 ${element.arkElement.bytesData}]`;
|
||||
return '[卡片消息]';
|
||||
}
|
||||
|
||||
if (element.faceElement) {
|
||||
@@ -213,19 +214,19 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
||||
}
|
||||
|
||||
if (element.marketFaceElement) {
|
||||
return `[商城表情 ${element.marketFaceElement.faceName}]`;
|
||||
return element.marketFaceElement.faceName;
|
||||
}
|
||||
|
||||
if (element.markdownElement) {
|
||||
return `[Markdown ${element.markdownElement.content}]`;
|
||||
return '[Markdown 消息]';
|
||||
}
|
||||
|
||||
if (element.multiForwardMsgElement) {
|
||||
return `[转发消息]`;
|
||||
return '[转发消息]';
|
||||
}
|
||||
|
||||
if (element.elementType === ElementType.GreyTip) {
|
||||
return `[灰条消息]`; // TODO: resolve the text
|
||||
return '[灰条消息]';
|
||||
}
|
||||
|
||||
return `[未实现 (ElementType = ${element.elementType})]`;
|
||||
|
@@ -1 +1 @@
|
||||
export const napCatVersion = '2.3.0';
|
||||
export const napCatVersion = '2.3.7';
|
||||
|
@@ -298,65 +298,6 @@ export class NTQQFileApi {
|
||||
});
|
||||
}
|
||||
|
||||
async addFileCache(peer: Peer, msgId: string, msgSeq: string, senderUid: string, elemId: string, elemType: string, fileSize: string, fileName: string) {
|
||||
let GroupData;
|
||||
let BuddyData;
|
||||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||||
GroupData =
|
||||
[{
|
||||
groupCode: peer.peerUid,
|
||||
isConf: false,
|
||||
hasModifyConfGroupFace: true,
|
||||
hasModifyConfGroupName: true,
|
||||
groupName: 'NapCat.Cached',
|
||||
remark: 'NapCat.Cached',
|
||||
}];
|
||||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||||
BuddyData = [{
|
||||
category_name: 'NapCat.Cached',
|
||||
peerUid: peer.peerUid,
|
||||
peerUin: peer.peerUid,
|
||||
remark: 'NapCat.Cached',
|
||||
}];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.context.session.getSearchService().addSearchHistory({
|
||||
type: 4,
|
||||
contactList: [],
|
||||
id: -1,
|
||||
groupInfos: [],
|
||||
msgs: [],
|
||||
fileInfos: [
|
||||
{
|
||||
chatType: peer.chatType,
|
||||
buddyChatInfo: BuddyData || [],
|
||||
discussChatInfo: [],
|
||||
groupChatInfo: GroupData || [],
|
||||
dataLineChatInfo: [],
|
||||
tmpChatInfo: [],
|
||||
msgId: msgId,
|
||||
msgSeq: msgSeq,
|
||||
msgTime: Math.floor(Date.now() / 1000).toString(),
|
||||
senderUid: senderUid,
|
||||
senderNick: 'NapCat.Cached',
|
||||
senderRemark: 'NapCat.Cached',
|
||||
senderCard: 'NapCat.Cached',
|
||||
elemId: elemId,
|
||||
elemType: elemType,
|
||||
fileSize: fileSize,
|
||||
filePath: '',
|
||||
fileName: fileName,
|
||||
hits: [{
|
||||
start: 12,
|
||||
end: 14,
|
||||
}],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> {
|
||||
const randomResultId = 100000 + Math.floor(Math.random() * 10000);
|
||||
let searchId = 0;
|
||||
|
@@ -9,8 +9,9 @@ import {
|
||||
MemberExtSourceType,
|
||||
NapCatCore,
|
||||
} from '@/core';
|
||||
import { isNumeric } from '@/common/helper';
|
||||
import { isNumeric, solveAsyncProblem } from '@/common/helper';
|
||||
import { LimitedHashTable } from '@/common/message-unique';
|
||||
import { NTEventWrapper } from '@/common/event';
|
||||
|
||||
export class NTQQGroupApi {
|
||||
context: InstanceContext;
|
||||
@@ -264,14 +265,34 @@ export class NTQQGroupApi {
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
|
||||
let data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
|
||||
return eventWrapper.callNormalEventV2(
|
||||
'NodeIKernelGroupService/getMemberInfo',
|
||||
'NodeIKernelGroupListener/onMemberInfoChange',
|
||||
[GroupCode, [uid], forced],
|
||||
(ret) => ret.result === 0,
|
||||
(params, _, members) => params === GroupCode && members.size > 0 && members.has(uid),
|
||||
1,
|
||||
forced ? 2500 : 250
|
||||
);
|
||||
}, this.core.eventWrapper, GroupCode, uid, forced);
|
||||
if (data && data[3] instanceof Map && data[3].has(uid)) {
|
||||
return data[3].get(uid);
|
||||
}
|
||||
if (retry > 0) {
|
||||
let trydata = await this.getGroupMemberEx(GroupCode, uid, true, retry - 1) as GroupMember | undefined;
|
||||
if (trydata) return trydata;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||
const groupService = this.context.session.getGroupService();
|
||||
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||
const listener = this.core.eventWrapper.registerListen(
|
||||
'NodeIKernelGroupListener/onMemberListChange',
|
||||
1,
|
||||
500,
|
||||
5000,
|
||||
(params) => params.sceneId === sceneId,
|
||||
);
|
||||
try {
|
||||
|
@@ -113,7 +113,7 @@ export class NTQQMsgApi {
|
||||
return await this.context.session.getMsgService().getMsgsBySeqList(peer, msgSeqList);
|
||||
}
|
||||
async getMsgBySeqExFirstMsg(peer: Peer, rootMsgId: string, replyMsgId: string) {
|
||||
let reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
|
||||
const reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
|
||||
console.log(reply);
|
||||
}
|
||||
async getMsgExBySeq(peer: Peer, msgSeq: string) {
|
||||
@@ -164,6 +164,18 @@ export class NTQQMsgApi {
|
||||
}, msgIds);
|
||||
}
|
||||
|
||||
async recallMsgV2(peer: Peer, msgId: string) {
|
||||
await this.core.eventWrapper.callNormalEventV2(
|
||||
'NodeIKernelMsgService/recallMsg',
|
||||
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||||
[peer, [msgId]],
|
||||
() => true,
|
||||
(updatedList) => updatedList.find(m => m.msgId === msgId && m.recallTime !== '0') !== undefined,
|
||||
1,
|
||||
1000,
|
||||
);
|
||||
}
|
||||
|
||||
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
|
||||
return this.context.session.getMsgService().prepareTempChat({
|
||||
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
|
||||
|
@@ -11,7 +11,7 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
|
||||
actionName = ActionName.GetGroupIgnoreAddRequest;
|
||||
|
||||
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
||||
const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
|
||||
// const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
|
||||
// log(data);
|
||||
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
|
||||
// const returnData: OB11GroupRequestNotify[] = [];
|
||||
|
@@ -26,7 +26,7 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
|
||||
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
||||
if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`);
|
||||
const [member, info] = await Promise.allSettled([
|
||||
this.core.apis.GroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache),
|
||||
this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache),
|
||||
this.core.apis.UserApi.getUserDetailInfo(uid),
|
||||
]);
|
||||
if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`);
|
||||
|
@@ -115,6 +115,7 @@ export class OneBotMsgApi {
|
||||
file_id: encodedFileId,
|
||||
url: await this.core.apis.FileApi.getImageUrl(element),
|
||||
file_size: element.fileSize,
|
||||
file_unique: element.fileName
|
||||
},
|
||||
};
|
||||
} catch (e: any) {
|
||||
@@ -129,20 +130,6 @@ export class OneBotMsgApi {
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '',
|
||||
};
|
||||
await this.core.apis.FileApi.addFileCache(
|
||||
{
|
||||
peerUid: msg.peerUid,
|
||||
chatType: msg.chatType,
|
||||
guildId: '',
|
||||
},
|
||||
msg.msgId,
|
||||
msg.msgSeq,
|
||||
msg.senderUid,
|
||||
elementWrapper.elementId,
|
||||
elementWrapper.elementType.toString(),
|
||||
element.fileSize,
|
||||
element.fileName,
|
||||
);
|
||||
return {
|
||||
type: OB11MessageDataType.file,
|
||||
data: {
|
||||
@@ -151,6 +138,7 @@ export class OneBotMsgApi {
|
||||
url: element.filePath,
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||
file_size: element.fileSize,
|
||||
file_unique: element.fileName,
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -182,20 +170,6 @@ export class OneBotMsgApi {
|
||||
},
|
||||
|
||||
marketFaceElement: async (_, msg, elementWrapper) => {
|
||||
await this.core.apis.FileApi.addFileCache(
|
||||
{
|
||||
peerUid: msg.peerUid,
|
||||
chatType: msg.chatType,
|
||||
guildId: '',
|
||||
},
|
||||
msg.msgId,
|
||||
msg.msgSeq,
|
||||
msg.senderUid,
|
||||
elementWrapper.elementId,
|
||||
elementWrapper.elementType.toString(),
|
||||
'0',
|
||||
'marketface',
|
||||
);
|
||||
const peer = {
|
||||
chatType: msg.chatType,
|
||||
peerUid: msg.peerUid,
|
||||
@@ -208,6 +182,7 @@ export class OneBotMsgApi {
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||
path: elementWrapper.elementId,
|
||||
url: elementWrapper.elementId,
|
||||
file_unique: _.key
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -283,21 +258,6 @@ export class OneBotMsgApi {
|
||||
videoDownUrl = element.filePath;
|
||||
}
|
||||
|
||||
await this.core.apis.FileApi.addFileCache(
|
||||
{
|
||||
peerUid: msg.peerUid,
|
||||
chatType: msg.chatType,
|
||||
guildId: '',
|
||||
},
|
||||
msg.msgId,
|
||||
msg.msgSeq,
|
||||
msg.senderUid,
|
||||
elementWrapper.elementId,
|
||||
elementWrapper.elementType.toString(),
|
||||
element.fileSize ?? '0',
|
||||
element.fileName,
|
||||
);
|
||||
|
||||
return {
|
||||
type: OB11MessageDataType.video,
|
||||
data: {
|
||||
@@ -306,6 +266,7 @@ export class OneBotMsgApi {
|
||||
url: videoDownUrl,
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||
file_size: element.fileSize,
|
||||
file_unique: element.fileName,
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -316,20 +277,6 @@ export class OneBotMsgApi {
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '',
|
||||
};
|
||||
await this.core.apis.FileApi.addFileCache(
|
||||
{
|
||||
peerUid: msg.peerUid,
|
||||
chatType: msg.chatType,
|
||||
guildId: '',
|
||||
},
|
||||
msg.msgId,
|
||||
msg.msgSeq,
|
||||
msg.senderUid,
|
||||
elementWrapper.elementId,
|
||||
elementWrapper.elementType.toString(),
|
||||
element.fileSize || '0',
|
||||
element.fileUuid || '',
|
||||
);
|
||||
return {
|
||||
type: OB11MessageDataType.voice,
|
||||
data: {
|
||||
@@ -730,8 +677,10 @@ export class OneBotMsgApi {
|
||||
if (ret.result === 0) {
|
||||
resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode);
|
||||
resMsg.sender.nickname = ret.tmpChatInfo!.fromNick;
|
||||
resMsg.temp_source = resMsg.group_id;
|
||||
} else {
|
||||
resMsg.group_id = 284840486; //兜底数据
|
||||
resMsg.temp_source = resMsg.group_id;
|
||||
resMsg.sender.nickname = '临时会话';
|
||||
}
|
||||
}
|
||||
|
@@ -66,10 +66,7 @@ export function encodeCQCode(data: OB11MessageData) {
|
||||
|
||||
let result = '[CQ:' + data.type;
|
||||
for (const name in data.data) {
|
||||
const value =
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
data.data[name];
|
||||
const value = (data.data as any)[name];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ export class NapCatOneBot11Adapter {
|
||||
if (ob11Config.http.enablePost) {
|
||||
ob11Config.http.postUrls.forEach(url => {
|
||||
this.networkManager.registerAdapter(new OB11ActiveHttpAdapter(
|
||||
url, ob11Config.token, this.core, this,
|
||||
url, ob11Config.http.secret, this.core, this,
|
||||
));
|
||||
});
|
||||
}
|
||||
@@ -168,7 +168,7 @@ export class NapCatOneBot11Adapter {
|
||||
if (now.http.enablePost) {
|
||||
now.http.postUrls.forEach(url => {
|
||||
this.networkManager.registerAdapterAndOpen(new OB11ActiveHttpAdapter(
|
||||
url, now.token, this.core, this,
|
||||
url, now.http.secret, this.core, this,
|
||||
));
|
||||
});
|
||||
} else {
|
||||
@@ -182,7 +182,7 @@ export class NapCatOneBot11Adapter {
|
||||
);
|
||||
for (const url of added) {
|
||||
await this.networkManager.registerAdapterAndOpen(new OB11ActiveHttpAdapter(
|
||||
url, now.token, this.core, this,
|
||||
url, now.http.secret, this.core, this,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ export enum OB11MessageType {
|
||||
}
|
||||
|
||||
export interface OB11Message {
|
||||
temp_source?: number;
|
||||
message_sent_type?: string;
|
||||
target_id?: number; // 自己发送的消息才有此字段
|
||||
self_id?: number,
|
||||
|
@@ -3,6 +3,7 @@ import { ALLRouter } from './src/router';
|
||||
import { LogWrapper } from '@/common/log';
|
||||
import { NapCatPathWrapper } from '@/common/path';
|
||||
import { WebUiConfigWrapper } from './src/helper/config';
|
||||
import { RequestUtil } from '@/common/request';
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -38,7 +39,23 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
|
||||
app.use(config.prefix + '/api', ALLRouter);
|
||||
app.listen(config.port, config.host, async () => {
|
||||
log(`[NapCat] [WebUi] Current WebUi is running at http://${config.host}:${config.port}${config.prefix}`);
|
||||
log(`[NapCat] [WebUi] Login URL is http://${config.host}:${config.port}${config.prefix}/webui`);
|
||||
log(`[NapCat] [WebUi] Login Token is ${config.token}`);
|
||||
log(`[NapCat] [WebUi] WebUi User Panel Url: http://${config.host}:${config.port}${config.prefix}/webui?token=${config.token}`);
|
||||
log(`[NapCat] [WebUi] WebUi Local Panel Url: http://127.0.0.1:${config.port}${config.prefix}/webui?token=${config.token}`);
|
||||
//获取上网Ip
|
||||
//https://www.ip.cn/api/index?ip&type=0
|
||||
RequestUtil.HttpGetJson<{ IP: {IP:string} }>(
|
||||
'https://ip.011102.xyz/',
|
||||
'GET',
|
||||
{},
|
||||
{},
|
||||
true,
|
||||
true
|
||||
).then((data) => {
|
||||
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
|
||||
}).catch((err) => {
|
||||
logger.logError(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
undefined,
|
||||
SettingButton('V2.3.0', 'napcat-update-button', 'secondary'),
|
||||
SettingButton('V2.3.7', 'napcat-update-button', 'secondary'),
|
||||
),
|
||||
]),
|
||||
SettingList([
|
||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
void 0,
|
||||
SettingButton("V2.3.0", "napcat-update-button", "secondary")
|
||||
SettingButton("V2.3.7", "napcat-update-button", "secondary")
|
||||
)
|
||||
]),
|
||||
SettingList([
|
||||
|
@@ -29,7 +29,7 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
input[type="password"] {
|
||||
width: 90%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
@@ -64,7 +64,7 @@
|
||||
<form id="token-form" onsubmit="event.preventDefault(); submitToken();">
|
||||
<div class="input-group">
|
||||
<label for="token-input">Enter Token:</label>
|
||||
<input type="text" id="token-input" required>
|
||||
<input type="password" id="token-input" required>
|
||||
</div>
|
||||
<p class="error-message hidden" id="error-message"></p>
|
||||
<button type="submit">Login</button>
|
||||
|
Reference in New Issue
Block a user