mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-13 00:10:27 +00:00
Implement password-based QQ login across the stack: add a PasswordLogin React component, integrate it into the QQ login page, and add a frontend controller method to call a new /QQLogin/PasswordLogin API. On the backend, add QQPasswordLoginHandler, router entry, and WebUiDataRuntime hooks (setPasswordLoginCall / requestPasswordLogin) plus a default handler. Register a password login callback in the shell (base.ts) that calls the kernel login service, handles common error cases and falls back to QR code when needed. Update types to include onPasswordLoginRequested and adjust NodeIKernelLoginService method signatures (including passwordLogin return type changed to Promise<QuickLoginResult>) and minor formatting fixes.
214 lines
6.1 KiB
TypeScript
214 lines
6.1 KiB
TypeScript
import store from 'napcat-common/src/store';
|
||
import { napCatVersion } from 'napcat-common/src/version';
|
||
import { NapCatCoreWorkingEnv, type LoginRuntimeType } from '../types';
|
||
|
||
const LoginRuntime: LoginRuntimeType = {
|
||
workingEnv: NapCatCoreWorkingEnv.Unknown,
|
||
LoginCurrentTime: Date.now(),
|
||
LoginCurrentRate: 0,
|
||
QQLoginStatus: false, // 已实现 但太傻了 得去那边注册个回调刷新
|
||
QQQRCodeURL: '',
|
||
QQLoginUin: '',
|
||
QQLoginInfo: {
|
||
uid: '',
|
||
uin: '',
|
||
nick: '',
|
||
},
|
||
QQLoginError: '',
|
||
QQVersion: 'unknown',
|
||
OneBotContext: null,
|
||
onQQLoginStatusChange: async (status: boolean) => {
|
||
LoginRuntime.QQLoginStatus = status;
|
||
},
|
||
onWebUiTokenChange: async (_token: string) => {
|
||
|
||
},
|
||
onRefreshQRCode: async () => {
|
||
// 默认空实现,由 shell 注册真实回调
|
||
},
|
||
NapCatHelper: {
|
||
onOB11ConfigChanged: async () => {
|
||
|
||
},
|
||
onQuickLoginRequested: async () => {
|
||
return { result: false, message: '' };
|
||
},
|
||
onPasswordLoginRequested: async () => {
|
||
return { result: false, message: '密码登录功能未初始化' };
|
||
},
|
||
onRestartProcessRequested: async () => {
|
||
return { result: false, message: '重启功能未初始化' };
|
||
},
|
||
QQLoginList: [],
|
||
NewQQLoginList: [],
|
||
},
|
||
NapCatVersion: napCatVersion,
|
||
WebUiConfigQuickFunction: async () => {
|
||
|
||
},
|
||
};
|
||
export const WebUiDataRuntime = {
|
||
setWorkingEnv (env: NapCatCoreWorkingEnv): void {
|
||
LoginRuntime.workingEnv = env;
|
||
},
|
||
getWorkingEnv (): NapCatCoreWorkingEnv {
|
||
return LoginRuntime.workingEnv;
|
||
},
|
||
setWebUiTokenChangeCallback (func: (token: string) => Promise<void>): void {
|
||
LoginRuntime.onWebUiTokenChange = func;
|
||
},
|
||
getWebUiTokenChangeCallback (): (token: string) => Promise<void> {
|
||
return LoginRuntime.onWebUiTokenChange;
|
||
},
|
||
checkLoginRate (ip: string, RateLimit: number): boolean {
|
||
const key = `login_rate:${ip}`;
|
||
const count = store.get<number>(key) || 0;
|
||
|
||
if (count === 0) {
|
||
// 第一次访问,设置计数器为1,并设置60秒过期
|
||
store.set(key, 1, 60);
|
||
return true;
|
||
}
|
||
|
||
if (count >= RateLimit) {
|
||
return false;
|
||
}
|
||
|
||
store.set(key, count + 1);
|
||
return true;
|
||
},
|
||
|
||
getQQLoginStatus (): LoginRuntimeType['QQLoginStatus'] {
|
||
return LoginRuntime.QQLoginStatus;
|
||
},
|
||
|
||
setQQLoginCallback (func: (status: boolean) => Promise<void>): void {
|
||
LoginRuntime.onQQLoginStatusChange = func;
|
||
},
|
||
|
||
getQQLoginCallback (): (status: boolean) => Promise<void> {
|
||
return LoginRuntime.onQQLoginStatusChange;
|
||
},
|
||
|
||
setQQLoginStatus (status: LoginRuntimeType['QQLoginStatus']): void {
|
||
LoginRuntime.QQLoginStatus = status;
|
||
},
|
||
|
||
setQQLoginQrcodeURL (url: LoginRuntimeType['QQQRCodeURL']): void {
|
||
LoginRuntime.QQQRCodeURL = url;
|
||
},
|
||
|
||
getQQLoginQrcodeURL (): LoginRuntimeType['QQQRCodeURL'] {
|
||
return LoginRuntime.QQQRCodeURL;
|
||
},
|
||
|
||
setQQLoginInfo (info: LoginRuntimeType['QQLoginInfo']): void {
|
||
LoginRuntime.QQLoginInfo = info;
|
||
LoginRuntime.QQLoginUin = info.uin.toString();
|
||
},
|
||
|
||
getQQLoginInfo (): LoginRuntimeType['QQLoginInfo'] {
|
||
return LoginRuntime.QQLoginInfo;
|
||
},
|
||
|
||
getQQLoginUin (): LoginRuntimeType['QQLoginUin'] {
|
||
return LoginRuntime.QQLoginUin;
|
||
},
|
||
|
||
getQQQuickLoginList (): LoginRuntimeType['NapCatHelper']['QQLoginList'] {
|
||
return LoginRuntime.NapCatHelper.QQLoginList;
|
||
},
|
||
|
||
setQQQuickLoginList (list: LoginRuntimeType['NapCatHelper']['QQLoginList']): void {
|
||
LoginRuntime.NapCatHelper.QQLoginList = list;
|
||
},
|
||
|
||
getQQNewLoginList (): LoginRuntimeType['NapCatHelper']['NewQQLoginList'] {
|
||
return LoginRuntime.NapCatHelper.NewQQLoginList;
|
||
},
|
||
|
||
setQQNewLoginList (list: LoginRuntimeType['NapCatHelper']['NewQQLoginList']): void {
|
||
LoginRuntime.NapCatHelper.NewQQLoginList = list;
|
||
},
|
||
|
||
setQuickLoginCall (func: LoginRuntimeType['NapCatHelper']['onQuickLoginRequested']): void {
|
||
LoginRuntime.NapCatHelper.onQuickLoginRequested = func;
|
||
},
|
||
|
||
requestQuickLogin: function (uin) {
|
||
return LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
|
||
} as LoginRuntimeType['NapCatHelper']['onQuickLoginRequested'],
|
||
|
||
setPasswordLoginCall (func: LoginRuntimeType['NapCatHelper']['onPasswordLoginRequested']): void {
|
||
LoginRuntime.NapCatHelper.onPasswordLoginRequested = func;
|
||
},
|
||
|
||
requestPasswordLogin: function (uin: string, passwordMd5: string) {
|
||
return LoginRuntime.NapCatHelper.onPasswordLoginRequested(uin, passwordMd5);
|
||
} as LoginRuntimeType['NapCatHelper']['onPasswordLoginRequested'],
|
||
|
||
setOnOB11ConfigChanged (func: LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged']): void {
|
||
LoginRuntime.NapCatHelper.onOB11ConfigChanged = func;
|
||
},
|
||
|
||
setOB11Config: function (ob11) {
|
||
return LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
|
||
} as LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged'],
|
||
|
||
GetNapCatVersion () {
|
||
return LoginRuntime.NapCatVersion;
|
||
},
|
||
|
||
setQQVersion (version: string) {
|
||
LoginRuntime.QQVersion = version;
|
||
},
|
||
|
||
getQQVersion () {
|
||
return LoginRuntime.QQVersion;
|
||
},
|
||
|
||
setWebUiConfigQuickFunction (func: LoginRuntimeType['WebUiConfigQuickFunction']): void {
|
||
LoginRuntime.WebUiConfigQuickFunction = func;
|
||
},
|
||
runWebUiConfigQuickFunction: async function () {
|
||
await LoginRuntime.WebUiConfigQuickFunction();
|
||
},
|
||
|
||
setOneBotContext (context: any): void {
|
||
LoginRuntime.OneBotContext = context;
|
||
},
|
||
|
||
getOneBotContext (): any | null {
|
||
return LoginRuntime.OneBotContext;
|
||
},
|
||
|
||
setRestartProcessCall (func: () => Promise<{ result: boolean; message: string; }>): void {
|
||
LoginRuntime.NapCatHelper.onRestartProcessRequested = func;
|
||
},
|
||
|
||
requestRestartProcess: async function () {
|
||
return await LoginRuntime.NapCatHelper.onRestartProcessRequested();
|
||
},
|
||
|
||
setQQLoginError (error: string): void {
|
||
LoginRuntime.QQLoginError = error;
|
||
},
|
||
|
||
getQQLoginError (): string {
|
||
return LoginRuntime.QQLoginError;
|
||
},
|
||
|
||
setRefreshQRCodeCallback (func: () => Promise<void>): void {
|
||
LoginRuntime.onRefreshQRCode = func;
|
||
},
|
||
|
||
getRefreshQRCodeCallback (): () => Promise<void> {
|
||
return LoginRuntime.onRefreshQRCode;
|
||
},
|
||
|
||
refreshQRCode: async function () {
|
||
LoginRuntime.QQLoginError = '';
|
||
await LoginRuntime.onRefreshQRCode();
|
||
},
|
||
};
|