mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
91df57d932 | ||
![]() |
e27d4c4302 | ||
![]() |
55847f6e10 | ||
![]() |
b39d8bae27 | ||
![]() |
b0cf23f775 | ||
![]() |
c641246056 | ||
![]() |
1e5bc9bbea |
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
nanaeonn@outlook.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
11
SECURITY.md
Normal file
11
SECURITY.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| > 4.0 | :white_check_mark: |
|
||||
| < 4.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
you should open an issue
|
@@ -4,7 +4,7 @@
|
||||
"name": "NapCatQQ",
|
||||
"slug": "NapCat.Framework",
|
||||
"description": "高性能的 OneBot 11 协议实现",
|
||||
"version": "4.6.9",
|
||||
"version": "4.7.1",
|
||||
"icon": "./logo.png",
|
||||
"authors": [
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "4.6.9",
|
||||
"version": "4.7.1",
|
||||
"scripts": {
|
||||
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
||||
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
||||
|
@@ -1 +1 @@
|
||||
export const napCatVersion = '4.6.9';
|
||||
export const napCatVersion = '4.7.1';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
export class NodeIKernelLoginListener {
|
||||
onLoginConnected(...args: any[]): any {
|
||||
onLoginConnected(): Promise<void> | void {
|
||||
}
|
||||
|
||||
onLoginDisConnected(...args: any[]): any {
|
||||
|
@@ -60,7 +60,10 @@ export interface QuickLoginResult {
|
||||
}
|
||||
|
||||
export interface NodeIKernelLoginService {
|
||||
getMsfStatus: () => number;
|
||||
|
||||
setLoginMiscData(arg0: string, value: string): unknown;
|
||||
|
||||
getMachineGuid(): string;
|
||||
|
||||
get(): NodeIKernelLoginService;
|
||||
|
@@ -30,6 +30,8 @@ import { InitWebUi } from '@/webui';
|
||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||
import { napCatVersion } from '@/common/version';
|
||||
import { NodeIO3MiscListener } from '@/core/listeners/NodeIO3MiscListener';
|
||||
import { sleep } from '@/common/helper';
|
||||
|
||||
// NapCat Shell App ES 入口文件
|
||||
async function handleUncaughtExceptions(logger: LogWrapper) {
|
||||
process.on('uncaughtException', (err) => {
|
||||
@@ -113,120 +115,118 @@ async function handleLogin(
|
||||
quickLoginUin: string | undefined,
|
||||
historyLoginList: LoginListItem[]
|
||||
): Promise<SelfInfo> {
|
||||
return new Promise<SelfInfo>((resolve) => {
|
||||
const loginListener = new NodeIKernelLoginListener();
|
||||
let isLogined = false;
|
||||
let context = { isLogined: false };
|
||||
let inner_resolve: (value: SelfInfo) => void;
|
||||
let selfInfo: Promise<SelfInfo> = new Promise((resolve) => {
|
||||
inner_resolve = resolve;
|
||||
handleLoginInner(context, logger, loginService, quickLoginUin, historyLoginList).then().catch(e => logger.logError(e));
|
||||
});
|
||||
// 连接服务
|
||||
|
||||
loginListener.onUserLoggedIn = (userid: string) => {
|
||||
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
||||
};
|
||||
|
||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||
isLogined = true;
|
||||
resolve({
|
||||
uid: loginResult.uid,
|
||||
uin: loginResult.uin,
|
||||
nick: '',
|
||||
online: true,
|
||||
});
|
||||
};
|
||||
|
||||
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
||||
WebUiDataRuntime.setQQLoginQrcodeURL(qrcodeUrl);
|
||||
|
||||
const realBase64 = pngBase64QrcodeData.replace(/^data:image\/\w+;base64,/, '');
|
||||
const buffer = Buffer.from(realBase64, 'base64');
|
||||
logger.logWarn('请扫描下面的二维码,然后在手Q上授权登录:');
|
||||
const qrcodePath = path.join(pathWrapper.cachePath, 'qrcode.png');
|
||||
qrcode.generate(qrcodeUrl, { small: true }, (res) => {
|
||||
logger.logWarn([
|
||||
'\n',
|
||||
res,
|
||||
'二维码解码URL: ' + qrcodeUrl,
|
||||
'如果控制台二维码无法扫码,可以复制解码url到二维码生成网站生成二维码再扫码,也可以打开下方的二维码路径图片进行扫码。',
|
||||
].join('\n'));
|
||||
fs.writeFile(qrcodePath, buffer, {}, () => {
|
||||
logger.logWarn('二维码已保存到', qrcodePath);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number) => {
|
||||
if (!isLogined) {
|
||||
logger.logError('[Core] [Login] Login Error,ErrType: ', errType, ' ErrCode:', errCode);
|
||||
if (errType == 1 && errCode == 3) {
|
||||
// 二维码过期刷新
|
||||
}
|
||||
loginService.getQRCodePicture();
|
||||
}
|
||||
};
|
||||
|
||||
loginListener.onLoginFailed = (...args) => {
|
||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', JSON.stringify(args));
|
||||
};
|
||||
|
||||
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger));
|
||||
const isConnect = loginService.connect();
|
||||
if (!isConnect) {
|
||||
logger.logError('核心登录服务连接失败!');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log('核心登录服务连接成功!');
|
||||
|
||||
loginService.getLoginList().then((res) => {
|
||||
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
||||
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
|
||||
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
|
||||
WebUiDataRuntime.setQQNewLoginList(list);
|
||||
const loginListener = new NodeIKernelLoginListener();
|
||||
loginListener.onUserLoggedIn = (userid: string) => {
|
||||
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
||||
};
|
||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||
context.isLogined = true;
|
||||
inner_resolve({
|
||||
uid: loginResult.uid,
|
||||
uin: loginResult.uin,
|
||||
nick: '',
|
||||
online: true,
|
||||
});
|
||||
|
||||
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
||||
return await new Promise((resolve) => {
|
||||
if (uin) {
|
||||
logger.log('正在快速登录 ', uin);
|
||||
loginService.quickLoginWithUin(uin).then(res => {
|
||||
if (res.loginErrorInfo.errMsg) {
|
||||
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
||||
}
|
||||
resolve({ result: true, message: '' });
|
||||
}).catch((e) => {
|
||||
logger.logError(e);
|
||||
resolve({ result: false, message: '快速登录发生错误' });
|
||||
});
|
||||
} else {
|
||||
resolve({ result: false, message: '快速登录失败' });
|
||||
}
|
||||
};
|
||||
|
||||
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
||||
WebUiDataRuntime.setQQLoginQrcodeURL(qrcodeUrl);
|
||||
|
||||
const realBase64 = pngBase64QrcodeData.replace(/^data:image\/\w+;base64,/, '');
|
||||
const buffer = Buffer.from(realBase64, 'base64');
|
||||
logger.logWarn('请扫描下面的二维码,然后在手Q上授权登录:');
|
||||
const qrcodePath = path.join(pathWrapper.cachePath, 'qrcode.png');
|
||||
qrcode.generate(qrcodeUrl, { small: true }, (res) => {
|
||||
logger.logWarn([
|
||||
'\n',
|
||||
res,
|
||||
'二维码解码URL: ' + qrcodeUrl,
|
||||
'如果控制台二维码无法扫码,可以复制解码url到二维码生成网站生成二维码再扫码,也可以打开下方的二维码路径图片进行扫码。',
|
||||
].join('\n'));
|
||||
fs.writeFile(qrcodePath, buffer, {}, () => {
|
||||
logger.logWarn('二维码已保存到', qrcodePath);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (quickLoginUin) {
|
||||
if (historyLoginList.some(u => u.uin === quickLoginUin)) {
|
||||
logger.log('正在快速登录 ', quickLoginUin);
|
||||
setTimeout(() => {
|
||||
loginService.quickLoginWithUin(quickLoginUin)
|
||||
.then(result => {
|
||||
if (result.loginErrorInfo.errMsg) {
|
||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||
if (!isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
})
|
||||
.catch();
|
||||
}, 1000);
|
||||
} else {
|
||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||
if (!isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
} else {
|
||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||
if (historyLoginList.length > 0) {
|
||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||
.join('\n')
|
||||
}`);
|
||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number) => {
|
||||
if (!context.isLogined) {
|
||||
logger.logError('[Core] [Login] Login Error,ErrType: ', errType, ' ErrCode:', errCode);
|
||||
if (errType == 1 && errCode == 3) {
|
||||
// 二维码过期刷新
|
||||
}
|
||||
loginService.getQRCodePicture();
|
||||
}
|
||||
};
|
||||
|
||||
loginListener.onLoginFailed = (...args) => {
|
||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', JSON.stringify(args));
|
||||
};
|
||||
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger));
|
||||
loginService.connect();
|
||||
await waitForNetworkConnection(loginService, logger);
|
||||
// 等待网络
|
||||
return await selfInfo;
|
||||
}
|
||||
async function handleLoginInner(context: { isLogined: boolean }, logger: LogWrapper, loginService: NodeIKernelLoginService, quickLoginUin: string | undefined, historyLoginList: LoginListItem[]) {
|
||||
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
||||
return await new Promise((resolve) => {
|
||||
if (uin) {
|
||||
logger.log('正在快速登录 ', uin);
|
||||
loginService.quickLoginWithUin(uin).then(res => {
|
||||
if (res.loginErrorInfo.errMsg) {
|
||||
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
||||
}
|
||||
resolve({ result: true, message: '' });
|
||||
}).catch((e) => {
|
||||
logger.logError(e);
|
||||
resolve({ result: false, message: '快速登录发生错误' });
|
||||
});
|
||||
} else {
|
||||
resolve({ result: false, message: '快速登录失败' });
|
||||
}
|
||||
});
|
||||
});
|
||||
if (quickLoginUin) {
|
||||
if (historyLoginList.some(u => u.uin === quickLoginUin)) {
|
||||
logger.log('正在快速登录 ', quickLoginUin);
|
||||
loginService.quickLoginWithUin(quickLoginUin)
|
||||
.then(result => {
|
||||
if (result.loginErrorInfo.errMsg) {
|
||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||
if (!context.isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
})
|
||||
.catch();
|
||||
} else {
|
||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||
if (!context.isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
} else {
|
||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||
if (historyLoginList.length > 0) {
|
||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||
.join('\n')
|
||||
}`);
|
||||
}
|
||||
loginService.getQRCodePicture();
|
||||
}
|
||||
|
||||
loginService.getLoginList().then((res) => {
|
||||
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
||||
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
|
||||
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
|
||||
WebUiDataRuntime.setQQNewLoginList(list);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -284,6 +284,20 @@ async function handleProxy(session: NodeIQQNTWrapperSession, logger: LogWrapper)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForNetworkConnection(loginService: NodeIKernelLoginService, logger: LogWrapper) {
|
||||
let network_ok = false;
|
||||
let tryCount = 0;
|
||||
while (!network_ok) {
|
||||
network_ok = loginService.getMsfStatus() === 0;
|
||||
logger.log('等待网络连接...');
|
||||
await sleep(500);
|
||||
tryCount++;
|
||||
}
|
||||
logger.log('网络已连接');
|
||||
return network_ok;
|
||||
}
|
||||
|
||||
export async function NCoreInitShell() {
|
||||
console.log('NapCat Shell App Loading...');
|
||||
const pathWrapper = new NapCatPathWrapper();
|
||||
|
Reference in New Issue
Block a user