Compare commits

...

36 Commits

Author SHA1 Message Date
手瓜一十雪
35c232ab25 fix 2024-04-16 13:27:33 +08:00
手瓜一十雪
02299e3892 fix 2024-04-16 13:17:30 +08:00
手瓜一十雪
6af4d6f5b8 fix 2024-04-16 13:14:09 +08:00
手瓜一十雪
4fb5700367 fix 2024-04-16 13:12:33 +08:00
手瓜一十雪
8579276381 fix 2024-04-16 13:10:07 +08:00
手瓜一十雪
7ba60b22c5 fix 2024-04-16 13:06:07 +08:00
linyuchen
031932f41c Merge remote-tracking branch 'origin/main' 2024-04-16 13:00:02 +08:00
linyuchen
079d0a89b1 fix: tsconfig path alias 2024-04-16 12:59:52 +08:00
手瓜一十雪
c4fdce6d64 fix 2024-04-16 12:55:16 +08:00
手瓜一十雪
5604c2b29f Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-04-16 12:55:05 +08:00
手瓜一十雪
74b5ab2b47 fix 2024-04-16 12:53:37 +08:00
linyuchen
c29cbfe123 Merge remote-tracking branch 'origin/main' 2024-04-16 12:51:42 +08:00
手瓜一十雪
6fe5cb1ffd remove 2024-04-16 12:51:12 +08:00
linyuchen
7edd5a7a8e Merge remote-tracking branch 'origin/main' 2024-04-16 12:50:22 +08:00
linyuchen
c1edc1b99b fix: Send empty forward msg 2024-04-16 12:50:14 +08:00
手瓜一十雪
4d1d890f72 fix 2024-04-16 12:47:36 +08:00
手瓜一十雪
fe0f82fa2b fix:checkVesion 2024-04-16 12:46:37 +08:00
手瓜一十雪
84083a65a8 fix:checkVesion 2024-04-16 12:45:07 +08:00
手瓜一十雪
fc91c6bc08 fix 2024-04-16 12:43:39 +08:00
手瓜一十雪
09120171ba fix 2024-04-16 12:42:07 +08:00
手瓜一十雪
a362f920dc fix:workflow 2024-04-16 12:41:18 +08:00
手瓜一十雪
9d7729f548 fix:workflow 2024-04-16 12:21:50 +08:00
手瓜一十雪
ed56e177cf chore:workflow version 2024-04-16 11:49:44 +08:00
手瓜一十雪
9db28bd502 fix:version output 2024-04-16 11:43:14 +08:00
linyuchen
aded70eb2e Create LICENSE 2024-04-16 10:27:32 +08:00
手瓜一十雪
dfbad85465 re:version 2024-04-16 10:02:40 +08:00
手瓜一十雪
52076fe182 chore: version 2024-04-16 08:50:48 +08:00
linyuchen
5575c3cb13 style: remove unused import 2024-04-15 22:44:48 +08:00
linyuchen
637d32efff fix: calculate qq level 2024-04-15 22:44:29 +08:00
linyuchen
fd54658e53 todo: retry get groups if groups length is 0 2024-04-15 22:42:31 +08:00
linyuchen
2f39a8d76e refactor: rename extends api folder 2024-04-15 22:39:31 +08:00
linyuchen
6a3e793500 style: comment unused function 2024-04-15 22:39:06 +08:00
linyuchen
3b3ffeda6b script: gen version 2024-04-15 22:36:06 +08:00
linyuchen
f7d92a3b11 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	script/napcat.bat
2024-04-15 22:31:18 +08:00
linyuchen
d9d9ba8bf1 fix: Support Onebot v11 get_forward_msg 2024-04-15 17:39:18 +08:00
linyuchen
d66ab7d389 chore: start bat 2024-04-15 01:38:46 +08:00
26 changed files with 188 additions and 70 deletions

View File

@@ -1,11 +1,36 @@
name: "release"
on:
push:
tags:
- "v*"
permissions: write-all
jobs:
check-version:
runs-on: ubuntu-latest
steps:
- name: Clone Repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Use Node.js 20.X
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Check Version
run: |
ls
node ./script/checkVersion.cjs
sh ./checkVersion.sh
build-linux:
needs: [check-version]
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -23,6 +48,7 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Build NuCat Linux
run: |
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
@@ -37,6 +63,7 @@ jobs:
path: dist
build-win32:
runs-on: ubuntu-latest
needs: [check-version]
strategy:
fail-fast: false
matrix:
@@ -49,10 +76,12 @@ jobs:
repository: 'NapNeko/NapCatQQ'
submodules: true
token: ${{ secrets.NAPCAT_BUILD }}
- name: Use Node.js 20.X
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Build NuCat Linux
run: |
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
@@ -60,11 +89,13 @@ jobs:
cd dist
npm i --omit=dev --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
cd ..
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: NapCat.${{ matrix.target_platform }}.${{ matrix.target_arch }}
path: dist
release-napcat:
needs: [build-win32,build-linux]
runs-on: ubuntu-latest
@@ -78,6 +109,7 @@ jobs:
base=$(basename "$dir")
zip -r "${base}.zip" "$dir"
done
- name: Create Release Draft and Upload Artifacts
uses: softprops/action-gh-release@v1
with:

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@ src/core.lib/common/
# Build
*.db
checkVersion.sh

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 NapCatQQ
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

15
script/checkVersion.cjs Normal file
View File

@@ -0,0 +1,15 @@
let fs = require("fs");
let process = require("process")
console.log("[NapCat] [CheckVersion] 开始检测当前仓库版本...");
let currentVersion = require("../package.json").version;
let targetVersion = process.env.VERSION;
console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, " targetVersion:", targetVersion);
// fs.mkdirSync("./dist");
if (currentVersion === targetVersion) {
fs.writeFileSync("./checkVersion.sh", "#!/bin/bashe\necho \"CheckVersion Is Done\"")
} else {
let packageJson = JSON.parse(fs.readFileSync("./package.json"));
packageJson.version = targetVersion;
fs.writeFileSync("./package.json", JSON.stringify(packageJson));
fs.writeFileSync("./checkVersion.sh", "#!/bin/bashe\ngit config --global user.email \"bot@test.mail\"\n git config --global user.name \"Version\"\ngit checkout main\ngit add .\n git commit -m \"chore:version change\"\n git push -u origin main")
}

21
script/gen-version.ts Normal file
View File

@@ -0,0 +1,21 @@
import fs from 'fs'
import path from 'path'
import { version } from '../src/onebot11/version'
const manifestPath = path.join(__dirname, '../package.json')
function readManifest (): any {
if (fs.existsSync(manifestPath)) {
return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'))
}
}
function writeManifest (manifest: any) {
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2))
}
const manifest = readManifest()
if (version !== manifest.version) {
manifest.version = version
writeManifest(manifest)
}

3
script/napcat-custom.bat Normal file
View File

@@ -0,0 +1,3 @@
chcp 65001
set ELECTRON_RUN_AS_NODE=1
"H:\Program Files\QQNT最新版\QQ.exe" %~dp0/napcat.cjs %*

View File

@@ -29,7 +29,10 @@ export class WebsocketServerBase {
start(port: number) {
try {
this.ws = new WebSocketServer({ port });
this.ws = new WebSocketServer({
port ,
maxPayload: 1024 * 1024 * 1024
});
} catch (e: any) {
throw Error('ws服务启动失败, ' + e.toString());
}

View File

@@ -8,7 +8,6 @@ import { dbUtil } from './db';
import * as fileType from 'file-type';
import { v4 as uuidv4 } from 'uuid';
import { napCatCore } from '@/core';
import os from 'node:os';
export const getNapCatDir = () => {
const p = path.join(napCatCore.wrapper.dataPath, 'NapCat');

View File

@@ -1,5 +1,4 @@
import crypto from 'node:crypto';
import { resolve } from 'dns';
export function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));

View File

@@ -1,5 +1,5 @@
// QQ等级换算
import { QQLevel } from '../../ntqqapi/types';
import { QQLevel } from '@/core/qqnt/entities';
export function calcQQLevel(level: QQLevel) {
const { crownNum, sunNum, moonNum, starNum } = level;

1
src/core Submodule

Submodule src/core added at 0e7c9d43c4

View File

@@ -21,7 +21,6 @@ export interface GetFileResponse {
base64?: string;
}
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
private getElement(msg: RawMessage): { id: string, element: VideoElement | FileElement } {
let element = msg.elements.find(e => e.fileElement);

View File

@@ -7,6 +7,7 @@ import { ActionName } from '../types';
interface Payload {
message_id: string; // long msg id
id?: string; // short msg id
}
interface Response {
@@ -17,7 +18,7 @@ export class GoCQHTTGetForwardMsgAction extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetForwardMsg;
protected async _handle(payload: Payload): Promise<any> {
const rootMsg = await dbUtil.getMsgByLongId(payload.message_id);
const rootMsg = await dbUtil.getMsgByLongId( payload.id || payload.message_id);
if (!rootMsg) {
throw Error('msg not found');
}

View File

@@ -3,16 +3,18 @@ import { OB11Constructor } from '../../constructor';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { groups } from '@/common/data';
import {NTQQGroupApi} from "@/core/qqnt/apis";
class GetGroupList extends BaseAction<null, OB11Group[]> {
actionName = ActionName.GetGroupList;
protected async _handle(payload: null) {
// if (groups.length === 0) {
if (groups.size === 0) {
//todo: get groups
// const groups = await NTQQGroupApi.getGroups(true)
// log("get groups", groups)
// }
}
return OB11Constructor.groups(Array.from(groups.values()));
}
}

View File

@@ -24,7 +24,7 @@ import SendLike from './user/SendLike';
import SetGroupAddRequest from './group/SetGroupAddRequest';
import SetGroupLeave from './group/SetGroupLeave';
import GetGuildList from './group/GetGuildList';
import Debug from './llonebot/Debug';
import Debug from '@/onebot11/action/extends/Debug';
import SetFriendAddRequest from './user/SetFriendAddRequest';
import SetGroupWholeBan from './group/SetGroupWholeBan';
import SetGroupName from './group/SetGroupName';
@@ -37,9 +37,9 @@ import GetRecord from './file/GetRecord';
import GoCQHTTPMarkMsgAsRead from './msg/MarkMsgAsRead';
import CleanCache from './system/CleanCache';
import GoCQHTTPUploadGroupFile from './go-cqhttp/UploadGroupFile';
import { GetConfigAction, SetConfigAction } from './llonebot/Config';
import GetGroupAddRequest from './llonebot/GetGroupAddRequest';
import SetQQAvatar from './llonebot/SetQQAvatar';
import { GetConfigAction, SetConfigAction } from '@/onebot11/action/extends/Config';
import GetGroupAddRequest from '@/onebot11/action/extends/GetGroupAddRequest';
import SetQQAvatar from '@/onebot11/action/extends/SetQQAvatar';
import GoCQHTTPDownloadFile from './go-cqhttp/DownloadFile';
import GoCQHTTPGetGroupMsgHistory from './go-cqhttp/GetGroupMsgHistory';
import GetFile from './file/GetFile';

View File

@@ -17,7 +17,7 @@ class GetMsg extends BaseAction<PayloadType, OB11Message> {
protected async _handle(payload: PayloadType) {
// log("history msg ids", Object.keys(msgHistory));
if (!payload.message_id) {
throw ('参数message_id不能为空');
throw Error('参数message_id不能为空');
}
let msg = await dbUtil.getMsgByShortId(payload.message_id);
if (!msg) {

View File

@@ -27,7 +27,8 @@ import { log } from '@/common/utils/log';
import { sleep } from '@/common/utils/helper';
import { uri2local } from '@/common/utils/file';
import { getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } from '@/common/data';
import { NTQQMsgApi } from '@/core/qqnt/apis/msg';
import { NTQQMsgApi } from '@/core/qqnt/apis';
import { NTQQFileApi } from '@/core/qqnt/apis';
const ALLOW_SEND_TEMP_MSG = false;
@@ -144,25 +145,40 @@ export async function createSendElements(messageData: OB11MessageData[], group:
case OB11MessageDataType.file:
case OB11MessageDataType.video:
case OB11MessageDataType.voice: {
const file = sendMsg.data?.file;
let file = sendMsg.data?.file;
const payloadFileName = sendMsg.data?.name;
if (file) {
// todo: 使用缓存文件发送
// const cache = await dbUtil.getFileCache(file);
// if (cache) {
// if (fs.existsSync(cache.filePath)) {
// file = "file://" + cache.filePath;
// } else if (cache.downloadFunc) {
// await cache.downloadFunc();
// file = cache.filePath;
// } else if (cache.url) {
// file = cache.url;
// }
// log("找到文件缓存", file);
// }
const cache = await dbUtil.getFileCacheByName(file);
if (cache) {
if (fs.existsSync(cache.path)) {
file = 'file://' + cache.path;
}
else if (cache.url) {
file = cache.url;
}
else{
const fileMsg = await dbUtil.getMsgByLongId(cache.msgId);
if (fileMsg){
const downloadPath = await NTQQFileApi.downloadMedia(fileMsg.msgId, fileMsg.chatType, fileMsg.peerUid,
cache.elementId, '', '');
cache.path = downloadPath!;
dbUtil.updateFileCache(cache).then();
file = 'file://' + cache.path;
}
// await sleep(1000);
// log('download result', downloadPath);
// log('下载完成后的msg', msg);
}
log('找到文件缓存', file);
}
const { path, isLocal, fileName, errMsg } = (await uri2local(file));
if (errMsg) {
throw errMsg;
log('文件下载失败', errMsg);
throw Error('文件下载失败' + errMsg);
// throw (errMsg);
// continue
}
if (path) {
if (!isLocal) { // 只删除http和base64转过来的文件
@@ -311,7 +327,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group);
return { message_id: returnMsg!.id! };
} catch (e: any) {
throw ('发送转发消息失败 ' + e.toString());
throw Error('发送转发消息失败 ' + e.toString());
}
} else {
if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) {
@@ -482,6 +498,9 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
// nodeIds.push(nodeMsg.msgId)
// await sleep(500);
// 开发转发
if (nodeMsgIds.length === 0){
throw Error('转发消息失败,生成节点为空');
}
try {
log('开发转发', nodeMsgIds);
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds);

View File

@@ -21,15 +21,16 @@ checkVersion().then((remoteVersion: string) => {
const localVersion = require('./package.json').version;
const localVersionList = localVersion.split('.');
const remoteVersionList = remoteVersion.split('.');
console.log('[NapCat] [Upate] 当前版本:', localVersion);
for (const k of [0, 1, 2]) {
if (parseInt(remoteVersionList[k]) > parseInt(localVersionList[k])) {
console.log('检测到更新,请前往 https://github.com/NapNeko/NapCatQQ 下载 NapCatQQ V', remoteVersion);
console.log('[NapCat] [Upate] 检测到更新,请前往 https://github.com/NapNeko/NapCatQQ 下载 NapCatQQ V', remoteVersion);
return;
} else if (parseInt(remoteVersionList[k]) < parseInt(localVersionList[k])) {
break;
}
}
console.log('当前已是最新版本,版本:', localVersion);
console.log('[NapCat] [Upate] 当前已是最新版本');
return;
});
new NapCatOnebot11();

View File

@@ -298,38 +298,38 @@ export class NapCatOnebot11 {
}
}
async postGroupMemberChange(groupList: Group[]) {
// todo: 有无更好的方法判断群成员变动
const newGroupList = groupList;
for (const group of newGroupList) {
const existGroup = await getGroup(group.groupCode);
if (existGroup) {
if (existGroup.memberCount > group.memberCount) {
log(`群(${group.groupCode})成员数量减少${existGroup.memberCount} -> ${group.memberCount}`);
const oldMembers = existGroup.members;
const newMembers = await NTQQGroupApi.getGroupMembers(group.groupCode);
group.members = newMembers;
const newMembersSet = new Set<string>(); // 建立索引降低时间复杂度
for (const member of newMembers) {
newMembersSet.add(member.uin);
}
// 判断bot是否是管理员如果是管理员不需要从这里得知有人退群这里的退群无法得知是主动退群还是被踢
const bot = await getGroupMember(group.groupCode, selfInfo.uin);
if (bot!.role == GroupMemberRole.admin || bot!.role == GroupMemberRole.owner) {
continue;
}
for (const member of oldMembers) {
if (!newMembersSet.has(member.uin) && member.uin != selfInfo.uin) {
postOB11Event(new OB11GroupDecreaseEvent(parseInt(group.groupCode), parseInt(member.uin), parseInt(member.uin), 'leave'));
break;
}
}
}
}
}
}
// async postGroupMemberChange(groupList: Group[]) {
// // todo: 有无更好的方法判断群成员变动
// const newGroupList = groupList;
// for (const group of newGroupList) {
// const existGroup = await getGroup(group.groupCode);
// if (existGroup) {
// if (existGroup.memberCount > group.memberCount) {
// log(`群(${group.groupCode})成员数量减少${existGroup.memberCount} -> ${group.memberCount}`);
// const oldMembers = existGroup.members;
// const newMembers = await NTQQGroupApi.getGroupMembers(group.groupCode);
// group.members = newMembers;
// const newMembersSet = new Set<string>(); // 建立索引降低时间复杂度
//
// for (const member of newMembers) {
// newMembersSet.add(member.uin);
// }
//
// // 判断bot是否是管理员如果是管理员不需要从这里得知有人退群这里的退群无法得知是主动退群还是被踢
// const bot = await getGroupMember(group.groupCode, selfInfo.uin);
// if (bot!.role == GroupMemberRole.admin || bot!.role == GroupMemberRole.owner) {
// continue;
// }
// for (const member of oldMembers) {
// if (!newMembersSet.has(member.uin) && member.uin != selfInfo.uin) {
// postOB11Event(new OB11GroupDecreaseEvent(parseInt(group.groupCode), parseInt(member.uin), parseInt(member.uin), 'leave'));
// break;
// }
// }
// }
// }
// }
// }
}
// export const napCatOneBot11 = new NapCatOnebot11();

View File

@@ -79,6 +79,7 @@ export class ReverseWebsocket {
private connect() {
const { token, heartInterval } = ob11Config;
this.websocket = new WebSocketClass(this.url, {
maxPayload: 1024 * 1024 * 1024,
handshakeTimeout: 2000,
perMessageDeflate: false,
headers: {

View File

@@ -1 +1 @@
export const version = '1.0.0';
export const version = '1.0.3';

View File

@@ -30,11 +30,11 @@
],
"@/core/qqnt/*": [
"./src/core/src/qqnt/*",
"./src/core.lib/src/qqnt/index"
"./src/core.lib/src/qqnt/*"
],
"@/core/*": [
"./src/core/src/*",
"./src/core.lib/src"
"./src/core.lib/src/*"
]
}
},