mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
44ff92ad4b | ||
![]() |
892262eb85 | ||
![]() |
2d9cc4d198 | ||
![]() |
a0c479485d | ||
![]() |
5650f18e50 | ||
![]() |
553885d025 | ||
![]() |
35de00c4af | ||
![]() |
09583e5de5 | ||
![]() |
38b0b7cd00 | ||
![]() |
8b9c7b0c27 | ||
![]() |
1005619bf3 | ||
![]() |
3e09cff9cb | ||
![]() |
c24384e454 | ||
![]() |
f87a543406 | ||
![]() |
f752136283 | ||
![]() |
7e71622a44 | ||
![]() |
da92afb379 | ||
![]() |
d3062de5f9 | ||
![]() |
f1440b03a8 | ||
![]() |
9a8b266cef | ||
![]() |
2a9bc57120 | ||
![]() |
2ed83a0e30 | ||
![]() |
116e8fd30a | ||
![]() |
891f11173b | ||
![]() |
dfc7996c17 | ||
![]() |
dc0561d34f | ||
![]() |
4fb0845d79 | ||
![]() |
0e0d4837b8 | ||
![]() |
a6adde7966 | ||
![]() |
7b693132f9 | ||
![]() |
3c3114b6ab | ||
![]() |
5cdbf58f59 | ||
![]() |
6f0a4131a2 | ||
![]() |
aa520e2f5d | ||
![]() |
2c3b7e9ee8 | ||
![]() |
b86a28092a | ||
![]() |
d59e5f2133 | ||
![]() |
3fdd187102 | ||
![]() |
3f085fd8ae | ||
![]() |
a4fc131aec | ||
![]() |
d7d446c3fc | ||
![]() |
212666e603 | ||
![]() |
b545c28340 | ||
![]() |
72bc345515 | ||
![]() |
cc5082a9e3 | ||
![]() |
45782a6c6c | ||
![]() |
e86d646cce | ||
![]() |
92cfc6b8c8 | ||
![]() |
82289d9f1f | ||
![]() |
4cdbdaaf4e | ||
![]() |
ecde2427da | ||
![]() |
fed1ec5d83 | ||
![]() |
4fbd764ced | ||
![]() |
5361079010 | ||
![]() |
002d135ef5 | ||
![]() |
a39b0a4a78 | ||
![]() |
eb5d68422f | ||
![]() |
3dc13e5c2e | ||
![]() |
16881f057a | ||
![]() |
1cd7d0577f | ||
![]() |
3c872df97a | ||
![]() |
218b7bd2a0 | ||
![]() |
4552d6970d | ||
![]() |
4b319d15a7 | ||
![]() |
0ae3a4172c |
11
README.md
11
README.md
@@ -30,11 +30,16 @@ NapCatQQ 是现代化的基于 NTQQ 的 Bot 协议端实现
|
|||||||
|
|
||||||
[Cloudflare.Pages](https://napneko.pages.dev/)
|
[Cloudflare.Pages](https://napneko.pages.dev/)
|
||||||
|
|
||||||
[Server.Other](https://napcat.cyou/)
|
[Server.Other](https://docs.napcat.cyou/)
|
||||||
|
|
||||||
|
|
||||||
## 回家旅途
|
## 回家旅途
|
||||||
[QQ Group](https://qm.qq.com/q/I6LU87a0Yq)
|
[QQ Group#1](https://qm.qq.com/q/I6LU87a0Yq)
|
||||||
|
|
||||||
|
[QQ Group#2](https://qm.qq.com/q/uqh4I87KoM)
|
||||||
|
|
||||||
|
[Telegram](https://t.me/MelodicMoonlight)
|
||||||
|
|
||||||
|
> QQ Group#2 准许Bot / Telegram与QQ Group#2 为新建Group
|
||||||
|
|
||||||
## 性能设计/协议标准
|
## 性能设计/协议标准
|
||||||
NapCat 已实现90%+的 OneBot / GoCQ 标准接口,并提供兼容性保留接口,其设计理念遵守 无数据库/异步优先/后台刷新 的性能思想。
|
NapCat 已实现90%+的 OneBot / GoCQ 标准接口,并提供兼容性保留接口,其设计理念遵守 无数据库/异步优先/后台刷新 的性能思想。
|
||||||
|
BIN
external/LiteLoaderWrapper.zip
vendored
BIN
external/LiteLoaderWrapper.zip
vendored
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "4.2.25",
|
"version": "4.2.35",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"tdesign-icons-vue-next": "^0.3.3",
|
"tdesign-icons-vue-next": "^0.3.3",
|
||||||
"tdesign-vue-next": "^1.10.3",
|
"tdesign-vue-next": "^1.10.3",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
export class githubApiManager {
|
export class githubApiManager {
|
||||||
public async GetBaseData(): Promise<Response | null> {
|
public async GetBaseData(): Promise<Response | null> {
|
||||||
try {
|
try {
|
||||||
const ConfigResponse= await fetch('https://api.github.com/repos/NapNeko/NapCatQQ', {
|
const ConfigResponse = await fetch('https://api.github.com/repos/NapNeko/NapCatQQ', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { OneBotConfig } from '../../../src/onebot/config/config';
|
import { OneBotConfig } from '../../../src/onebot/config/config';
|
||||||
|
import { ResponseCode } from '../../../src/webui/src/const/status';
|
||||||
export class QQLoginManager {
|
export class QQLoginManager {
|
||||||
private retCredential: string;
|
private retCredential: string;
|
||||||
private readonly apiPrefix: string;
|
private readonly apiPrefix: string;
|
||||||
@@ -22,8 +22,8 @@ export class QQLoginManager {
|
|||||||
});
|
});
|
||||||
if (ConfigResponse.status == 200) {
|
if (ConfigResponse.status == 200) {
|
||||||
const ConfigResponseJson = await ConfigResponse.json();
|
const ConfigResponseJson = await ConfigResponse.json();
|
||||||
if (ConfigResponseJson.code == 0) {
|
if (ConfigResponseJson.code == ResponseCode.Success) {
|
||||||
return ConfigResponseJson?.data as OneBotConfig;
|
return ConfigResponseJson.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@@ -4,31 +4,17 @@
|
|||||||
<h2 class="sotheby-font">QQ Login</h2>
|
<h2 class="sotheby-font">QQ Login</h2>
|
||||||
<div class="login-methods">
|
<div class="login-methods">
|
||||||
<t-tooltip content="快速登录">
|
<t-tooltip content="快速登录">
|
||||||
<t-button
|
<t-button id="quick-login" class="login-method" :class="{ active: loginMethod === 'quick' }"
|
||||||
id="quick-login"
|
@click="loginMethod = 'quick'">Quick Login</t-button>
|
||||||
class="login-method"
|
|
||||||
:class="{ active: loginMethod === 'quick' }"
|
|
||||||
@click="loginMethod = 'quick'"
|
|
||||||
>Quick Login</t-button
|
|
||||||
>
|
|
||||||
</t-tooltip>
|
</t-tooltip>
|
||||||
<t-tooltip content="二维码登录">
|
<t-tooltip content="二维码登录">
|
||||||
<t-button
|
<t-button id="qrcode-login" class="login-method" :class="{ active: loginMethod === 'qrcode' }"
|
||||||
id="qrcode-login"
|
@click="loginMethod = 'qrcode'">QR Code</t-button>
|
||||||
class="login-method"
|
|
||||||
:class="{ active: loginMethod === 'qrcode' }"
|
|
||||||
@click="loginMethod = 'qrcode'"
|
|
||||||
>QR Code</t-button
|
|
||||||
>
|
|
||||||
</t-tooltip>
|
</t-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="loginMethod === 'quick'" id="quick-login-dropdown" class="login-form">
|
<div v-show="loginMethod === 'quick'" id="quick-login-dropdown" class="login-form">
|
||||||
<t-select
|
<t-select id="quick-login-select" v-model="selectedAccount" placeholder="Select Account"
|
||||||
id="quick-login-select"
|
@change="selectAccount">
|
||||||
v-model="selectedAccount"
|
|
||||||
placeholder="Select Account"
|
|
||||||
@change="selectAccount"
|
|
||||||
>
|
|
||||||
<t-option v-for="account in quickLoginList" :key="account" :value="account">{{ account }}</t-option>
|
<t-option v-for="account in quickLoginList" :key="account" :value="account">{{ account }}</t-option>
|
||||||
</t-select>
|
</t-select>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,7 +27,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
|
||||||
import * as QRCode from 'qrcode';
|
import * as QRCode from 'qrcode';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { MessagePlugin } from 'tdesign-vue-next';
|
import { MessagePlugin } from 'tdesign-vue-next';
|
||||||
@@ -55,6 +41,7 @@ const qrcodeCanvas = ref<HTMLCanvasElement | null>(null);
|
|||||||
const qqLoginManager = new QQLoginManager(localStorage.getItem('auth') || '');
|
const qqLoginManager = new QQLoginManager(localStorage.getItem('auth') || '');
|
||||||
let heartBeatTimer: number | null = null;
|
let heartBeatTimer: number | null = null;
|
||||||
let qrcodeUrl: string = '';
|
let qrcodeUrl: string = '';
|
||||||
|
|
||||||
const selectAccount = async (accountName: string): Promise<void> => {
|
const selectAccount = async (accountName: string): Promise<void> => {
|
||||||
const { result, errMsg } = await qqLoginManager.setQuickLogin(accountName);
|
const { result, errMsg } = await qqLoginManager.setQuickLogin(accountName);
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -88,10 +75,6 @@ const HeartBeat = async (): Promise<void> => {
|
|||||||
if (heartBeatTimer) {
|
if (heartBeatTimer) {
|
||||||
clearInterval(heartBeatTimer);
|
clearInterval(heartBeatTimer);
|
||||||
}
|
}
|
||||||
// //判断是否已经调转
|
|
||||||
// if (router.currentRoute.value.path !== '/dashboard/basic-info') {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
await MessagePlugin.success('登录成功即将跳转');
|
await MessagePlugin.success('登录成功即将跳转');
|
||||||
await router.push({ path: '/dashboard/basic-info' });
|
await router.push({ path: '/dashboard/basic-info' });
|
||||||
} else if (isLogined?.qrcodeurl && qrcodeUrl !== isLogined.qrcodeurl) {
|
} else if (isLogined?.qrcodeurl && qrcodeUrl !== isLogined.qrcodeurl) {
|
||||||
@@ -103,19 +86,38 @@ const HeartBeat = async (): Promise<void> => {
|
|||||||
const InitPages = async (): Promise<void> => {
|
const InitPages = async (): Promise<void> => {
|
||||||
quickLoginList.value = await qqLoginManager.getQQQuickLoginList();
|
quickLoginList.value = await qqLoginManager.getQQQuickLoginList();
|
||||||
qrcodeUrl = await qqLoginManager.getQQLoginQrcode();
|
qrcodeUrl = await qqLoginManager.getQQLoginQrcode();
|
||||||
|
await nextTick();
|
||||||
generateQrCode(qrcodeUrl, qrcodeCanvas.value);
|
generateQrCode(qrcodeUrl, qrcodeCanvas.value);
|
||||||
heartBeatTimer = window.setInterval(HeartBeat, 3000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
InitPages();
|
InitPages().then().catch((err) => {
|
||||||
|
console.error('InitPages Error:', err);
|
||||||
|
});
|
||||||
|
heartBeatTimer = window.setInterval(HeartBeat, 3000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (heartBeatTimer) {
|
||||||
|
clearInterval(heartBeatTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(loginMethod, async (newMethod) => {
|
||||||
|
if (newMethod === 'qrcode') {
|
||||||
|
await nextTick();
|
||||||
|
generateQrCode(qrcodeUrl, qrcodeCanvas.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.layout {
|
.layout {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-container {
|
.login-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -182,4 +184,4 @@ onMounted(() => {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, defineProps, onMounted, watch } from 'vue';
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import emitter from '@/ts/event-bus';
|
import emitter from '@/ts/event-bus';
|
||||||
|
|
||||||
type MenuItem = {
|
type MenuItem = {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<t-head-menu theme="light" class="bottom-menu">
|
<t-head-menu theme="light" class="bottom-menu">
|
||||||
<router-link v-for="item in menuItems" :key="item.value" :to="item.route">
|
<router-link v-for="item in menuItems" :key="item.value" :to="item.route">
|
||||||
<t-tooltip :content="item.label" placement="top">
|
<t-tooltip :content="item.label" placement="top">
|
||||||
<t-menu-item :value="item.value" :disabled="item.disabled" class="menu-item">
|
<t-menu-item :value="item.value" :disabled="item.disabled" class="menu-item">
|
||||||
@@ -7,15 +7,13 @@
|
|||||||
<t-icon :name="item.icon" />
|
<t-icon :name="item.icon" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- {{item.label}}-->
|
<!-- {{item.label}}-->
|
||||||
</t-menu-item>
|
</t-menu-item>
|
||||||
</t-tooltip>
|
</t-tooltip>
|
||||||
</router-link>
|
</router-link>
|
||||||
</t-head-menu>
|
</t-head-menu>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps } from 'vue';
|
|
||||||
|
|
||||||
type MenuItem = {
|
type MenuItem = {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
@@ -46,7 +46,7 @@ import {
|
|||||||
Loading as TLoading,
|
Loading as TLoading,
|
||||||
HeadMenu as THeadMenu
|
HeadMenu as THeadMenu
|
||||||
} from 'tdesign-vue-next';
|
} from 'tdesign-vue-next';
|
||||||
import { router } from './router';
|
import router from './router';
|
||||||
import 'tdesign-vue-next/es/style/index.css';
|
import 'tdesign-vue-next/es/style/index.css';
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
@@ -89,7 +89,11 @@
|
|||||||
<t-tag class="tag-item pgk-color"> WebUi: {{ pkg.version }} </t-tag>
|
<t-tag class="tag-item pgk-color"> WebUi: {{ pkg.version }} </t-tag>
|
||||||
<t-tag class="tag-item nc-color">
|
<t-tag class="tag-item nc-color">
|
||||||
NapCat:
|
NapCat:
|
||||||
{{ githubReleasesData&&githubReleasesData[0] ?.tag_name ? githubReleasesData[0].tag_name : napCatVersion }}
|
{{ napCatVersion }}
|
||||||
|
</t-tag>
|
||||||
|
<t-tag v-if="githubReleasesData&&githubReleasesData[0] ?.tag_name" class="tag-item nc-color">
|
||||||
|
New NapCat:
|
||||||
|
{{ githubReleasesData[0].tag_name }}
|
||||||
</t-tag>
|
</t-tag>
|
||||||
<t-tag class="tag-item td-color"> TDesign: {{ pkg.dependencies['tdesign-vue-next'] }} </t-tag>
|
<t-tag class="tag-item td-color"> TDesign: {{ pkg.dependencies['tdesign-vue-next'] }} </t-tag>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { HttpClientConfig } from '../../../../src/onebot/config/config';
|
import { HttpClientConfig } from '../../../../src/onebot/config/config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { HttpServerConfig } from '../../../../src/onebot/config/config';
|
import { HttpServerConfig } from '../../../../src/onebot/config/config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { WebsocketClientConfig } from '../../../../src/onebot/config/config';
|
import { WebsocketClientConfig } from '../../../../src/onebot/config/config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { WebsocketServerConfig } from '../../../../src/onebot/config/config';
|
import { WebsocketServerConfig } from '../../../../src/onebot/config/config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@@ -7,6 +7,8 @@ import NetWork from '../pages/NetWork.vue';
|
|||||||
import QQLogin from '../components/QQLogin.vue';
|
import QQLogin from '../components/QQLogin.vue';
|
||||||
import WebUiLogin from '../components/WebUiLogin.vue';
|
import WebUiLogin from '../components/WebUiLogin.vue';
|
||||||
import OtherConfig from '../pages/OtherConfig.vue';
|
import OtherConfig from '../pages/OtherConfig.vue';
|
||||||
|
import { MessagePlugin } from 'tdesign-vue-next';
|
||||||
|
import { QQLoginManager } from '@/backend/shell';
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{ path: '/', redirect: '/webui' },
|
{ path: '/', redirect: '/webui' },
|
||||||
@@ -26,7 +28,27 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from, next) => {
|
||||||
|
const isPublicRoute = ['/webui', '/qqlogin'].includes(to.path);
|
||||||
|
const token = localStorage.getItem('auth');
|
||||||
|
|
||||||
|
if (!isPublicRoute) {
|
||||||
|
if (!token) {
|
||||||
|
MessagePlugin.error('请先登录');
|
||||||
|
return next('/webui');
|
||||||
|
}
|
||||||
|
const login = await new QQLoginManager(token).checkWebUiLogined();
|
||||||
|
if (!login) {
|
||||||
|
MessagePlugin.error('请先登录');
|
||||||
|
return next('/webui');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
@@ -3,22 +3,15 @@
|
|||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"jsxImportSource": "vue",
|
"jsxImportSource": "vue",
|
||||||
"lib": [
|
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
||||||
"DOM",
|
|
||||||
"DOM.Iterable"
|
|
||||||
],
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": ["src/*"]
|
||||||
"src/*"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"types": [
|
"types": ["vite/client"],
|
||||||
"vite/client"
|
|
||||||
],
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
@@ -30,5 +23,5 @@
|
|||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"],
|
||||||
"references": [{"path": "./tsconfig.node.json"}]
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "4.2.25",
|
"version": "4.2.35",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
||||||
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
"@eslint/js": "^9.14.0",
|
"@eslint/js": "^9.14.0",
|
||||||
"@log4js-node/log4js-api": "^1.0.2",
|
"@log4js-node/log4js-api": "^1.0.2",
|
||||||
"@napneko/nap-proto-core": "^0.0.4",
|
"@napneko/nap-proto-core": "^0.0.4",
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-typescript": "^12.1.2",
|
||||||
"@rollup/plugin-typescript": "^11.1.6",
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@sinclair/typebox": "^0.34.9",
|
"@sinclair/typebox": "^0.34.9",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '4.2.25';
|
export const napCatVersion = '4.2.35';
|
||||||
|
@@ -8,6 +8,7 @@ import {
|
|||||||
MemberExtSourceType,
|
MemberExtSourceType,
|
||||||
NapCatCore,
|
NapCatCore,
|
||||||
GroupNotify,
|
GroupNotify,
|
||||||
|
GroupInfoSource,
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { isNumeric, solveAsyncProblem } from '@/common/helper';
|
import { isNumeric, solveAsyncProblem } from '@/common/helper';
|
||||||
import { LimitedHashTable } from '@/common/message-unique';
|
import { LimitedHashTable } from '@/common/message-unique';
|
||||||
@@ -24,6 +25,19 @@ export class NTQQGroupApi {
|
|||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchGroupDetail(groupCode: string) {
|
||||||
|
const [, detailInfo] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelGroupService/getGroupDetailInfo',
|
||||||
|
'NodeIKernelGroupListener/onGroupDetailInfoChange',
|
||||||
|
[groupCode, GroupInfoSource.KDATACARD],
|
||||||
|
(ret) => ret.result === 0,
|
||||||
|
(detailInfo) => detailInfo.groupCode === groupCode,
|
||||||
|
1,
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
return detailInfo;
|
||||||
|
}
|
||||||
|
|
||||||
async initApi() {
|
async initApi() {
|
||||||
this.initCache().then().catch(e => this.context.logger.logError(e));
|
this.initCache().then().catch(e => this.context.logger.logError(e));
|
||||||
}
|
}
|
||||||
|
24
src/core/external/appid.json
vendored
24
src/core/external/appid.json
vendored
@@ -110,5 +110,29 @@
|
|||||||
"6.9.62-30366": {
|
"6.9.62-30366": {
|
||||||
"appid": 537258401,
|
"appid": 537258401,
|
||||||
"qua": "V1_MAC_NQ_6.9.62_30366_GW_B"
|
"qua": "V1_MAC_NQ_6.9.62_30366_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.17-30483": {
|
||||||
|
"appid": 537258439,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.17_30483_GW_B"
|
||||||
|
},
|
||||||
|
"6.9.62-30483": {
|
||||||
|
"appid": 537258463,
|
||||||
|
"qua": "V1_MAC_NQ_6.9.62_30483_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.15-30483": {
|
||||||
|
"appid": 537258474,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.15_30483_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.17-30594": {
|
||||||
|
"appid": 537258439,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.17_30594_GW_B"
|
||||||
|
},
|
||||||
|
"6.9.62-30594": {
|
||||||
|
"appid": 537258463,
|
||||||
|
"qua": "V1_MAC_NQ_6.9.62_30594_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.15-30594": {
|
||||||
|
"appid": 537258474,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.15_30594_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
40
src/core/external/offset.json
vendored
40
src/core/external/offset.json
vendored
@@ -122,5 +122,45 @@
|
|||||||
"6.9.62-30366-arm64": {
|
"6.9.62-30366-arm64": {
|
||||||
"send": "4189770",
|
"send": "4189770",
|
||||||
"recv": "418BF88"
|
"recv": "418BF88"
|
||||||
|
},
|
||||||
|
"9.9.17-30483-x64": {
|
||||||
|
"send": "39AC1B0",
|
||||||
|
"recv": "39B05E4"
|
||||||
|
},
|
||||||
|
"6.9.62-30483-arm64": {
|
||||||
|
"send": "41896B0",
|
||||||
|
"recv": "418bec8"
|
||||||
|
},
|
||||||
|
"6.9.62-30483-x64": {
|
||||||
|
"send": "4669460",
|
||||||
|
"recv": "466BCCC"
|
||||||
|
},
|
||||||
|
"3.2.15-30483-x64": {
|
||||||
|
"send": "A402540",
|
||||||
|
"recv": "A405E40"
|
||||||
|
},
|
||||||
|
"3.2.15-30483-arm64": {
|
||||||
|
"send": "70C40E8",
|
||||||
|
"recv": "70C7920"
|
||||||
|
},
|
||||||
|
"9.9.17-30594-x64": {
|
||||||
|
"send": "39AC1B0",
|
||||||
|
"recv": "39B05E4"
|
||||||
|
},
|
||||||
|
"6.9.62-30594-arm64": {
|
||||||
|
"send": "41896B0",
|
||||||
|
"recv": "418bec8"
|
||||||
|
},
|
||||||
|
"6.9.62-30594-x64": {
|
||||||
|
"send": "4669460",
|
||||||
|
"recv": "466BCCC"
|
||||||
|
},
|
||||||
|
"3.2.15-30594-x64": {
|
||||||
|
"send": "A402540",
|
||||||
|
"recv": "A405E40"
|
||||||
|
},
|
||||||
|
"3.2.15-30594-arm64": {
|
||||||
|
"send": "70C40E8",
|
||||||
|
"recv": "70C7920"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { DataSource, Group, GroupListUpdateType, GroupMember, GroupNotify, ShutUpGroupMember } from '@/core/types';
|
import { DataSource, Group, GroupDetailInfo, GroupListUpdateType, GroupMember, GroupNotify, ShutUpGroupMember } from '@/core/types';
|
||||||
|
|
||||||
export class NodeIKernelGroupListener {
|
export class NodeIKernelGroupListener {
|
||||||
onGroupListInited(listEmpty: boolean): any { }
|
onGroupListInited(listEmpty: boolean): any { }
|
||||||
@@ -28,7 +28,7 @@ export class NodeIKernelGroupListener {
|
|||||||
onGroupConfMemberChange(...args: unknown[]): any {
|
onGroupConfMemberChange(...args: unknown[]): any {
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]): any {
|
onGroupDetailInfoChange(detailInfo: GroupDetailInfo): any {
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]): any {
|
onGroupExtListUpdate(...args: unknown[]): any {
|
||||||
|
@@ -3,6 +3,7 @@ export interface MiniAppReqCustomParams {
|
|||||||
desc: string;
|
desc: string;
|
||||||
picUrl: string;
|
picUrl: string;
|
||||||
jumpUrl: string;
|
jumpUrl: string;
|
||||||
|
webUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MiniAppReqTemplateParams {
|
export interface MiniAppReqTemplateParams {
|
||||||
|
@@ -124,7 +124,7 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isGroupReply(): boolean {
|
get isGroupReply(): boolean {
|
||||||
return this.messageClientSeq !== 0;
|
return this.messageClientSeq === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||||
|
@@ -30,7 +30,7 @@ class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAda
|
|||||||
shareType: req.shareType,
|
shareType: req.shareType,
|
||||||
versionId: req.versionId,
|
versionId: req.versionId,
|
||||||
withShareTicket: req.withShareTicket,
|
withShareTicket: req.withShareTicket,
|
||||||
webURL: "",
|
webURL: req.webUrl ?? "",
|
||||||
appidRich: Buffer.alloc(0),
|
appidRich: Buffer.alloc(0),
|
||||||
template: {
|
template: {
|
||||||
templateId: "",
|
templateId: "",
|
||||||
|
@@ -149,7 +149,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getGroupDetailInfo(groupCode: string, groupInfoSource: GroupInfoSource): Promise<unknown>;
|
getGroupDetailInfo(groupCode: string, groupInfoSource: GroupInfoSource): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ import { GeneralCallResult } from '@/core/services/common';
|
|||||||
import { MsgReqType, QueryMsgsParams, TmpChatInfoApi } from '@/core/types/msg';
|
import { MsgReqType, QueryMsgsParams, TmpChatInfoApi } from '@/core/types/msg';
|
||||||
|
|
||||||
export interface NodeIKernelMsgService {
|
export interface NodeIKernelMsgService {
|
||||||
|
buildMultiForwardMsg(req: { srcMsgIds: Array<string>, srcContact: Peer }): Promise<GeneralCallResult & { rspInfo: { elements: unknown } }>;
|
||||||
|
|
||||||
generateMsgUniqueId(chatType: number, time: string): string;
|
generateMsgUniqueId(chatType: number, time: string): string;
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ export interface NodeIKernelSearchService {
|
|||||||
penetrate: string
|
penetrate: string
|
||||||
}): Promise<GeneralCallResult>;// needs 1 arguments
|
}): Promise<GeneralCallResult>;// needs 1 arguments
|
||||||
|
|
||||||
searchLocalInfo(keywords: string, unknown: number/*4*/): unknown;
|
searchLocalInfo(keywords: string, type: number/*4*/): unknown;
|
||||||
|
|
||||||
cancelSearchLocalInfo(...args: any[]): unknown;// needs 3 arguments
|
cancelSearchLocalInfo(...args: any[]): unknown;// needs 3 arguments
|
||||||
|
|
||||||
|
@@ -17,7 +17,160 @@ export enum GroupInfoSource {
|
|||||||
KRECENTCONTACT,
|
KRECENTCONTACT,
|
||||||
KMOREPANEL
|
KMOREPANEL
|
||||||
}
|
}
|
||||||
|
export interface GroupDetailInfo {
|
||||||
|
groupCode: string;
|
||||||
|
groupUin: string;
|
||||||
|
ownerUid: string;
|
||||||
|
ownerUin: string;
|
||||||
|
groupFlag: number;
|
||||||
|
groupFlagExt: number;
|
||||||
|
maxMemberNum: number;
|
||||||
|
memberNum: number;
|
||||||
|
groupOption: number;
|
||||||
|
classExt: number;
|
||||||
|
groupName: string;
|
||||||
|
fingerMemo: string;
|
||||||
|
groupQuestion: string;
|
||||||
|
certType: number;
|
||||||
|
richFingerMemo: string;
|
||||||
|
tagRecord: any[];
|
||||||
|
shutUpAllTimestamp: number;
|
||||||
|
shutUpMeTimestamp: number;
|
||||||
|
groupTypeFlag: number;
|
||||||
|
privilegeFlag: number;
|
||||||
|
groupSecLevel: number;
|
||||||
|
groupFlagExt3: number;
|
||||||
|
isConfGroup: number;
|
||||||
|
isModifyConfGroupFace: number;
|
||||||
|
isModifyConfGroupName: number;
|
||||||
|
groupFlagExt4: number;
|
||||||
|
groupMemo: string;
|
||||||
|
cmdUinMsgSeq: number;
|
||||||
|
cmdUinJoinTime: number;
|
||||||
|
cmdUinUinFlag: number;
|
||||||
|
cmdUinMsgMask: number;
|
||||||
|
groupSecLevelInfo: number;
|
||||||
|
cmdUinPrivilege: number;
|
||||||
|
cmdUinFlagEx2: number;
|
||||||
|
appealDeadline: number;
|
||||||
|
remarkName: string;
|
||||||
|
isTop: boolean;
|
||||||
|
groupFace: number;
|
||||||
|
groupGeoInfo: {
|
||||||
|
ownerUid: string;
|
||||||
|
SetTime: number;
|
||||||
|
CityId: number;
|
||||||
|
Longitude: string;
|
||||||
|
Latitude: string;
|
||||||
|
GeoContent: string;
|
||||||
|
poiId: string;
|
||||||
|
};
|
||||||
|
certificationText: string;
|
||||||
|
cmdUinRingtoneId: number;
|
||||||
|
longGroupName: string;
|
||||||
|
autoAgreeJoinGroupUserNumForConfGroup: number;
|
||||||
|
autoAgreeJoinGroupUserNumForNormalGroup: number;
|
||||||
|
cmdUinFlagExt3Grocery: number;
|
||||||
|
groupCardPrefix: {
|
||||||
|
introduction: string;
|
||||||
|
rptPrefix: any[];
|
||||||
|
};
|
||||||
|
groupExt: {
|
||||||
|
groupInfoExtSeq: number;
|
||||||
|
reserve: number;
|
||||||
|
luckyWordId: string;
|
||||||
|
lightCharNum: number;
|
||||||
|
luckyWord: string;
|
||||||
|
starId: number;
|
||||||
|
essentialMsgSwitch: number;
|
||||||
|
todoSeq: number;
|
||||||
|
blacklistExpireTime: number;
|
||||||
|
isLimitGroupRtc: number;
|
||||||
|
companyId: number;
|
||||||
|
hasGroupCustomPortrait: number;
|
||||||
|
bindGuildId: string;
|
||||||
|
groupOwnerId: {
|
||||||
|
memberUin: string;
|
||||||
|
memberUid: string;
|
||||||
|
memberQid: string;
|
||||||
|
};
|
||||||
|
essentialMsgPrivilege: number;
|
||||||
|
msgEventSeq: string;
|
||||||
|
inviteRobotSwitch: number;
|
||||||
|
gangUpId: string;
|
||||||
|
qqMusicMedalSwitch: number;
|
||||||
|
showPlayTogetherSwitch: number;
|
||||||
|
groupFlagPro1: string;
|
||||||
|
groupBindGuildIds: {
|
||||||
|
guildIds: any[];
|
||||||
|
};
|
||||||
|
viewedMsgDisappearTime: string;
|
||||||
|
groupExtFlameData: {
|
||||||
|
switchState: number;
|
||||||
|
state: number;
|
||||||
|
dayNums: any[];
|
||||||
|
version: number;
|
||||||
|
updateTime: string;
|
||||||
|
isDisplayDayNum: boolean;
|
||||||
|
};
|
||||||
|
groupBindGuildSwitch: number;
|
||||||
|
groupAioBindGuildId: string;
|
||||||
|
groupExcludeGuildIds: {
|
||||||
|
guildIds: any[];
|
||||||
|
};
|
||||||
|
fullGroupExpansionSwitch: number;
|
||||||
|
fullGroupExpansionSeq: string;
|
||||||
|
inviteRobotMemberSwitch: number;
|
||||||
|
inviteRobotMemberExamine: number;
|
||||||
|
groupSquareSwitch: number;
|
||||||
|
};
|
||||||
|
msgLimitFrequency: number;
|
||||||
|
hlGuildAppid: number;
|
||||||
|
hlGuildSubType: number;
|
||||||
|
isAllowRecallMsg: number;
|
||||||
|
confUin: string;
|
||||||
|
confMaxMsgSeq: number;
|
||||||
|
confToGroupTime: number;
|
||||||
|
groupSchoolInfo: {
|
||||||
|
location: string;
|
||||||
|
grade: number;
|
||||||
|
school: string;
|
||||||
|
};
|
||||||
|
activeMemberNum: number;
|
||||||
|
groupGrade: number;
|
||||||
|
groupCreateTime: number;
|
||||||
|
subscriptionUin: string;
|
||||||
|
subscriptionUid: string;
|
||||||
|
noFingerOpenFlag: number;
|
||||||
|
noCodeFingerOpenFlag: number;
|
||||||
|
isGroupFreeze: number;
|
||||||
|
allianceId: string;
|
||||||
|
groupExtOnly: {
|
||||||
|
tribeId: number;
|
||||||
|
moneyForAddGroup: number;
|
||||||
|
};
|
||||||
|
isAllowConfGroupMemberModifyGroupName: number;
|
||||||
|
isAllowConfGroupMemberNick: number;
|
||||||
|
isAllowConfGroupMemberAtAll: number;
|
||||||
|
groupClassText: string;
|
||||||
|
groupFreezeReason: number;
|
||||||
|
headPortraitSeq: number;
|
||||||
|
groupHeadPortrait: {
|
||||||
|
portraitCnt: number;
|
||||||
|
portraitInfo: any[];
|
||||||
|
defaultId: number;
|
||||||
|
verifyingPortraitCnt: number;
|
||||||
|
verifyingPortraitInfo: any[];
|
||||||
|
};
|
||||||
|
cmdUinJoinMsgSeq: number;
|
||||||
|
cmdUinJoinRealMsgSeq: number;
|
||||||
|
groupAnswer: string;
|
||||||
|
groupAdminMaxNum: number;
|
||||||
|
inviteNoAuthNumLimit: string;
|
||||||
|
hlGuildOrgId: number;
|
||||||
|
isAllowHlGuildBinary: number;
|
||||||
|
localExitGroupReason: number;
|
||||||
|
}
|
||||||
export interface GroupExt0xEF0InfoFilter {
|
export interface GroupExt0xEF0InfoFilter {
|
||||||
bindGuildId: number;
|
bindGuildId: number;
|
||||||
blacklistExpireTime: number;
|
blacklistExpireTime: number;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
//LiteLoader需要提供部分IPC接口,以便于其他插件调用
|
//LiteLoader需要提供部分IPC接口,以便于其他插件调用
|
||||||
const { ipcMain } = require('electron');
|
const { ipcMain, BrowserWindow } = require('electron');
|
||||||
const napcat = require('./napcat.cjs');
|
const napcat = require('./napcat.cjs');
|
||||||
const { shell } = require('electron');
|
const { shell } = require('electron');
|
||||||
ipcMain.handle('napcat_get_webtoken', async (event, arg) => {
|
ipcMain.handle('napcat_get_webtoken', async (event, arg) => {
|
||||||
@@ -13,4 +13,14 @@ ipcMain.handle('napcat_get_reactweb', async (event, arg) => {
|
|||||||
let port = url.port;
|
let port = url.port;
|
||||||
let token = url.searchParams.get('token');
|
let token = url.searchParams.get('token');
|
||||||
return `https://napcat.152710.xyz/web_login?back=http://127.0.0.1:${port}&token=${token}`;
|
return `https://napcat.152710.xyz/web_login?back=http://127.0.0.1:${port}&token=${token}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('napcat_open_inner_url', (event, url) => {
|
||||||
|
const win = new BrowserWindow({
|
||||||
|
autoHideMenuBar: true,
|
||||||
|
});
|
||||||
|
win.loadURL(url);
|
||||||
|
win.webContents.setWindowOpenHandler(details => {
|
||||||
|
win.loadURL(details.url)
|
||||||
|
})
|
||||||
});
|
});
|
@@ -6,6 +6,9 @@ const napcat = {
|
|||||||
openExternalUrl: async (url) => {
|
openExternalUrl: async (url) => {
|
||||||
ipcRenderer.send('open_external_url', url);
|
ipcRenderer.send('open_external_url', url);
|
||||||
},
|
},
|
||||||
|
openInnerUrl: async (url) => {
|
||||||
|
ipcRenderer.send('napcat_open_inner_url', url);
|
||||||
|
},
|
||||||
getWebUiUrlReact: async () => {
|
getWebUiUrlReact: async () => {
|
||||||
return ipcRenderer.invoke('napcat_get_reactweb');
|
return ipcRenderer.invoke('napcat_get_reactweb');
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ export const onSettingWindowCreated = async (view) => {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
view.querySelector('.nc_openwebui').addEventListener('click', () => {
|
view.querySelector('.nc_openwebui').addEventListener('click', () => {
|
||||||
window.open(webui, '_blank');
|
window.napcat.openInnerUrl(webui);
|
||||||
});
|
});
|
||||||
view.querySelector('.nc_openwebui_ex').addEventListener('click', () => {
|
view.querySelector('.nc_openwebui_ex').addEventListener('click', () => {
|
||||||
window.napcat.openExternalUrl(webui);
|
window.napcat.openExternalUrl(webui);
|
||||||
|
@@ -29,7 +29,7 @@ export class OB11Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class OneBotAction<PayloadType, ReturnDataType> {
|
export abstract class OneBotAction<PayloadType, ReturnDataType> {
|
||||||
actionName: ActionName = ActionName.Unknown;
|
actionName: typeof ActionName[keyof typeof ActionName] = ActionName.Unknown;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
private validate: ValidateFunction<any> | undefined = undefined;
|
private validate: ValidateFunction<any> | undefined = undefined;
|
||||||
payloadSchema: any = undefined;
|
payloadSchema: any = undefined;
|
||||||
@@ -84,4 +84,4 @@ export abstract class OneBotAction<PayloadType, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract _handle(payload: PayloadType, adaptername: string): PromiseLike<ReturnDataType>;
|
abstract _handle(payload: PayloadType, adaptername: string): PromiseLike<ReturnDataType>;
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,8 @@ const SchemaData = Type.Union([
|
|||||||
desc: Type.String(),
|
desc: Type.String(),
|
||||||
picUrl: Type.String(),
|
picUrl: Type.String(),
|
||||||
jumpUrl: Type.String(),
|
jumpUrl: Type.String(),
|
||||||
rawArkData: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
|
webUrl: Type.Optional(Type.String()),
|
||||||
|
rawArkData: Type.Optional(Type.Union([Type.String()]))
|
||||||
}),
|
}),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
title: Type.String(),
|
title: Type.String(),
|
||||||
@@ -19,6 +20,7 @@ const SchemaData = Type.Union([
|
|||||||
picUrl: Type.String(),
|
picUrl: Type.String(),
|
||||||
jumpUrl: Type.String(),
|
jumpUrl: Type.String(),
|
||||||
iconUrl: Type.String(),
|
iconUrl: Type.String(),
|
||||||
|
webUrl: Type.Optional(Type.String()),
|
||||||
appId: Type.String(),
|
appId: Type.String(),
|
||||||
scene: Type.Union([Type.Number(), Type.String()]),
|
scene: Type.Union([Type.Number(), Type.String()]),
|
||||||
templateType: Type.Union([Type.Number(), Type.String()]),
|
templateType: Type.Union([Type.Number(), Type.String()]),
|
||||||
@@ -28,7 +30,7 @@ const SchemaData = Type.Union([
|
|||||||
versionId: Type.String(),
|
versionId: Type.String(),
|
||||||
sdkId: Type.String(),
|
sdkId: Type.String(),
|
||||||
withShareTicket: Type.Union([Type.Number(), Type.String()]),
|
withShareTicket: Type.Union([Type.Number(), Type.String()]),
|
||||||
rawArkData: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
|
rawArkData: Type.Optional(Type.Union([Type.String()]))
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
type Payload = Static<typeof SchemaData>;
|
type Payload = Static<typeof SchemaData>;
|
||||||
@@ -45,7 +47,8 @@ export class GetMiniAppArk extends GetPacketStatusDepends<Payload, {
|
|||||||
title: payload.title,
|
title: payload.title,
|
||||||
desc: payload.desc,
|
desc: payload.desc,
|
||||||
picUrl: payload.picUrl,
|
picUrl: payload.picUrl,
|
||||||
jumpUrl: payload.jumpUrl
|
jumpUrl: payload.jumpUrl,
|
||||||
|
webUrl: payload.webUrl,
|
||||||
} as MiniAppReqCustomParams;
|
} as MiniAppReqCustomParams;
|
||||||
if ('type' in payload) {
|
if ('type' in payload) {
|
||||||
reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template);
|
reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template);
|
||||||
@@ -63,13 +66,13 @@ export class GetMiniAppArk extends GetPacketStatusDepends<Payload, {
|
|||||||
verType: +verType,
|
verType: +verType,
|
||||||
shareType: +shareType,
|
shareType: +shareType,
|
||||||
versionId: versionId,
|
versionId: versionId,
|
||||||
withShareTicket: +withShareTicket
|
withShareTicket: +withShareTicket,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const arkData = await this.core.apis.PacketApi.pkt.operation.GetMiniAppAdaptShareInfo(reqParam);
|
const arkData = await this.core.apis.PacketApi.pkt.operation.GetMiniAppAdaptShareInfo(reqParam);
|
||||||
return {
|
return {
|
||||||
data: payload.rawArkData ? arkData : MiniAppInfoHelper.RawToSend(arkData)
|
data: payload.rawArkData === 'true' ? arkData : MiniAppInfoHelper.RawToSend(arkData)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,7 @@ const SchemaData = Type.Object({
|
|||||||
|
|
||||||
type Payload = Static<typeof SchemaData>;
|
type Payload = Static<typeof SchemaData>;
|
||||||
|
|
||||||
export class OCRImage extends OneBotAction<Payload, any> {
|
class OCRImageBase extends OneBotAction<Payload, any> {
|
||||||
actionName = ActionName.OCRImage;
|
|
||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
@@ -34,6 +33,10 @@ export class OCRImage extends OneBotAction<Payload, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IOCRImage extends OCRImage {
|
export class OCRImage extends OCRImageBase {
|
||||||
|
actionName = ActionName.OCRImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IOCRImage extends OCRImageBase {
|
||||||
actionName = ActionName.IOCRImage;
|
actionName = ActionName.IOCRImage;
|
||||||
}
|
}
|
||||||
|
@@ -8,14 +8,18 @@ const SchemaData = Type.Object({
|
|||||||
|
|
||||||
type Payload = Static<typeof SchemaData>;
|
type Payload = Static<typeof SchemaData>;
|
||||||
|
|
||||||
export class SetGroupSign extends GetPacketStatusDepends<Payload, any> {
|
class SetGroupSignBase extends GetPacketStatusDepends<Payload, any> {
|
||||||
actionName = ActionName.SetGroupSign;
|
|
||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
return await this.core.apis.PacketApi.pkt.operation.GroupSign(+payload.group_id);
|
return await this.core.apis.PacketApi.pkt.operation.GroupSign(+payload.group_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class SendGroupSign extends SetGroupSign {
|
|
||||||
|
export class SetGroupSign extends SetGroupSignBase {
|
||||||
|
actionName = ActionName.SendGroupSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SendGroupSign extends SetGroupSignBase {
|
||||||
actionName = ActionName.SendGroupSign;
|
actionName = ActionName.SendGroupSign;
|
||||||
}
|
}
|
||||||
|
@@ -17,14 +17,13 @@ class GetGroupInfo extends OneBotAction<Payload, OB11Group> {
|
|||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
|
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
|
||||||
if (!group) {
|
if (!group) {
|
||||||
const data = await this.core.apis.GroupApi.searchGroup(payload.group_id.toString());
|
const data = await this.core.apis.GroupApi.fetchGroupDetail(payload.group_id.toString());
|
||||||
if (!data) throw new Error('Group not found');
|
|
||||||
return {
|
return {
|
||||||
...data.searchGroupInfo,
|
...data,
|
||||||
group_id: +payload.group_id,
|
group_id: +payload.group_id,
|
||||||
group_name: data.searchGroupInfo.groupName,
|
group_name: data.groupName,
|
||||||
member_count: data.searchGroupInfo.memberNum,
|
member_count: data.memberNum,
|
||||||
max_member_count: data.searchGroupInfo.maxMemberNum,
|
max_member_count: data.maxMemberNum,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return OB11Construct.group(group);
|
return OB11Construct.group(group);
|
||||||
|
@@ -29,13 +29,14 @@ class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> {
|
|||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const isNocache = this.parseBoolean(payload.no_cache ?? true);
|
const isNocache = this.parseBoolean(payload.no_cache ?? true);
|
||||||
const uid = await this.getUid(payload.user_id);
|
const uid = await this.getUid(payload.user_id);
|
||||||
const [member, info] = await Promise.all([
|
const groupMember = this.core.apis.GroupApi.groupMemberCache.get(payload.group_id.toString())?.get(uid);
|
||||||
|
let [member, info] = await Promise.all([
|
||||||
this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache),
|
this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache),
|
||||||
this.core.apis.UserApi.getUserDetailInfo(uid),
|
this.core.apis.UserApi.getUserDetailInfo(uid),
|
||||||
]);
|
]);
|
||||||
if (!member) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`);
|
if (!member || !groupMember) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`);
|
||||||
if (info) {
|
if (info) {
|
||||||
Object.assign(member, info);
|
member = { ...groupMember, ...member, ...info };
|
||||||
} else {
|
} else {
|
||||||
this.core.context.logger.logDebug(`获取群成员详细信息失败, 只能返回基础信息`);
|
this.core.context.logger.logDebug(`获取群成员详细信息失败, 只能返回基础信息`);
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import SendMsg, { ContextMode } from '@/onebot/action/msg/SendMsg';
|
import { ContextMode, SendMsgBase } from '@/onebot/action/msg/SendMsg';
|
||||||
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
||||||
import { OB11PostSendMsg } from '@/onebot/types';
|
import { OB11PostSendMsg } from '@/onebot/types';
|
||||||
|
|
||||||
// 未检测参数
|
// 未检测参数
|
||||||
class SendGroupMsg extends SendMsg {
|
class SendGroupMsg extends SendMsgBase {
|
||||||
actionName = ActionName.SendGroupMsg;
|
actionName = ActionName.SendGroupMsg;
|
||||||
contextMode: ContextMode = ContextMode.Group;
|
contextMode: ContextMode = ContextMode.Group;
|
||||||
|
|
||||||
|
@@ -103,10 +103,7 @@ import { GetAiCharacters } from "@/onebot/action/extends/GetAiCharacters";
|
|||||||
import { GetGuildList } from './guild/GetGuildList';
|
import { GetGuildList } from './guild/GetGuildList';
|
||||||
import { GetGuildProfile } from './guild/GetGuildProfile';
|
import { GetGuildProfile } from './guild/GetGuildProfile';
|
||||||
|
|
||||||
|
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
export type ActionMap = Map<string, OneBotAction<any, any>>;
|
|
||||||
|
|
||||||
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
|
|
||||||
|
|
||||||
const actionHandlers = [
|
const actionHandlers = [
|
||||||
new GetGroupInfoEx(obContext, core),
|
new GetGroupInfoEx(obContext, core),
|
||||||
@@ -220,12 +217,30 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new SendGroupAiRecord(obContext, core),
|
new SendGroupAiRecord(obContext, core),
|
||||||
new GetAiCharacters(obContext, core),
|
new GetAiCharacters(obContext, core),
|
||||||
];
|
];
|
||||||
const actionMap = new Map();
|
|
||||||
for (const action of actionHandlers) {
|
type HandlerUnion = typeof actionHandlers[number];
|
||||||
actionMap.set(action.actionName, action);
|
type MapType = {
|
||||||
actionMap.set(action.actionName + '_async', action);
|
[H in HandlerUnion as H['actionName']]: H;
|
||||||
actionMap.set(action.actionName + '_rate_limited', action);
|
} & {
|
||||||
|
[H in HandlerUnion as `${H['actionName']}_async`]: H;
|
||||||
|
} & {
|
||||||
|
[H in HandlerUnion as `${H['actionName']}_rate_limited`]: H;
|
||||||
|
};
|
||||||
|
|
||||||
|
const _map = new Map<keyof MapType, HandlerUnion>();
|
||||||
|
|
||||||
|
actionHandlers.forEach(h => {
|
||||||
|
_map.set(h.actionName as keyof MapType, h);
|
||||||
|
_map.set(`${h.actionName}_async` as keyof MapType, h);
|
||||||
|
_map.set(`${h.actionName}_rate_limited` as keyof MapType, h);
|
||||||
|
});
|
||||||
|
|
||||||
|
function get<K extends keyof MapType>(key: K): MapType[K];
|
||||||
|
function get<K extends keyof MapType>(key: K): null;
|
||||||
|
function get<K extends keyof MapType>(key: K): HandlerUnion | null | MapType[K] {
|
||||||
|
return _map.get(key as keyof MapType) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionMap;
|
return { get };
|
||||||
}
|
}
|
||||||
|
export type ActionMap = ReturnType<typeof createActionMap>
|
||||||
|
@@ -88,8 +88,7 @@ function getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
|
export class SendMsgBase extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
|
||||||
actionName = ActionName.SendMsg;
|
|
||||||
contextMode = ContextMode.Normal;
|
contextMode = ContextMode.Normal;
|
||||||
|
|
||||||
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
||||||
@@ -379,4 +378,6 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SendMsg;
|
export default class SendMsg extends SendMsgBase {
|
||||||
|
actionName = ActionName.SendMsg;
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import SendMsg, { ContextMode } from './SendMsg';
|
import { ContextMode, SendMsgBase } from './SendMsg';
|
||||||
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
||||||
import { OB11PostSendMsg } from '@/onebot/types';
|
import { OB11PostSendMsg } from '@/onebot/types';
|
||||||
|
|
||||||
// 未检测参数
|
// 未检测参数
|
||||||
class SendPrivateMsg extends SendMsg {
|
class SendPrivateMsg extends SendMsgBase {
|
||||||
actionName = ActionName.SendPrivateMsg;
|
actionName = ActionName.SendPrivateMsg;
|
||||||
contextMode: ContextMode = ContextMode.Private;
|
contextMode: ContextMode = ContextMode.Private;
|
||||||
|
|
||||||
|
@@ -3,8 +3,6 @@ import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
|||||||
|
|
||||||
|
|
||||||
export abstract class GetPacketStatusDepends<PT, RT> extends OneBotAction<PT, RT> {
|
export abstract class GetPacketStatusDepends<PT, RT> extends OneBotAction<PT, RT> {
|
||||||
actionName = ActionName.GetPacketStatus;
|
|
||||||
|
|
||||||
protected async check(payload: PT): Promise<BaseCheckResult>{
|
protected async check(payload: PT): Promise<BaseCheckResult>{
|
||||||
if (!this.core.apis.PacketApi.available) {
|
if (!this.core.apis.PacketApi.available) {
|
||||||
return {
|
return {
|
||||||
@@ -18,6 +16,8 @@ export abstract class GetPacketStatusDepends<PT, RT> extends OneBotAction<PT, RT
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GetPacketStatus extends GetPacketStatusDepends<any, null> {
|
export class GetPacketStatus extends GetPacketStatusDepends<any, null> {
|
||||||
|
actionName = ActionName.GetPacketStatus;
|
||||||
|
|
||||||
async _handle(payload: any) {
|
async _handle(payload: any) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -13,134 +13,134 @@ export interface InvalidCheckResult {
|
|||||||
[k: string | number]: any;
|
[k: string | number]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ActionName {
|
export const ActionName = {
|
||||||
// onebot 11
|
// onebot 11
|
||||||
SendPrivateMsg = 'send_private_msg',
|
SendPrivateMsg : 'send_private_msg',
|
||||||
SendGroupMsg = 'send_group_msg',
|
SendGroupMsg : 'send_group_msg',
|
||||||
SendMsg = 'send_msg',
|
SendMsg : 'send_msg',
|
||||||
DeleteMsg = 'delete_msg',
|
DeleteMsg : 'delete_msg',
|
||||||
GetMsg = 'get_msg',
|
GetMsg : 'get_msg',
|
||||||
GoCQHTTP_GetForwardMsg = 'get_forward_msg',
|
GoCQHTTP_GetForwardMsg : 'get_forward_msg',
|
||||||
SendLike = 'send_like',
|
SendLike : 'send_like',
|
||||||
SetGroupKick = 'set_group_kick',
|
SetGroupKick : 'set_group_kick',
|
||||||
SetGroupBan = 'set_group_ban',
|
SetGroupBan : 'set_group_ban',
|
||||||
// SetGroupAnoymousBan = 'set_group_anonymous_ban',
|
// SetGroupAnoymousBan : 'set_group_anonymous_ban',
|
||||||
SetGroupWholeBan = 'set_group_whole_ban',
|
SetGroupWholeBan : 'set_group_whole_ban',
|
||||||
SetGroupAdmin = 'set_group_admin',
|
SetGroupAdmin : 'set_group_admin',
|
||||||
// SetGroupAnoymous = 'set_group_anonymous',
|
// SetGroupAnoymous : 'set_group_anonymous',
|
||||||
SetGroupCard = 'set_group_card',
|
SetGroupCard : 'set_group_card',
|
||||||
SetGroupName = 'set_group_name',
|
SetGroupName : 'set_group_name',
|
||||||
SetGroupLeave = 'set_group_leave',
|
SetGroupLeave : 'set_group_leave',
|
||||||
SetSpecialTittle = 'set_group_special_title',
|
SetSpecialTittle : 'set_group_special_title',
|
||||||
SetFriendAddRequest = 'set_friend_add_request',
|
SetFriendAddRequest : 'set_friend_add_request',
|
||||||
SetGroupAddRequest = 'set_group_add_request',
|
SetGroupAddRequest : 'set_group_add_request',
|
||||||
GetLoginInfo = 'get_login_info',
|
GetLoginInfo : 'get_login_info',
|
||||||
GoCQHTTP_GetStrangerInfo = 'get_stranger_info',
|
GoCQHTTP_GetStrangerInfo : 'get_stranger_info',
|
||||||
GetFriendList = 'get_friend_list',
|
GetFriendList : 'get_friend_list',
|
||||||
GetGroupInfo = 'get_group_info',
|
GetGroupInfo : 'get_group_info',
|
||||||
GetGroupList = 'get_group_list',
|
GetGroupList : 'get_group_list',
|
||||||
GetGroupMemberInfo = 'get_group_member_info',
|
GetGroupMemberInfo : 'get_group_member_info',
|
||||||
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',
|
||||||
CanSendRecord = 'can_send_record',
|
CanSendRecord : 'can_send_record',
|
||||||
GetStatus = 'get_status',
|
GetStatus : 'get_status',
|
||||||
GetVersionInfo = 'get_version_info',
|
GetVersionInfo : 'get_version_info',
|
||||||
// Reboot = 'set_restart',
|
// Reboot : 'set_restart',
|
||||||
// CleanCache = 'clean_cache',
|
// CleanCache : 'clean_cache',
|
||||||
|
|
||||||
// go-cqhttp
|
// go-cqhttp
|
||||||
SetQQProfile = 'set_qq_profile',
|
SetQQProfile : 'set_qq_profile',
|
||||||
// QidianGetAccountInfo = 'qidian_get_account_info',
|
// QidianGetAccountInfo : 'qidian_get_account_info',
|
||||||
GoCQHTTP_GetModelShow = '_get_model_show',
|
GoCQHTTP_GetModelShow : '_get_model_show',
|
||||||
GoCQHTTP_SetModelShow = '_set_model_show',
|
GoCQHTTP_SetModelShow : '_set_model_show',
|
||||||
GetOnlineClient = 'get_online_clients',
|
GetOnlineClient : 'get_online_clients',
|
||||||
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
|
// GetUnidirectionalFriendList : 'get_unidirectional_friend_list',
|
||||||
GoCQHTTP_DeleteFriend = 'delete_friend',
|
GoCQHTTP_DeleteFriend : 'delete_friend',
|
||||||
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
|
// DeleteUnidirectionalFriendList : 'delete_unidirectional_friend',
|
||||||
GoCQHTTP_MarkMsgAsRead = 'mark_msg_as_read',
|
GoCQHTTP_MarkMsgAsRead : 'mark_msg_as_read',
|
||||||
GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg',
|
GoCQHTTP_SendGroupForwardMsg : 'send_group_forward_msg',
|
||||||
GoCQHTTP_SendPrivateForwardMsg = 'send_private_forward_msg',
|
GoCQHTTP_SendPrivateForwardMsg : 'send_private_forward_msg',
|
||||||
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
|
GoCQHTTP_GetGroupMsgHistory : 'get_group_msg_history',
|
||||||
OCRImage = 'ocr_image',
|
OCRImage : 'ocr_image',
|
||||||
IOCRImage = '.ocr_image',
|
IOCRImage : '.ocr_image',
|
||||||
GetGroupSystemMsg = 'get_group_system_msg',
|
GetGroupSystemMsg : 'get_group_system_msg',
|
||||||
GoCQHTTP_GetEssenceMsg = 'get_essence_msg_list',
|
GoCQHTTP_GetEssenceMsg : 'get_essence_msg_list',
|
||||||
GoCQHTTP_GetGroupAtAllRemain = 'get_group_at_all_remain',
|
GoCQHTTP_GetGroupAtAllRemain : 'get_group_at_all_remain',
|
||||||
SetGroupPortrait = 'set_group_portrait',
|
SetGroupPortrait : 'set_group_portrait',
|
||||||
SetEssenceMsg = 'set_essence_msg',
|
SetEssenceMsg : 'set_essence_msg',
|
||||||
DelEssenceMsg = 'delete_essence_msg',
|
DelEssenceMsg : 'delete_essence_msg',
|
||||||
GoCQHTTP_SendGroupNotice = '_send_group_notice',
|
GoCQHTTP_SendGroupNotice : '_send_group_notice',
|
||||||
GoCQHTTP_GetGroupNotice = '_get_group_notice',
|
GoCQHTTP_GetGroupNotice : '_get_group_notice',
|
||||||
GoCQHTTP_UploadGroupFile = 'upload_group_file',
|
GoCQHTTP_UploadGroupFile : 'upload_group_file',
|
||||||
GOCQHTTP_DeleteGroupFile = 'delete_group_file',
|
GOCQHTTP_DeleteGroupFile : 'delete_group_file',
|
||||||
GoCQHTTP_CreateGroupFileFolder = 'create_group_file_folder',
|
GoCQHTTP_CreateGroupFileFolder : 'create_group_file_folder',
|
||||||
GoCQHTTP_DeleteGroupFileFolder = 'delete_group_folder',
|
GoCQHTTP_DeleteGroupFileFolder : 'delete_group_folder',
|
||||||
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
|
GoCQHTTP_GetGroupFileSystemInfo : 'get_group_file_system_info',
|
||||||
GoCQHTTP_GetGroupRootFiles = 'get_group_root_files',
|
GoCQHTTP_GetGroupRootFiles : 'get_group_root_files',
|
||||||
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
|
GoCQHTTP_GetGroupFilesByFolder : 'get_group_files_by_folder',
|
||||||
GOCQHTTP_GetGroupFileUrl = 'get_group_file_url',
|
GOCQHTTP_GetGroupFileUrl : 'get_group_file_url',
|
||||||
GOCQHTTP_UploadPrivateFile = 'upload_private_file',
|
GOCQHTTP_UploadPrivateFile : 'upload_private_file',
|
||||||
// GOCQHTTP_ReloadEventFilter = 'reload_event_filter',
|
// GOCQHTTP_ReloadEventFilter : 'reload_event_filter',
|
||||||
GoCQHTTP_DownloadFile = 'download_file',
|
GoCQHTTP_DownloadFile : 'download_file',
|
||||||
GoCQHTTP_CheckUrlSafely = 'check_url_safely',
|
GoCQHTTP_CheckUrlSafely : 'check_url_safely',
|
||||||
GoCQHTTP_GetWordSlices = '.get_word_slices',
|
GoCQHTTP_GetWordSlices : '.get_word_slices',
|
||||||
GoCQHTTP_HandleQuickAction = '.handle_quick_operation',
|
GoCQHTTP_HandleQuickAction : '.handle_quick_operation',
|
||||||
|
|
||||||
// 以下为扩展napcat扩展
|
// 以下为扩展napcat扩展
|
||||||
Unknown = 'unknown',
|
Unknown : 'unknown',
|
||||||
SharePeer = 'ArkSharePeer',
|
SharePeer : 'ArkSharePeer',
|
||||||
ShareGroupEx = 'ArkShareGroup',
|
ShareGroupEx : 'ArkShareGroup',
|
||||||
// RebootNormal = 'reboot_normal', //无快速登录重新启动
|
// RebootNormal : 'reboot_normal', //无快速登录重新启动
|
||||||
GetRobotUinRange = 'get_robot_uin_range',
|
GetRobotUinRange : 'get_robot_uin_range',
|
||||||
SetOnlineStatus = 'set_online_status',
|
SetOnlineStatus : 'set_online_status',
|
||||||
GetFriendsWithCategory = 'get_friends_with_category',
|
GetFriendsWithCategory : 'get_friends_with_category',
|
||||||
SetQQAvatar = 'set_qq_avatar',
|
SetQQAvatar : 'set_qq_avatar',
|
||||||
GetFile = 'get_file',
|
GetFile : 'get_file',
|
||||||
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',
|
||||||
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',
|
||||||
MarkGroupMsgAsRead = 'mark_group_msg_as_read',
|
MarkGroupMsgAsRead : 'mark_group_msg_as_read',
|
||||||
GetFriendMsgHistory = 'get_friend_msg_history',
|
GetFriendMsgHistory : 'get_friend_msg_history',
|
||||||
CreateCollection = 'create_collection',
|
CreateCollection : 'create_collection',
|
||||||
GetCollectionList = 'get_collection_list',
|
GetCollectionList : 'get_collection_list',
|
||||||
SetLongNick = 'set_self_longnick',
|
SetLongNick : 'set_self_longnick',
|
||||||
GetRecentContact = 'get_recent_contact',
|
GetRecentContact : 'get_recent_contact',
|
||||||
_MarkAllMsgAsRead = '_mark_all_as_read',
|
_MarkAllMsgAsRead : '_mark_all_as_read',
|
||||||
GetProfileLike = 'get_profile_like',
|
GetProfileLike : 'get_profile_like',
|
||||||
FetchCustomFace = 'fetch_custom_face',
|
FetchCustomFace : 'fetch_custom_face',
|
||||||
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',
|
||||||
GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
|
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',
|
||||||
GroupPoke = 'group_poke',
|
GroupPoke : 'group_poke',
|
||||||
GetPacketStatus = 'nc_get_packet_status',
|
GetPacketStatus : 'nc_get_packet_status',
|
||||||
GetUserStatus = 'nc_get_user_status',
|
GetUserStatus : 'nc_get_user_status',
|
||||||
GetRkey = 'nc_get_rkey',
|
GetRkey : 'nc_get_rkey',
|
||||||
GetGroupShutList = 'get_group_shut_list',
|
GetGroupShutList : 'get_group_shut_list',
|
||||||
|
|
||||||
GetGuildList = 'get_guild_list',
|
GetGuildList : 'get_guild_list',
|
||||||
GetGuildProfile = 'get_guild_service_profile',
|
GetGuildProfile : 'get_guild_service_profile',
|
||||||
|
|
||||||
GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
|
GetGroupIgnoredNotifies : 'get_group_ignored_notifies',
|
||||||
|
|
||||||
SetGroupSign = "set_group_sign",
|
SetGroupSign : "set_group_sign",
|
||||||
SendGroupSign = "send_group_sign",
|
SendGroupSign : "send_group_sign",
|
||||||
|
|
||||||
GetMiniAppArk = "get_mini_app_ark",
|
GetMiniAppArk : "get_mini_app_ark",
|
||||||
// UploadForwardMsg = "upload_forward_msg",
|
// UploadForwardMsg : "upload_forward_msg",
|
||||||
GetAiRecord = "get_ai_record",
|
GetAiRecord : "get_ai_record",
|
||||||
GetAiCharacters = "get_ai_characters",
|
GetAiCharacters : "get_ai_characters",
|
||||||
SendGroupAiRecord = "send_group_ai_record",
|
SendGroupAiRecord : "send_group_ai_record",
|
||||||
}
|
} as const;
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { ActionName } from '@/onebot/action/router';
|
import { ActionName } from '@/onebot/action/router';
|
||||||
import CanSendRecord from './CanSendRecord';
|
import CanSendRecord, { CanSend } from './CanSendRecord';
|
||||||
|
|
||||||
interface ReturnType {
|
interface ReturnType {
|
||||||
yes: boolean;
|
yes: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class CanSendImage extends CanSendRecord {
|
export default class CanSendImage extends CanSend {
|
||||||
actionName = ActionName.CanSendImage;
|
actionName = ActionName.CanSendImage;
|
||||||
}
|
}
|
||||||
|
@@ -5,12 +5,15 @@ interface ReturnType {
|
|||||||
yes: boolean;
|
yes: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class CanSendRecord extends OneBotAction<any, ReturnType> {
|
export class CanSend extends OneBotAction<any, ReturnType> {
|
||||||
actionName = ActionName.CanSendRecord;
|
|
||||||
|
|
||||||
async _handle(_payload: void): Promise<ReturnType> {
|
async _handle(_payload: void): Promise<ReturnType> {
|
||||||
return {
|
return {
|
||||||
yes: true,
|
yes: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default class CanSendRecord extends CanSend{
|
||||||
|
actionName = ActionName.CanSendRecord;
|
||||||
|
}
|
||||||
|
@@ -1,19 +1,5 @@
|
|||||||
import type { OneBotFriendApi } from '@/onebot/api/friend';
|
|
||||||
import type { OneBotUserApi } from '@/onebot/api/user';
|
|
||||||
import type { OneBotGroupApi } from '@/onebot/api/group';
|
|
||||||
import type { OneBotMsgApi } from '@/onebot/api/msg';
|
|
||||||
import type { OneBotQuickActionApi } from '@/onebot/api/quick-action';
|
|
||||||
|
|
||||||
export * from './friend';
|
export * from './friend';
|
||||||
export * from './group';
|
export * from './group';
|
||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './msg';
|
export * from './msg';
|
||||||
export * from './quick-action';
|
export * from './quick-action';
|
||||||
|
|
||||||
export interface StableOneBotApiWrapper {
|
|
||||||
FriendApi: OneBotFriendApi;
|
|
||||||
UserApi: OneBotUserApi;
|
|
||||||
GroupApi: OneBotGroupApi;
|
|
||||||
MsgApi: OneBotMsgApi;
|
|
||||||
QuickActionApi: OneBotQuickActionApi,
|
|
||||||
}
|
|
@@ -895,16 +895,16 @@ export class OneBotMsgApi {
|
|||||||
const calculateTotalSize = async (elements: SendMessageElement[]): Promise<number> => {
|
const calculateTotalSize = async (elements: SendMessageElement[]): Promise<number> => {
|
||||||
const sizePromises = elements.map(async element => {
|
const sizePromises = elements.map(async element => {
|
||||||
switch (element.elementType) {
|
switch (element.elementType) {
|
||||||
case ElementType.PTT:
|
case ElementType.PTT:
|
||||||
return (await fsPromise.stat(element.pttElement.filePath)).size;
|
return (await fsPromise.stat(element.pttElement.filePath)).size;
|
||||||
case ElementType.FILE:
|
case ElementType.FILE:
|
||||||
return (await fsPromise.stat(element.fileElement.filePath)).size;
|
return (await fsPromise.stat(element.fileElement.filePath)).size;
|
||||||
case ElementType.VIDEO:
|
case ElementType.VIDEO:
|
||||||
return (await fsPromise.stat(element.videoElement.filePath)).size;
|
return (await fsPromise.stat(element.videoElement.filePath)).size;
|
||||||
case ElementType.PIC:
|
case ElementType.PIC:
|
||||||
return (await fsPromise.stat(element.picElement.sourcePath)).size;
|
return (await fsPromise.stat(element.picElement.sourcePath)).size;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const sizes = await Promise.all(sizePromises);
|
const sizes = await Promise.all(sizePromises);
|
||||||
@@ -970,14 +970,14 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
groupChangDecreseType2String(type: number): GroupDecreaseSubType {
|
groupChangDecreseType2String(type: number): GroupDecreaseSubType {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 130:
|
case 130:
|
||||||
return 'leave';
|
return 'leave';
|
||||||
case 131:
|
case 131:
|
||||||
return 'kick';
|
return 'kick';
|
||||||
case 3:
|
case 3:
|
||||||
return 'kick_me';
|
return 'kick_me';
|
||||||
default:
|
default:
|
||||||
return 'kick';
|
return 'kick';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,8 +18,8 @@ import { ContextMode, createContext, normalize } from '@/onebot/action/msg/SendM
|
|||||||
import { isNull } from '@/common/helper';
|
import { isNull } from '@/common/helper';
|
||||||
|
|
||||||
export class OneBotQuickActionApi {
|
export class OneBotQuickActionApi {
|
||||||
private obContext: NapCatOneBot11Adapter;
|
obContext: NapCatOneBot11Adapter;
|
||||||
private core: NapCatCore;
|
core: NapCatCore;
|
||||||
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
this.obContext = obContext;
|
this.obContext = obContext;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
@@ -82,11 +82,20 @@ export class OneBotQuickActionApi {
|
|||||||
this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles, false).then().catch(e => this.core.context.logger.logError(e));
|
this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles, false).then().catch(e => this.core.context.logger.logError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async findNotify(flag: string) {
|
||||||
|
let notify = (await this.core.apis.GroupApi.getSingleScreenNotifies(false, 100)).find(e => e.seq == flag);
|
||||||
|
if (!notify) {
|
||||||
|
notify = (await this.core.apis.GroupApi.getSingleScreenNotifies(true, 100)).find(e => e.seq == flag);
|
||||||
|
}
|
||||||
|
return notify;
|
||||||
|
}
|
||||||
|
|
||||||
async handleGroupRequest(request: OB11GroupRequestEvent, quickAction: QuickActionGroupRequest) {
|
async handleGroupRequest(request: OB11GroupRequestEvent, quickAction: QuickActionGroupRequest) {
|
||||||
if (!isNull(quickAction.approve)) {
|
const noify = await this.findNotify(request.flag);
|
||||||
|
|
||||||
|
if (!isNull(quickAction.approve) && noify) {
|
||||||
this.core.apis.GroupApi.handleGroupRequest(
|
this.core.apis.GroupApi.handleGroupRequest(
|
||||||
request.flag,
|
noify,
|
||||||
quickAction.approve ? NTGroupRequestOperateTypes.KAGREE : NTGroupRequestOperateTypes.KREFUSE,
|
quickAction.approve ? NTGroupRequestOperateTypes.KAGREE : NTGroupRequestOperateTypes.KREFUSE,
|
||||||
quickAction.reason,
|
quickAction.reason,
|
||||||
).catch(e => this.core.context.logger.logError(e));
|
).catch(e => this.core.context.logger.logError(e));
|
||||||
@@ -94,8 +103,9 @@ export class OneBotQuickActionApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleFriendRequest(request: OB11FriendRequestEvent, quickAction: QuickActionFriendRequest) {
|
async handleFriendRequest(request: OB11FriendRequestEvent, quickAction: QuickActionFriendRequest) {
|
||||||
if (!isNull(quickAction.approve)) {
|
const notify = (await this.core.apis.FriendApi.getBuddyReq()).buddyReqs.find(e => e.reqTime == request.flag.toString());
|
||||||
this.core.apis.FriendApi.handleFriendRequest(request.flag, !!quickAction.approve).then().catch(e => this.core.context.logger.logError(e));
|
if (!isNull(quickAction.approve) && notify) {
|
||||||
|
this.core.apis.FriendApi.handleFriendRequest(notify, !!quickAction.approve).then().catch(e => this.core.context.logger.logError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ interface v1Config {
|
|||||||
export interface AdapterConfigInner {
|
export interface AdapterConfigInner {
|
||||||
name: string;
|
name: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
|
||||||
}
|
}
|
||||||
export type AdapterConfigWrap = AdapterConfigInner & Partial<NetworkConfigAdapter>;
|
export type AdapterConfigWrap = AdapterConfigInner & Partial<NetworkConfigAdapter>;
|
||||||
|
|
||||||
@@ -37,6 +38,14 @@ export interface AdapterConfig extends AdapterConfigInner {
|
|||||||
|
|
||||||
const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config;
|
const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config;
|
||||||
|
|
||||||
|
export interface PluginConfig extends AdapterConfig {
|
||||||
|
name: string;
|
||||||
|
enable: boolean;
|
||||||
|
messagePostFormat: string;
|
||||||
|
reportSelfMessage: boolean;
|
||||||
|
debug: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const httpServerDefaultConfigs = createDefaultAdapterConfig({
|
export const httpServerDefaultConfigs = createDefaultAdapterConfig({
|
||||||
name: 'http-server',
|
name: 'http-server',
|
||||||
enable: false as boolean,
|
enable: false as boolean,
|
||||||
@@ -127,7 +136,7 @@ export const mergeNetworkDefaultConfig = {
|
|||||||
websocketClients: websocketClientDefaultConfigs,
|
websocketClients: websocketClientDefaultConfigs,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig;
|
export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | PluginConfig;
|
||||||
type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig;
|
type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig;
|
||||||
|
|
||||||
export function mergeOneBotConfigs(
|
export function mergeOneBotConfigs(
|
||||||
@@ -233,4 +242,4 @@ export function getConfigBoolKey(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,6 @@ import {
|
|||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { OB11ConfigLoader } from '@/onebot/config';
|
import { OB11ConfigLoader } from '@/onebot/config';
|
||||||
import {
|
import {
|
||||||
IOB11NetworkAdapter,
|
|
||||||
OB11ActiveHttpAdapter,
|
OB11ActiveHttpAdapter,
|
||||||
OB11ActiveWebSocketAdapter,
|
OB11ActiveWebSocketAdapter,
|
||||||
OB11NetworkManager,
|
OB11NetworkManager,
|
||||||
@@ -31,7 +30,6 @@ import {
|
|||||||
OneBotMsgApi,
|
OneBotMsgApi,
|
||||||
OneBotQuickActionApi,
|
OneBotQuickActionApi,
|
||||||
OneBotUserApi,
|
OneBotUserApi,
|
||||||
StableOneBotApiWrapper,
|
|
||||||
} from '@/onebot/api';
|
} from '@/onebot/api';
|
||||||
import { ActionMap, createActionMap } from '@/onebot/action';
|
import { ActionMap, createActionMap } from '@/onebot/action';
|
||||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||||
@@ -45,8 +43,16 @@ import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecal
|
|||||||
import { LRUCache } from '@/common/lru-cache';
|
import { LRUCache } from '@/common/lru-cache';
|
||||||
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
||||||
import { BotOfflineEvent } from './event/notice/BotOfflineEvent';
|
import { BotOfflineEvent } from './event/notice/BotOfflineEvent';
|
||||||
import { AdapterConfigWrap, mergeOneBotConfigs, migrateOneBotConfigsV1, NetworkConfigAdapter, OneBotConfig } from './config/config';
|
import {
|
||||||
|
AdapterConfigWrap,
|
||||||
|
mergeOneBotConfigs,
|
||||||
|
migrateOneBotConfigsV1,
|
||||||
|
NetworkConfigAdapter,
|
||||||
|
OneBotConfig,
|
||||||
|
} from './config/config';
|
||||||
import { OB11Message } from './types';
|
import { OB11Message } from './types';
|
||||||
|
import { OB11PluginAdapter } from './network/plugin';
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
//OneBot实现类
|
//OneBot实现类
|
||||||
export class NapCatOneBot11Adapter {
|
export class NapCatOneBot11Adapter {
|
||||||
@@ -54,7 +60,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
readonly context: InstanceContext;
|
readonly context: InstanceContext;
|
||||||
|
|
||||||
configLoader: OB11ConfigLoader;
|
configLoader: OB11ConfigLoader;
|
||||||
public readonly apis: StableOneBotApiWrapper;
|
public readonly apis;
|
||||||
networkManager: OB11NetworkManager;
|
networkManager: OB11NetworkManager;
|
||||||
actions: ActionMap;
|
actions: ActionMap;
|
||||||
private readonly bootTime = Date.now() / 1000;
|
private readonly bootTime = Date.now() / 1000;
|
||||||
@@ -71,7 +77,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
UserApi: new OneBotUserApi(this, core),
|
UserApi: new OneBotUserApi(this, core),
|
||||||
FriendApi: new OneBotFriendApi(this, core),
|
FriendApi: new OneBotFriendApi(this, core),
|
||||||
MsgApi: new OneBotMsgApi(this, core),
|
MsgApi: new OneBotMsgApi(this, core),
|
||||||
QuickActionApi: new OneBotQuickActionApi(this, core),
|
QuickActionApi: new OneBotQuickActionApi(this, core)
|
||||||
} as const;
|
} as const;
|
||||||
this.actions = createActionMap(this, core);
|
this.actions = createActionMap(this, core);
|
||||||
this.networkManager = new OB11NetworkManager();
|
this.networkManager = new OB11NetworkManager();
|
||||||
@@ -106,11 +112,16 @@ export class NapCatOneBot11Adapter {
|
|||||||
const serviceInfo = await this.creatOneBotLog(ob11Config);
|
const serviceInfo = await this.creatOneBotLog(ob11Config);
|
||||||
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
||||||
|
|
||||||
// //创建NetWork服务
|
//创建NetWork服务
|
||||||
|
|
||||||
|
// 注册Plugin 如果需要基于NapCat进行快速开发
|
||||||
|
// this.networkManager.registerAdapter(
|
||||||
|
// new OB11PluginAdapter('myPlugin', this.core, this,this.actions)
|
||||||
|
// );
|
||||||
for (const key of ob11Config.network.httpServers) {
|
for (const key of ob11Config.network.httpServers) {
|
||||||
if (key.enable) {
|
if (key.enable) {
|
||||||
this.networkManager.registerAdapter(
|
this.networkManager.registerAdapter(
|
||||||
new OB11PassiveHttpAdapter(key.name, key, this.core, this.actions)
|
new OB11PassiveHttpAdapter(key.name, key, this.core, this, this.actions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,6 +139,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
key.name,
|
key.name,
|
||||||
key,
|
key,
|
||||||
this.core,
|
this.core,
|
||||||
|
this,
|
||||||
this.actions
|
this.actions
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -140,6 +152,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
key.name,
|
key.name,
|
||||||
key,
|
key,
|
||||||
this.core,
|
this.core,
|
||||||
|
this,
|
||||||
this.actions
|
this.actions
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -151,9 +164,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.initBuddyListener();
|
this.initBuddyListener();
|
||||||
this.initGroupListener();
|
this.initGroupListener();
|
||||||
|
|
||||||
await WebUiDataRuntime.setQQLoginUin(selfInfo.uin.toString());
|
WebUiDataRuntime.setQQLoginInfo(selfInfo);
|
||||||
await WebUiDataRuntime.setQQLoginStatus(true);
|
WebUiDataRuntime.setQQLoginStatus(true);
|
||||||
await WebUiDataRuntime.setOnOB11ConfigChanged(async (newConfig) => {
|
WebUiDataRuntime.setOnOB11ConfigChanged(async (newConfig) => {
|
||||||
const prev = this.configLoader.configData;
|
const prev = this.configLoader.configData;
|
||||||
this.configLoader.save(newConfig);
|
this.configLoader.save(newConfig);
|
||||||
this.context.logger.log(`OneBot11 配置更改:${JSON.stringify(prev)} -> ${JSON.stringify(newConfig)}`);
|
this.context.logger.log(`OneBot11 配置更改:${JSON.stringify(prev)} -> ${JSON.stringify(newConfig)}`);
|
||||||
@@ -186,10 +199,12 @@ export class NapCatOneBot11Adapter {
|
|||||||
await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter);
|
await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleConfigChange(
|
private async handleConfigChange<CT extends NetworkConfigAdapter>(
|
||||||
prevConfig: NetworkConfigAdapter[],
|
prevConfig: NetworkConfigAdapter[],
|
||||||
nowConfig: NetworkConfigAdapter[],
|
nowConfig: NetworkConfigAdapter[],
|
||||||
adapterClass: new (...args: any[]) => IOB11NetworkAdapter
|
adapterClass: new (
|
||||||
|
...args: ConstructorParameters<typeof IOB11NetworkAdapter<CT>>
|
||||||
|
) => IOB11NetworkAdapter<CT>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// 比较旧的在新的找不到的回收
|
// 比较旧的在新的找不到的回收
|
||||||
for (const adapterConfig of prevConfig) {
|
for (const adapterConfig of prevConfig) {
|
||||||
@@ -201,7 +216,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 通知新配置重载 删除关闭的 加入新开的
|
// 通知新配置重载 删除关闭的 加入新开的
|
||||||
for (const adapterConfig of nowConfig) {
|
for (const adapterConfig of nowConfig) {
|
||||||
const existingAdapter = this.networkManager.findSomeAdapter(adapterConfig.name);
|
const existingAdapter = this.networkManager.findSomeAdapter(adapterConfig.name);
|
||||||
if (existingAdapter) {
|
if (existingAdapter) {
|
||||||
@@ -210,7 +225,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
|
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
|
||||||
}
|
}
|
||||||
} else if (adapterConfig.enable) {
|
} else if (adapterConfig.enable) {
|
||||||
const newAdapter = new adapterClass(adapterConfig.name, adapterConfig, this.core, this.actions);
|
const newAdapter = new adapterClass(adapterConfig.name, adapterConfig as CT, this.core, this, this.actions);
|
||||||
await this.networkManager.registerAdapterAndOpen(newAdapter);
|
await this.networkManager.registerAdapterAndOpen(newAdapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,7 +458,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async emitMsg(message: RawMessage) {
|
private async emitMsg(message: RawMessage) {
|
||||||
const network = Object.values(this.configLoader.configData.network).flat() as Array<AdapterConfigWrap>;
|
const network = await this.networkManager.getAllConfig();
|
||||||
this.context.logger.logDebug('收到新消息 RawMessage', message);
|
this.context.logger.logDebug('收到新消息 RawMessage', message);
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
this.handleMsg(message, network),
|
this.handleMsg(message, network),
|
||||||
@@ -483,7 +498,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
ob11Msg.stringMsg.target_id = parseInt(message.peerUin);
|
ob11Msg.stringMsg.target_id = parseInt(message.peerUin);
|
||||||
ob11Msg.arrayMsg.target_id = parseInt(message.peerUin);
|
ob11Msg.arrayMsg.target_id = parseInt(message.peerUin);
|
||||||
}
|
}
|
||||||
if (e.messagePostFormat == 'string') {
|
if ('messagePostFormat' in e && e.messagePostFormat == 'string') {
|
||||||
msgMap.set(e.name, structuredClone(ob11Msg.stringMsg));
|
msgMap.set(e.name, structuredClone(ob11Msg.stringMsg));
|
||||||
} else {
|
} else {
|
||||||
msgMap.set(e.name, structuredClone(ob11Msg.arrayMsg));
|
msgMap.set(e.name, structuredClone(ob11Msg.arrayMsg));
|
||||||
|
@@ -1,62 +1,42 @@
|
|||||||
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
|
import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
|
||||||
import { createHmac } from 'crypto';
|
import { createHmac } from 'crypto';
|
||||||
import { LogWrapper } from '@/common/log';
|
|
||||||
import { QuickAction, QuickActionEvent } from '@/onebot/types';
|
import { QuickAction, QuickActionEvent } from '@/onebot/types';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { NapCatOneBot11Adapter } from '..';
|
import { NapCatOneBot11Adapter } from '..';
|
||||||
import { RequestUtil } from '@/common/request';
|
import { RequestUtil } from '@/common/request';
|
||||||
import { HttpClientConfig } from '@/onebot/config/config';
|
import { HttpClientConfig } from '@/onebot/config/config';
|
||||||
import { ActionMap } from '@/onebot/action';
|
import { ActionMap } from '@/onebot/action';
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
|
export class OB11ActiveHttpAdapter extends IOB11NetworkAdapter<HttpClientConfig> {
|
||||||
logger: LogWrapper;
|
|
||||||
isEnable: boolean = false;
|
|
||||||
public config: HttpClientConfig;
|
|
||||||
constructor(
|
constructor(
|
||||||
public name: string,
|
name: string, config: HttpClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
|
||||||
config: HttpClientConfig,
|
|
||||||
public core: NapCatCore,
|
|
||||||
public obContext: NapCatOneBot11Adapter,
|
|
||||||
public actions: ActionMap,
|
|
||||||
) {
|
) {
|
||||||
this.logger = core.context.logger;
|
super(name, config, core, obContext, actions);
|
||||||
this.config = structuredClone(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onEvent<T extends OB11EmitEventContent>(event: T) {
|
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||||
if (!this.isEnable) {
|
this.emitEventAsync(event).catch(e => this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e));
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
async emitEventAsync<T extends OB11EmitEventContent>(event: T) {
|
||||||
|
if (!this.isEnable) return;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'x-self-id': this.core.selfInfo.uin,
|
'x-self-id': this.core.selfInfo.uin,
|
||||||
};
|
};
|
||||||
|
|
||||||
const msgStr = JSON.stringify(event);
|
const msgStr = JSON.stringify(event);
|
||||||
if (this.config.token && this.config.token.length > 0) {
|
if (this.config.token) {
|
||||||
const hmac = createHmac('sha1', this.config.token);
|
const hmac = createHmac('sha1', this.config.token);
|
||||||
hmac.update(msgStr);
|
hmac.update(msgStr);
|
||||||
const sig = hmac.digest('hex');
|
headers['x-signature'] = 'sha1=' + hmac.digest('hex');
|
||||||
headers['x-signature'] = 'sha1=' + sig;
|
|
||||||
}
|
}
|
||||||
RequestUtil.HttpGetText(this.config.url, 'POST', msgStr, headers).then(async (res) => {
|
|
||||||
let resJson: QuickAction;
|
const data = await RequestUtil.HttpGetText(this.config.url, 'POST', msgStr, headers);
|
||||||
try {
|
const resJson: QuickAction = data ? JSON.parse(data) : {};
|
||||||
resJson = JSON.parse(res);
|
|
||||||
//logDebug('新消息事件HTTP上报返回快速操作: ', JSON.stringify(resJson));
|
await this.obContext.apis.QuickActionApi.handleQuickOperation(event as QuickActionEvent, resJson);
|
||||||
} catch (e) {
|
|
||||||
this.logger.logDebug('[OneBot] [Http Client] 新消息事件HTTP上报没有返回快速操作,不需要处理');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this.obContext.apis.QuickActionApi
|
|
||||||
.handleQuickOperation(event as QuickActionEvent, resJson)
|
|
||||||
.catch(e => this.logger.logError(e));
|
|
||||||
} catch (e: any) {
|
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e);
|
|
||||||
}
|
|
||||||
}).catch((e) => {
|
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报失败', e);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
@@ -66,20 +46,24 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
close() {
|
close() {
|
||||||
this.isEnable = false;
|
this.isEnable = false;
|
||||||
}
|
}
|
||||||
async reload(newconfig: HttpClientConfig) {
|
|
||||||
|
async reload(newConfig: HttpClientConfig) {
|
||||||
const wasEnabled = this.isEnable;
|
const wasEnabled = this.isEnable;
|
||||||
const oldUrl = this.config.url;
|
const oldUrl = this.config.url;
|
||||||
this.config = newconfig;
|
this.config = newConfig;
|
||||||
if (newconfig.enable && !wasEnabled) {
|
|
||||||
|
if (newConfig.enable && !wasEnabled) {
|
||||||
this.open();
|
this.open();
|
||||||
return OB11NetworkReloadType.NetWorkOpen;
|
return OB11NetworkReloadType.NetWorkOpen;
|
||||||
} else if (!newconfig.enable && wasEnabled) {
|
} else if (!newConfig.enable && wasEnabled) {
|
||||||
this.close();
|
this.close();
|
||||||
return OB11NetworkReloadType.NetWorkClose;
|
return OB11NetworkReloadType.NetWorkClose;
|
||||||
}
|
}
|
||||||
if (oldUrl !== newconfig.url) {
|
|
||||||
|
if (oldUrl !== newConfig.url) {
|
||||||
return OB11NetworkReloadType.NetWorkReload;
|
return OB11NetworkReloadType.NetWorkReload;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OB11NetworkReloadType.Normal;
|
return OB11NetworkReloadType.Normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,21 @@
|
|||||||
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
|
import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
|
||||||
import { WebSocket } from 'ws';
|
import { WebSocket } from 'ws';
|
||||||
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
|
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { ActionName } from '@/onebot/action/router';
|
import { ActionName } from '@/onebot/action/router';
|
||||||
import { OB11Response } from '@/onebot/action/OneBotAction';
|
import { OB11Response } from '@/onebot/action/OneBotAction';
|
||||||
import { LogWrapper } from '@/common/log';
|
|
||||||
import { ActionMap } from '@/onebot/action';
|
import { ActionMap } from '@/onebot/action';
|
||||||
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
|
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
|
||||||
import { WebsocketClientConfig } from '@/onebot/config/config';
|
import { WebsocketClientConfig } from '@/onebot/config/config';
|
||||||
|
import { NapCatOneBot11Adapter } from "@/onebot";
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
export class OB11ActiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketClientConfig> {
|
||||||
isEnable: boolean = false;
|
|
||||||
logger: LogWrapper;
|
|
||||||
private connection: WebSocket | null = null;
|
private connection: WebSocket | null = null;
|
||||||
private heartbeatRef: NodeJS.Timeout | null = null;
|
private heartbeatRef: NodeJS.Timeout | null = null;
|
||||||
public config: WebsocketClientConfig;
|
|
||||||
|
|
||||||
constructor(
|
constructor(name: string, config: WebsocketClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
|
||||||
public name: string,
|
super(name, config, core, obContext, actions);
|
||||||
confg: WebsocketClientConfig,
|
|
||||||
public core: NapCatCore,
|
|
||||||
public actions: ActionMap,
|
|
||||||
) {
|
|
||||||
this.logger = core.context.logger;
|
|
||||||
this.config = structuredClone(confg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onEvent<T extends OB11EmitEventContent>(event: T) {
|
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||||
@@ -133,7 +125,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleMessage(message: any) {
|
private async handleMessage(message: any) {
|
||||||
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
|
let receiveData: { action: typeof ActionName[keyof typeof ActionName], params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
|
||||||
let echo = undefined;
|
let echo = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -145,7 +137,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};// 兼容类型验证
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};// 兼容类型验证
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action as any);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的Api ' + receiveData.action);
|
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的Api ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的Api ' + receiveData.action, 1404, echo));
|
this.checkStateAndReply<any>(OB11Response.error('不支持的Api ' + receiveData.action, 1404, echo));
|
||||||
|
33
src/onebot/network/adapter.ts
Normal file
33
src/onebot/network/adapter.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { NetworkConfigAdapter } from "@/onebot/config/config";
|
||||||
|
import { LogWrapper } from "@/common/log";
|
||||||
|
import { NapCatCore } from "@/core";
|
||||||
|
import { NapCatOneBot11Adapter } from "@/onebot";
|
||||||
|
import { ActionMap } from "@/onebot/action";
|
||||||
|
import { OB11EmitEventContent, OB11NetworkReloadType } from "@/onebot/network/index";
|
||||||
|
|
||||||
|
export abstract class IOB11NetworkAdapter<CT extends NetworkConfigAdapter> {
|
||||||
|
name: string;
|
||||||
|
isEnable: boolean = false;
|
||||||
|
config: CT;
|
||||||
|
readonly logger: LogWrapper;
|
||||||
|
readonly core: NapCatCore;
|
||||||
|
readonly obContext: NapCatOneBot11Adapter;
|
||||||
|
readonly actions: ActionMap;
|
||||||
|
|
||||||
|
constructor(name: string, config: CT, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
|
||||||
|
this.name = name;
|
||||||
|
this.config = structuredClone(config);
|
||||||
|
this.core = core;
|
||||||
|
this.obContext = obContext;
|
||||||
|
this.actions = actions;
|
||||||
|
this.logger = core.context.logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract onEvent<T extends OB11EmitEventContent>(event: T): void;
|
||||||
|
|
||||||
|
abstract open(): void | Promise<void>;
|
||||||
|
|
||||||
|
abstract close(): void | Promise<void>;
|
||||||
|
|
||||||
|
abstract reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
import { OneBotEvent } from '@/onebot/event/OneBotEvent';
|
import { OneBotEvent } from '@/onebot/event/OneBotEvent';
|
||||||
import { OB11Message } from '@/onebot';
|
import { OB11Message } from '@/onebot';
|
||||||
import { ActionMap } from '@/onebot/action';
|
|
||||||
import { NetworkConfigAdapter } from '@/onebot/config/config';
|
import { NetworkConfigAdapter } from '@/onebot/config/config';
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
export type OB11EmitEventContent = OneBotEvent | OB11Message;
|
export type OB11EmitEventContent = OneBotEvent | OB11Message;
|
||||||
export enum OB11NetworkReloadType {
|
export enum OB11NetworkReloadType {
|
||||||
@@ -11,30 +11,20 @@ export enum OB11NetworkReloadType {
|
|||||||
NetWorkClose = 3,
|
NetWorkClose = 3,
|
||||||
NetWorkOpen = 4
|
NetWorkOpen = 4
|
||||||
}
|
}
|
||||||
export interface IOB11NetworkAdapter {
|
|
||||||
actions: ActionMap;
|
|
||||||
name: string;
|
|
||||||
isEnable: boolean;
|
|
||||||
config: NetworkConfigAdapter;
|
|
||||||
|
|
||||||
onEvent<T extends OB11EmitEventContent>(event: T): void;
|
|
||||||
|
|
||||||
open(): void | Promise<void>;
|
|
||||||
|
|
||||||
close(): void | Promise<void>;
|
|
||||||
|
|
||||||
reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OB11NetworkManager {
|
export class OB11NetworkManager {
|
||||||
adapters: Map<string, IOB11NetworkAdapter> = new Map();
|
adapters: Map<string, IOB11NetworkAdapter<NetworkConfigAdapter>> = new Map();
|
||||||
|
|
||||||
async openAllAdapters() {
|
async openAllAdapters() {
|
||||||
return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.open()));
|
return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.open()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async emitEvent(event: OB11EmitEventContent) {
|
async emitEvent(event: OB11EmitEventContent) {
|
||||||
return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.onEvent(event)));
|
return Promise.all(Array.from(this.adapters.values()).map(adapter => {
|
||||||
|
if (adapter.isEnable) {
|
||||||
|
return adapter.onEvent(event);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async emitEvents(events: OB11EmitEventContent[]) {
|
async emitEvents(events: OB11EmitEventContent[]) {
|
||||||
@@ -44,35 +34,37 @@ export class OB11NetworkManager {
|
|||||||
async emitEventByName(names: string[], event: OB11EmitEventContent) {
|
async emitEventByName(names: string[], event: OB11EmitEventContent) {
|
||||||
return Promise.all(names.map(name => {
|
return Promise.all(names.map(name => {
|
||||||
const adapter = this.adapters.get(name);
|
const adapter = this.adapters.get(name);
|
||||||
if (adapter) {
|
if (adapter && adapter.isEnable) {
|
||||||
return adapter.onEvent(event);
|
return adapter.onEvent(event);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async emitEventByNames(map: Map<string, OB11EmitEventContent>) {
|
async emitEventByNames(map: Map<string, OB11EmitEventContent>) {
|
||||||
return Promise.all(Array.from(map.entries()).map(([name, event]) => {
|
return Promise.all(Array.from(map.entries()).map(([name, event]) => {
|
||||||
const adapter = this.adapters.get(name);
|
const adapter = this.adapters.get(name);
|
||||||
if (adapter) {
|
if (adapter && adapter.isEnable) {
|
||||||
return adapter.onEvent(event);
|
return adapter.onEvent(event);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
registerAdapter(adapter: IOB11NetworkAdapter) {
|
|
||||||
|
registerAdapter<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
|
||||||
this.adapters.set(adapter.name, adapter);
|
this.adapters.set(adapter.name, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerAdapterAndOpen(adapter: IOB11NetworkAdapter) {
|
async registerAdapterAndOpen<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
|
||||||
this.registerAdapter(adapter);
|
this.registerAdapter(adapter);
|
||||||
await adapter.open();
|
await adapter.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
async closeSomeAdapters(adaptersToClose: IOB11NetworkAdapter[]) {
|
async closeSomeAdapters<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
|
||||||
for (const adapter of adaptersToClose) {
|
for (const adapter of adaptersToClose) {
|
||||||
this.adapters.delete(adapter.name);
|
this.adapters.delete(adapter.name);
|
||||||
await adapter.close();
|
await adapter.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async closeSomeAdaterWhenOpen(adaptersToClose: IOB11NetworkAdapter[]) {
|
async closeSomeAdaterWhenOpen<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
|
||||||
for (const adapter of adaptersToClose) {
|
for (const adapter of adaptersToClose) {
|
||||||
this.adapters.delete(adapter.name);
|
this.adapters.delete(adapter.name);
|
||||||
if (adapter.isEnable) {
|
if (adapter.isEnable) {
|
||||||
@@ -85,7 +77,7 @@ export class OB11NetworkManager {
|
|||||||
return this.adapters.get(name);
|
return this.adapters.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter) => boolean) {
|
async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter<NetworkConfigAdapter>) => boolean) {
|
||||||
const adaptersToClose = Array.from(this.adapters.values()).filter(closeFilter);
|
const adaptersToClose = Array.from(this.adapters.values()).filter(closeFilter);
|
||||||
await this.closeSomeAdapters(adaptersToClose);
|
await this.closeSomeAdapters(adaptersToClose);
|
||||||
}
|
}
|
||||||
@@ -104,9 +96,12 @@ export class OB11NetworkManager {
|
|||||||
async readloadSomeAdapters<T>(configMap: Map<string, T>) {
|
async readloadSomeAdapters<T>(configMap: Map<string, T>) {
|
||||||
await Promise.all(Array.from(configMap.entries()).map(([name, config]) => this.readloadAdapter(name, config)));
|
await Promise.all(Array.from(configMap.entries()).map(([name, config]) => this.readloadAdapter(name, config)));
|
||||||
}
|
}
|
||||||
|
async getAllConfig() {
|
||||||
|
return Array.from(this.adapters.values()).map(adapter => adapter.config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from './active-http';
|
export * from './active-http';
|
||||||
export * from './active-websocket';
|
export * from './active-websocket';
|
||||||
export * from './passive-http';
|
export * from './passive-http';
|
||||||
export * from './passive-websocket';
|
export * from './passive-websocket';
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IOB11NetworkAdapter, OB11NetworkReloadType } from './index';
|
import { OB11NetworkReloadType } from './index';
|
||||||
import express, { Express, Request, Response } from 'express';
|
import express, { Express, Request, Response } from 'express';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
@@ -6,20 +6,15 @@ import { OB11Response } from '@/onebot/action/OneBotAction';
|
|||||||
import { ActionMap } from '@/onebot/action';
|
import { ActionMap } from '@/onebot/action';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { HttpServerConfig } from '@/onebot/config/config';
|
import { HttpServerConfig } from '@/onebot/config/config';
|
||||||
|
import { NapCatOneBot11Adapter } from "@/onebot";
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter<HttpServerConfig> {
|
||||||
private app: Express | undefined;
|
private app: Express | undefined;
|
||||||
private server: http.Server | undefined;
|
private server: http.Server | undefined;
|
||||||
isEnable: boolean = false;
|
|
||||||
public config: HttpServerConfig;
|
|
||||||
|
|
||||||
constructor(
|
constructor(name: string, config: HttpServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
|
||||||
public name: string,
|
super(name, config, core, obContext, actions);
|
||||||
config: HttpServerConfig,
|
|
||||||
public core: NapCatCore,
|
|
||||||
public actions: ActionMap,
|
|
||||||
) {
|
|
||||||
this.config = structuredClone(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onEvent() {
|
onEvent() {
|
||||||
@@ -105,7 +100,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
return res.json(hello);
|
return res.json(hello);
|
||||||
}
|
}
|
||||||
const actionName = req.path.split('/')[1];
|
const actionName = req.path.split('/')[1];
|
||||||
const action = this.actions.get(actionName);
|
const action = this.actions.get(actionName as any);
|
||||||
if (action) {
|
if (action) {
|
||||||
try {
|
try {
|
||||||
const result = await action.handle(payload, this.name);
|
const result = await action.handle(payload, this.name);
|
||||||
|
@@ -1,36 +1,30 @@
|
|||||||
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from './index';
|
import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
|
||||||
import urlParse from 'url';
|
import urlParse from 'url';
|
||||||
import { WebSocket, WebSocketServer } from 'ws';
|
import { WebSocket, WebSocketServer } from 'ws';
|
||||||
import { Mutex } from 'async-mutex';
|
import { Mutex } from 'async-mutex';
|
||||||
import { OB11Response } from '@/onebot/action/OneBotAction';
|
import { OB11Response } from '@/onebot/action/OneBotAction';
|
||||||
import { ActionName } from '@/onebot/action/router';
|
import { ActionName } from '@/onebot/action/router';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { LogWrapper } from '@/common/log';
|
|
||||||
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
|
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
|
||||||
import { IncomingMessage } from 'http';
|
import { IncomingMessage } from 'http';
|
||||||
import { ActionMap } from '@/onebot/action';
|
import { ActionMap } from '@/onebot/action';
|
||||||
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
|
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
|
||||||
import { WebsocketServerConfig } from '@/onebot/config/config';
|
import { WebsocketServerConfig } from '@/onebot/config/config';
|
||||||
|
import { NapCatOneBot11Adapter } from "@/onebot";
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
export class OB11PassiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketServerConfig> {
|
||||||
wsServer: WebSocketServer;
|
wsServer: WebSocketServer;
|
||||||
wsClients: WebSocket[] = [];
|
wsClients: WebSocket[] = [];
|
||||||
wsClientsMutex = new Mutex();
|
wsClientsMutex = new Mutex();
|
||||||
isEnable: boolean = false;
|
|
||||||
heartbeatInterval: number = 0;
|
heartbeatInterval: number = 0;
|
||||||
logger: LogWrapper;
|
|
||||||
public config: WebsocketServerConfig;
|
|
||||||
private heartbeatIntervalId: NodeJS.Timeout | null = null;
|
private heartbeatIntervalId: NodeJS.Timeout | null = null;
|
||||||
wsClientWithEvent: WebSocket[] = [];
|
wsClientWithEvent: WebSocket[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public name: string,
|
name: string, config: WebsocketServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
|
||||||
config: WebsocketServerConfig,
|
|
||||||
public core: NapCatCore,
|
|
||||||
public actions: ActionMap,
|
|
||||||
) {
|
) {
|
||||||
this.config = structuredClone(config);
|
super(name, config, core, obContext, actions);
|
||||||
this.logger = core.context.logger;
|
|
||||||
this.wsServer = new WebSocketServer({
|
this.wsServer = new WebSocketServer({
|
||||||
port: this.config.port,
|
port: this.config.port,
|
||||||
host: this.config.host === '0.0.0.0' ? '' : this.config.host,
|
host: this.config.host === '0.0.0.0' ? '' : this.config.host,
|
||||||
@@ -166,7 +160,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleMessage(wsClient: WebSocket, message: any) {
|
private async handleMessage(wsClient: WebSocket, message: any) {
|
||||||
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
|
let receiveData: { action: typeof ActionName[keyof typeof ActionName], params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
|
||||||
let echo = undefined;
|
let echo = undefined;
|
||||||
try {
|
try {
|
||||||
receiveData = JSON.parse(message.toString());
|
receiveData = JSON.parse(message.toString());
|
||||||
@@ -177,7 +171,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 不然类型校验爆炸
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 不然类型校验爆炸
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action as any);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的API ' + receiveData.action);
|
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的API ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的API ' + receiveData.action, 1404, echo), wsClient);
|
this.checkStateAndReply<any>(OB11Response.error('不支持的API ' + receiveData.action, 1404, echo), wsClient);
|
||||||
|
40
src/onebot/network/plugin.ts
Normal file
40
src/onebot/network/plugin.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
|
||||||
|
import { NapCatOneBot11Adapter, OB11Message } from '@/onebot';
|
||||||
|
import { NapCatCore } from '@/core';
|
||||||
|
import { PluginConfig } from '../config/config';
|
||||||
|
import { plugin_onmessage } from '@/plugin';
|
||||||
|
import { ActionMap } from '../action';
|
||||||
|
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
|
||||||
|
|
||||||
|
export class OB11PluginAdapter extends IOB11NetworkAdapter<PluginConfig> {
|
||||||
|
constructor(
|
||||||
|
name: string, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
|
||||||
|
) {
|
||||||
|
const config = {
|
||||||
|
name: name,
|
||||||
|
messagePostFormat: 'array',
|
||||||
|
reportSelfMessage: false,
|
||||||
|
enable: true,
|
||||||
|
debug: false,
|
||||||
|
};
|
||||||
|
super(name, config, core, obContext, actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||||
|
if (event.post_type === 'message') {
|
||||||
|
plugin_onmessage(this.config.name, this.core, this.obContext, event as OB11Message,this.actions).then().catch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
this.isEnable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async close() {
|
||||||
|
this.isEnable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async reload() {
|
||||||
|
return OB11NetworkReloadType.Normal;
|
||||||
|
}
|
||||||
|
}
|
10
src/plugin/index.ts
Normal file
10
src/plugin/index.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { NapCatOneBot11Adapter, OB11Message } from "@/onebot";
|
||||||
|
import { NapCatCore } from "@/core";
|
||||||
|
import { ActionMap } from "@/onebot/action";
|
||||||
|
|
||||||
|
export const plugin_onmessage = async (adapter: string, core: NapCatCore, obCtx: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap) => {
|
||||||
|
if (message.raw_message === 'ping') {
|
||||||
|
const ret = await action.get('send_group_msg')?.handle({ group_id: String(message.group_id), message: 'pong' }, adapter);
|
||||||
|
console.log(ret);
|
||||||
|
}
|
||||||
|
};
|
@@ -175,7 +175,9 @@ async function handleLogin(
|
|||||||
|
|
||||||
loginService.getLoginList().then((res) => {
|
loginService.getLoginList().then((res) => {
|
||||||
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
||||||
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
|
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
|
||||||
|
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
|
||||||
|
WebUiDataRuntime.setQQNewLoginList(list);
|
||||||
});
|
});
|
||||||
|
|
||||||
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
||||||
@@ -285,7 +287,7 @@ export async function NCoreInitShell() {
|
|||||||
|
|
||||||
await initializeEngine(engine, basicInfoWrapper, dataPathGlobal, systemPlatform, systemVersion);
|
await initializeEngine(engine, basicInfoWrapper, dataPathGlobal, systemPlatform, systemVersion);
|
||||||
await initializeLoginService(loginService, basicInfoWrapper, dataPathGlobal, systemVersion, hostname);
|
await initializeLoginService(loginService, basicInfoWrapper, dataPathGlobal, systemVersion, hostname);
|
||||||
|
|
||||||
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
||||||
const cmdOptions = program.opts();
|
const cmdOptions = program.opts();
|
||||||
const quickLoginUin = cmdOptions.qq;
|
const quickLoginUin = cmdOptions.qq;
|
||||||
@@ -354,8 +356,6 @@ export class NapCatShell {
|
|||||||
};
|
};
|
||||||
this.core = new NapCatCore(this.context, selfInfo);
|
this.core = new NapCatCore(this.context, selfInfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
async InitNapCat() {
|
async InitNapCat() {
|
||||||
await this.core.initCore();
|
await this.core.initCore();
|
||||||
|
@@ -18,7 +18,7 @@ export const LoginHandler: RequestHandler = async (req, res) => {
|
|||||||
return sendError(res, 'token is empty');
|
return sendError(res, 'token is empty');
|
||||||
}
|
}
|
||||||
// 检查登录频率
|
// 检查登录频率
|
||||||
if (!(await WebUiDataRuntime.checkLoginRate(WebUiConfigData.loginRate))) {
|
if (!WebUiDataRuntime.checkLoginRate(WebUiConfigData.loginRate)) {
|
||||||
return sendError(res, 'login rate limit');
|
return sendError(res, 'login rate limit');
|
||||||
}
|
}
|
||||||
//验证config.token是否等于token
|
//验证config.token是否等于token
|
||||||
|
@@ -1,15 +1,9 @@
|
|||||||
import { RequestHandler } from 'express';
|
import { RequestHandler } from 'express';
|
||||||
|
import { WebUiDataRuntime } from '@webapi/helper/Data';
|
||||||
|
|
||||||
import { sendSuccess } from '@webapi/utils/response';
|
import { sendSuccess } from '@webapi/utils/response';
|
||||||
|
|
||||||
// TODO: Implement LogFileListHandler
|
export const PackageInfoHandler: RequestHandler = (_, res) => {
|
||||||
export const LogFileListHandler: RequestHandler = async (_, res) => {
|
const data = WebUiDataRuntime.getPackageJson();
|
||||||
const fakeData = {
|
sendSuccess(res, data);
|
||||||
uin: 0,
|
|
||||||
nick: 'NapCat',
|
|
||||||
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=0&s=640',
|
|
||||||
status: 'online',
|
|
||||||
boottime: Date.now(),
|
|
||||||
};
|
|
||||||
sendSuccess(res, fakeData);
|
|
||||||
};
|
};
|
||||||
|
@@ -10,15 +10,15 @@ import { sendError, sendSuccess } from '@webapi/utils/response';
|
|||||||
import { isEmpty } from '@webapi/utils/check';
|
import { isEmpty } from '@webapi/utils/check';
|
||||||
|
|
||||||
// 获取OneBot11配置
|
// 获取OneBot11配置
|
||||||
export const OB11GetConfigHandler: RequestHandler = async (_, res) => {
|
export const OB11GetConfigHandler: RequestHandler = (_, res) => {
|
||||||
// 获取QQ登录状态
|
// 获取QQ登录状态
|
||||||
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
|
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||||
// 如果未登录,返回错误
|
// 如果未登录,返回错误
|
||||||
if (!isLogin) {
|
if (!isLogin) {
|
||||||
return sendError(res, 'Not Login');
|
return sendError(res, 'Not Login');
|
||||||
}
|
}
|
||||||
// 获取登录的QQ号
|
// 获取登录的QQ号
|
||||||
const uin = await WebUiDataRuntime.getQQLoginUin();
|
const uin = WebUiDataRuntime.getQQLoginUin();
|
||||||
// 读取配置文件
|
// 读取配置文件
|
||||||
const configFilePath = resolve(webUiPathWrapper.configPath, `./onebot11_${uin}.json`);
|
const configFilePath = resolve(webUiPathWrapper.configPath, `./onebot11_${uin}.json`);
|
||||||
// 尝试解析配置文件
|
// 尝试解析配置文件
|
||||||
@@ -39,7 +39,7 @@ export const OB11GetConfigHandler: RequestHandler = async (_, res) => {
|
|||||||
// 写入OneBot11配置
|
// 写入OneBot11配置
|
||||||
export const OB11SetConfigHandler: RequestHandler = async (req, res) => {
|
export const OB11SetConfigHandler: RequestHandler = async (req, res) => {
|
||||||
// 获取QQ登录状态
|
// 获取QQ登录状态
|
||||||
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
|
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||||
// 如果未登录,返回错误
|
// 如果未登录,返回错误
|
||||||
if (!isLogin) {
|
if (!isLogin) {
|
||||||
return sendError(res, 'Not Login');
|
return sendError(res, 'Not Login');
|
||||||
|
@@ -7,12 +7,12 @@ import { sendError, sendSuccess } from '@webapi/utils/response';
|
|||||||
// 获取QQ登录二维码
|
// 获取QQ登录二维码
|
||||||
export const QQGetQRcodeHandler: RequestHandler = async (req, res) => {
|
export const QQGetQRcodeHandler: RequestHandler = async (req, res) => {
|
||||||
// 判断是否已经登录
|
// 判断是否已经登录
|
||||||
if (await WebUiDataRuntime.getQQLoginStatus()) {
|
if (WebUiDataRuntime.getQQLoginStatus()) {
|
||||||
// 已经登录
|
// 已经登录
|
||||||
return sendError(res, 'QQ Is Logined');
|
return sendError(res, 'QQ Is Logined');
|
||||||
}
|
}
|
||||||
// 获取二维码
|
// 获取二维码
|
||||||
const qrcodeUrl = await WebUiDataRuntime.getQQLoginQrcodeURL();
|
const qrcodeUrl = WebUiDataRuntime.getQQLoginQrcodeURL();
|
||||||
// 判断二维码是否为空
|
// 判断二维码是否为空
|
||||||
if (isEmpty(qrcodeUrl)) {
|
if (isEmpty(qrcodeUrl)) {
|
||||||
return sendError(res, 'QRCode Get Error');
|
return sendError(res, 'QRCode Get Error');
|
||||||
@@ -27,8 +27,8 @@ export const QQGetQRcodeHandler: RequestHandler = async (req, res) => {
|
|||||||
// 获取QQ登录状态
|
// 获取QQ登录状态
|
||||||
export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => {
|
export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => {
|
||||||
const data = {
|
const data = {
|
||||||
isLogin: await WebUiDataRuntime.getQQLoginStatus(),
|
isLogin: WebUiDataRuntime.getQQLoginStatus(),
|
||||||
qrcodeurl: await WebUiDataRuntime.getQQLoginQrcodeURL(),
|
qrcodeurl: WebUiDataRuntime.getQQLoginQrcodeURL(),
|
||||||
};
|
};
|
||||||
return sendSuccess(res, data);
|
return sendSuccess(res, data);
|
||||||
};
|
};
|
||||||
@@ -38,7 +38,7 @@ export const QQSetQuickLoginHandler: RequestHandler = async (req, res) => {
|
|||||||
// 获取QQ号
|
// 获取QQ号
|
||||||
const { uin } = req.body;
|
const { uin } = req.body;
|
||||||
// 判断是否已经登录
|
// 判断是否已经登录
|
||||||
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
|
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
return sendError(res, 'QQ Is Logined');
|
return sendError(res, 'QQ Is Logined');
|
||||||
}
|
}
|
||||||
@@ -53,12 +53,24 @@ export const QQSetQuickLoginHandler: RequestHandler = async (req, res) => {
|
|||||||
return sendError(res, message);
|
return sendError(res, message);
|
||||||
}
|
}
|
||||||
//本来应该验证 但是http不宜这么搞 建议前端验证
|
//本来应该验证 但是http不宜这么搞 建议前端验证
|
||||||
//isLogin = await WebUiDataRuntime.getQQLoginStatus();
|
//isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||||
return sendSuccess(res, null);
|
return sendSuccess(res, null);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取快速登录列表
|
// 获取快速登录列表
|
||||||
export const QQGetQuickLoginListHandler: RequestHandler = async (_, res) => {
|
export const QQGetQuickLoginListHandler: RequestHandler = async (_, res) => {
|
||||||
const quickLoginList = await WebUiDataRuntime.getQQQuickLoginList();
|
const quickLoginList = WebUiDataRuntime.getQQQuickLoginList();
|
||||||
return sendSuccess(res, quickLoginList);
|
return sendSuccess(res, quickLoginList);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取快速登录列表(新)
|
||||||
|
export const QQGetLoginListNewHandler: RequestHandler = async (_, res) => {
|
||||||
|
const newLoginList = WebUiDataRuntime.getQQNewLoginList();
|
||||||
|
return sendSuccess(res, newLoginList);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取登录的QQ的信息
|
||||||
|
export const getQQLoginInfoHandler: RequestHandler = async (_, res) => {
|
||||||
|
const data = WebUiDataRuntime.getQQLoginInfo();
|
||||||
|
return sendSuccess(res, data);
|
||||||
|
};
|
||||||
|
@@ -1,11 +1,16 @@
|
|||||||
import { OneBotConfig } from '@/onebot/config/config';
|
import type { LoginRuntimeType } from '../types/data';
|
||||||
|
import packageJson from '../../../../package.json';
|
||||||
const LoginRuntime: LoginRuntimeType = {
|
const LoginRuntime: LoginRuntimeType = {
|
||||||
LoginCurrentTime: Date.now(),
|
LoginCurrentTime: Date.now(),
|
||||||
LoginCurrentRate: 0,
|
LoginCurrentRate: 0,
|
||||||
QQLoginStatus: false, //已实现 但太傻了 得去那边注册个回调刷新
|
QQLoginStatus: false, //已实现 但太傻了 得去那边注册个回调刷新
|
||||||
QQQRCodeURL: '',
|
QQQRCodeURL: '',
|
||||||
QQLoginUin: '',
|
QQLoginUin: '',
|
||||||
|
QQLoginInfo: {
|
||||||
|
uid: '',
|
||||||
|
uin: '',
|
||||||
|
nick: '',
|
||||||
|
},
|
||||||
NapCatHelper: {
|
NapCatHelper: {
|
||||||
onOB11ConfigChanged: async () => {
|
onOB11ConfigChanged: async () => {
|
||||||
return;
|
return;
|
||||||
@@ -14,11 +19,13 @@ const LoginRuntime: LoginRuntimeType = {
|
|||||||
return { result: false, message: '' };
|
return { result: false, message: '' };
|
||||||
},
|
},
|
||||||
QQLoginList: [],
|
QQLoginList: [],
|
||||||
|
NewQQLoginList: [],
|
||||||
},
|
},
|
||||||
|
packageJson: packageJson,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WebUiDataRuntime = {
|
export const WebUiDataRuntime = {
|
||||||
checkLoginRate: async function (RateLimit: number): Promise<boolean> {
|
checkLoginRate(RateLimit: number): boolean {
|
||||||
LoginRuntime.LoginCurrentRate++;
|
LoginRuntime.LoginCurrentRate++;
|
||||||
//console.log(RateLimit, LoginRuntime.LoginCurrentRate, Date.now() - LoginRuntime.LoginCurrentTime);
|
//console.log(RateLimit, LoginRuntime.LoginCurrentRate, Date.now() - LoginRuntime.LoginCurrentTime);
|
||||||
if (Date.now() - LoginRuntime.LoginCurrentTime > 1000 * 60) {
|
if (Date.now() - LoginRuntime.LoginCurrentTime > 1000 * 60) {
|
||||||
@@ -29,51 +36,68 @@ export const WebUiDataRuntime = {
|
|||||||
return LoginRuntime.LoginCurrentRate <= RateLimit;
|
return LoginRuntime.LoginCurrentRate <= RateLimit;
|
||||||
},
|
},
|
||||||
|
|
||||||
getQQLoginStatus: async function (): Promise<boolean> {
|
getQQLoginStatus(): LoginRuntimeType['QQLoginStatus'] {
|
||||||
return LoginRuntime.QQLoginStatus;
|
return LoginRuntime.QQLoginStatus;
|
||||||
},
|
},
|
||||||
|
|
||||||
setQQLoginStatus: async function (status: boolean): Promise<void> {
|
setQQLoginStatus(status: LoginRuntimeType['QQLoginStatus']): void {
|
||||||
LoginRuntime.QQLoginStatus = status;
|
LoginRuntime.QQLoginStatus = status;
|
||||||
},
|
},
|
||||||
|
|
||||||
setQQLoginQrcodeURL: async function (url: string): Promise<void> {
|
setQQLoginQrcodeURL(url: LoginRuntimeType['QQQRCodeURL']): void {
|
||||||
LoginRuntime.QQQRCodeURL = url;
|
LoginRuntime.QQQRCodeURL = url;
|
||||||
},
|
},
|
||||||
|
|
||||||
getQQLoginQrcodeURL: async function (): Promise<string> {
|
getQQLoginQrcodeURL(): LoginRuntimeType['QQQRCodeURL'] {
|
||||||
return LoginRuntime.QQQRCodeURL;
|
return LoginRuntime.QQQRCodeURL;
|
||||||
},
|
},
|
||||||
|
|
||||||
setQQLoginUin: async function (uin: string): Promise<void> {
|
setQQLoginInfo(info: LoginRuntimeType['QQLoginInfo']): void {
|
||||||
LoginRuntime.QQLoginUin = uin;
|
LoginRuntime.QQLoginInfo = info;
|
||||||
|
LoginRuntime.QQLoginUin = info.uin.toString();
|
||||||
},
|
},
|
||||||
|
|
||||||
getQQLoginUin: async function (): Promise<string> {
|
getQQLoginInfo(): LoginRuntimeType['QQLoginInfo'] {
|
||||||
|
return LoginRuntime.QQLoginInfo;
|
||||||
|
},
|
||||||
|
|
||||||
|
getQQLoginUin(): LoginRuntimeType['QQLoginUin'] {
|
||||||
return LoginRuntime.QQLoginUin;
|
return LoginRuntime.QQLoginUin;
|
||||||
},
|
},
|
||||||
|
|
||||||
getQQQuickLoginList: async function (): Promise<any[]> {
|
getQQQuickLoginList(): LoginRuntimeType['NapCatHelper']['QQLoginList'] {
|
||||||
return LoginRuntime.NapCatHelper.QQLoginList;
|
return LoginRuntime.NapCatHelper.QQLoginList;
|
||||||
},
|
},
|
||||||
|
|
||||||
setQQQuickLoginList: async function (list: string[]): Promise<void> {
|
setQQQuickLoginList(list: LoginRuntimeType['NapCatHelper']['QQLoginList']): void {
|
||||||
LoginRuntime.NapCatHelper.QQLoginList = list;
|
LoginRuntime.NapCatHelper.QQLoginList = list;
|
||||||
},
|
},
|
||||||
|
|
||||||
setQuickLoginCall(func: (uin: string) => Promise<{ result: boolean; message: string }>): void {
|
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;
|
LoginRuntime.NapCatHelper.onQuickLoginRequested = func;
|
||||||
},
|
},
|
||||||
|
|
||||||
requestQuickLogin: async function (uin: string): Promise<{ result: boolean; message: string }> {
|
requestQuickLogin: function (uin) {
|
||||||
return await LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
|
return LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
|
||||||
},
|
} as LoginRuntimeType['NapCatHelper']['onQuickLoginRequested'],
|
||||||
|
|
||||||
setOnOB11ConfigChanged: async function (func: (ob11: OneBotConfig) => Promise<void>): Promise<void> {
|
setOnOB11ConfigChanged(func: LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged']): void {
|
||||||
LoginRuntime.NapCatHelper.onOB11ConfigChanged = func;
|
LoginRuntime.NapCatHelper.onOB11ConfigChanged = func;
|
||||||
},
|
},
|
||||||
|
|
||||||
setOB11Config: async function (ob11: OneBotConfig): Promise<void> {
|
setOB11Config: function (ob11) {
|
||||||
await LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
|
return LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
|
||||||
|
} as LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged'],
|
||||||
|
|
||||||
|
getPackageJson() {
|
||||||
|
return LoginRuntime.packageJson;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
8
src/webui/src/router/Base.ts
Normal file
8
src/webui/src/router/Base.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Router } from 'express';
|
||||||
|
import { PackageInfoHandler } from '../api/BaseInfo';
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
// router: 获取nc的package.json信息
|
||||||
|
router.get('/PackageInfo', PackageInfoHandler);
|
||||||
|
|
||||||
|
export { router as BaseRouter };
|
@@ -5,16 +5,22 @@ import {
|
|||||||
QQGetQRcodeHandler,
|
QQGetQRcodeHandler,
|
||||||
QQGetQuickLoginListHandler,
|
QQGetQuickLoginListHandler,
|
||||||
QQSetQuickLoginHandler,
|
QQSetQuickLoginHandler,
|
||||||
|
QQGetLoginListNewHandler,
|
||||||
|
getQQLoginInfoHandler,
|
||||||
} from '@webapi/api/QQLogin';
|
} from '@webapi/api/QQLogin';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
// router:获取快速登录列表
|
// router:获取快速登录列表
|
||||||
router.all('/GetQuickLoginList', QQGetQuickLoginListHandler);
|
router.all('/GetQuickLoginList', QQGetQuickLoginListHandler);
|
||||||
|
// router:获取快速登录列表(新)
|
||||||
|
router.all('/GetQuickLoginListNew', QQGetLoginListNewHandler);
|
||||||
// router:检查QQ登录状态
|
// router:检查QQ登录状态
|
||||||
router.post('/CheckLoginStatus', QQCheckLoginStatusHandler);
|
router.post('/CheckLoginStatus', QQCheckLoginStatusHandler);
|
||||||
// router:获取QQ登录二维码
|
// router:获取QQ登录二维码
|
||||||
router.post('/GetQQLoginQrcode', QQGetQRcodeHandler);
|
router.post('/GetQQLoginQrcode', QQGetQRcodeHandler);
|
||||||
// router:设置QQ快速登录
|
// router:设置QQ快速登录
|
||||||
router.post('/SetQuickLogin', QQSetQuickLoginHandler);
|
router.post('/SetQuickLogin', QQSetQuickLoginHandler);
|
||||||
|
// router:获取QQ登录信息
|
||||||
|
router.post('/GetQQLoginInfo', getQQLoginInfoHandler);
|
||||||
|
|
||||||
export { router as QQLoginRouter };
|
export { router as QQLoginRouter };
|
||||||
|
@@ -11,6 +11,7 @@ import { sendSuccess } from '@webapi/utils/response';
|
|||||||
import { QQLoginRouter } from '@webapi/router/QQLogin';
|
import { QQLoginRouter } from '@webapi/router/QQLogin';
|
||||||
import { AuthRouter } from '@webapi/router/auth';
|
import { AuthRouter } from '@webapi/router/auth';
|
||||||
import { LogRouter } from '@webapi/router/Log';
|
import { LogRouter } from '@webapi/router/Log';
|
||||||
|
import { BaseRouter } from '@webapi/router/Base';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
@@ -21,6 +22,8 @@ router.use(auth);
|
|||||||
router.all('/test', (_, res) => {
|
router.all('/test', (_, res) => {
|
||||||
return sendSuccess(res);
|
return sendSuccess(res);
|
||||||
});
|
});
|
||||||
|
// router:基础信息相关路由
|
||||||
|
router.use('/base', BaseRouter);
|
||||||
// router:WebUI登录相关路由
|
// router:WebUI登录相关路由
|
||||||
router.use('/auth', AuthRouter);
|
router.use('/auth', AuthRouter);
|
||||||
// router:QQ登录相关路由
|
// router:QQ登录相关路由
|
||||||
|
5
src/webui/src/types/data.d.ts
vendored
5
src/webui/src/types/data.d.ts
vendored
@@ -1,12 +1,17 @@
|
|||||||
|
import type { LoginListItem, SelfInfo } from '@/core';
|
||||||
|
|
||||||
interface LoginRuntimeType {
|
interface LoginRuntimeType {
|
||||||
LoginCurrentTime: number;
|
LoginCurrentTime: number;
|
||||||
LoginCurrentRate: number;
|
LoginCurrentRate: number;
|
||||||
QQLoginStatus: boolean;
|
QQLoginStatus: boolean;
|
||||||
QQQRCodeURL: string;
|
QQQRCodeURL: string;
|
||||||
QQLoginUin: string;
|
QQLoginUin: string;
|
||||||
|
QQLoginInfo: SelfInfo;
|
||||||
NapCatHelper: {
|
NapCatHelper: {
|
||||||
onQuickLoginRequested: (uin: string) => Promise<{ result: boolean; message: string }>;
|
onQuickLoginRequested: (uin: string) => Promise<{ result: boolean; message: string }>;
|
||||||
onOB11ConfigChanged: (ob11: OneBotConfig) => Promise<void>;
|
onOB11ConfigChanged: (ob11: OneBotConfig) => Promise<void>;
|
||||||
QQLoginList: string[];
|
QQLoginList: string[];
|
||||||
|
NewQQLoginList: LoginListItem[];
|
||||||
};
|
};
|
||||||
|
packageJson: object;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user