melo-sample-websocket-chat-game-server-ts-run 1.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/app/components/nestComponent.ts +103 -0
- package/app/components/testcomponent.ts +22 -0
- package/app/logic/mutemodule/mute.dao.ts +21 -0
- package/app/logic/mutemodule/mute.module.ts +14 -0
- package/app/logic/mutemodule/mute.service.ts +16 -0
- package/app/logic/provider/db.provider.ts +15 -0
- package/app/servers/chat/cron/cronTest.ts +20 -0
- package/app/servers/chat/handler/chatHandler.ts +55 -0
- package/app/servers/chat/remote/anotherName.ts +32 -0
- package/app/servers/chat/remote/chatRemote.ts +96 -0
- package/app/servers/chat/remote/notifyRemote.ts +32 -0
- package/app/servers/chat.module.ts +23 -0
- package/app/servers/connector/handler/entryHandler.ts +69 -0
- package/app/servers/connector.module.ts +11 -0
- package/app/servers/gate/handler/gateHandler.ts +54 -0
- package/app/servers/gate.module.ts +11 -0
- package/app/util/dispatcher.ts +7 -0
- package/app/util/nestutil.ts +25 -0
- package/app/util/routeUtil.ts +15 -0
- package/app.ts +162 -0
- package/ci-test.js +44 -0
- package/config/adminServer.ts +11 -0
- package/config/adminUser.ts +17 -0
- package/config/clientProtos.ts +31 -0
- package/config/crons.ts +45 -0
- package/config/dictionary.ts +6 -0
- package/config/log4js.ts +134 -0
- package/config/log4js.without.logfile.ts +30 -0
- package/config/master.ts +18 -0
- package/config/serverProtos.ts +30 -0
- package/config/servers.ts +65 -0
- package/dist/app/components/nestComponent.js +91 -0
- package/dist/app/components/testcomponent.js +20 -0
- package/dist/app/logic/mutemodule/mute.dao.js +36 -0
- package/dist/app/logic/mutemodule/mute.module.js +26 -0
- package/dist/app/logic/mutemodule/mute.service.js +28 -0
- package/dist/app/logic/provider/db.provider.js +16 -0
- package/dist/app/servers/chat/cron/cronTest.js +34 -0
- package/dist/app/servers/chat/handler/chatHandler.js +68 -0
- package/dist/app/servers/chat/remote/anotherName.js +35 -0
- package/dist/app/servers/chat/remote/chatRemote.js +93 -0
- package/dist/app/servers/chat/remote/notifyRemote.js +35 -0
- package/dist/app/servers/chat.module.js +32 -0
- package/dist/app/servers/connector/handler/entryHandler.js +78 -0
- package/dist/app/servers/connector.module.js +24 -0
- package/dist/app/servers/gate/handler/gateHandler.js +69 -0
- package/dist/app/servers/gate.module.js +24 -0
- package/dist/app/util/dispatcher.js +10 -0
- package/dist/app/util/nestutil.js +28 -0
- package/dist/app/util/routeUtil.js +15 -0
- package/dist/app.js +134 -0
- package/dist/config/adminServer.js +12 -0
- package/dist/config/adminUser.js +18 -0
- package/dist/config/clientProtos.js +32 -0
- package/dist/config/crons.js +43 -0
- package/dist/config/dictionary.js +7 -0
- package/dist/config/log4js.js +132 -0
- package/dist/config/log4js.without.logfile.js +30 -0
- package/dist/config/master.js +18 -0
- package/dist/config/serverProtos.js +31 -0
- package/dist/config/servers.js +66 -0
- package/dist/preload.js +41 -0
- package/package.json +36 -0
- package/preload.ts +40 -0
- package/robot/robot.ts +97 -0
- package/tsconfig.json +37 -0
- package/tsrun.js +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 node-melo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { NestFactory } from "@nestjs/core";
|
|
2
|
+
import { Application, IComponent, manualReloadCrons, manualReloadHandlers, manualReloadRemoters } from "@bigtyphoon/melo";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export class NestComponent implements IComponent {
|
|
10
|
+
name = "NestComponent";
|
|
11
|
+
app: Application;
|
|
12
|
+
|
|
13
|
+
constructor(app: Application) {
|
|
14
|
+
this.app = app;
|
|
15
|
+
this.app.set(this.name, this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 组件开始
|
|
20
|
+
*/
|
|
21
|
+
start(cb) {
|
|
22
|
+
cb();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
beforeStart(cb) {
|
|
26
|
+
this.bootstrap().then(async result => {
|
|
27
|
+
this.app.set('nestjs', result);
|
|
28
|
+
cb();
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 组件结束
|
|
35
|
+
* @param cb
|
|
36
|
+
*/
|
|
37
|
+
afterStart(cb) {
|
|
38
|
+
process.nextTick(cb);
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 热更新. 只是示例 需要根据自己的逻辑处理自己的逻辑
|
|
43
|
+
public async hotUpdate() {
|
|
44
|
+
if (this.app.getServerType() == 'master') {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// 这里放热更新代码
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// 清除自己逻辑相关的缓存
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
// 生成新的nestapp
|
|
54
|
+
await new Promise((resolve) => {
|
|
55
|
+
this.beforeStart(() => {
|
|
56
|
+
resolve(null)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 热更新框架
|
|
61
|
+
console.log(this.app.getServerId(), 'logic hot update handler')
|
|
62
|
+
manualReloadHandlers(this.app)
|
|
63
|
+
console.log(this.app.getServerId(), 'logic hot update remoter')
|
|
64
|
+
manualReloadRemoters(this.app)
|
|
65
|
+
// manualReloadProxies(this.app)
|
|
66
|
+
console.log(this.app.getServerId(), 'logic hot update crons')
|
|
67
|
+
manualReloadCrons(this.app)
|
|
68
|
+
console.log(this.app.getServerId(), 'logic hot update finished')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private async bootstrap() {
|
|
72
|
+
const servertype = this.app.getServerType();
|
|
73
|
+
let moduleLocal: any = null;
|
|
74
|
+
console.log("bootstrap servertype")
|
|
75
|
+
switch (servertype) {
|
|
76
|
+
case 'connector': {
|
|
77
|
+
moduleLocal = require('../servers/connector.module').ConnectorServerModule;
|
|
78
|
+
console.log('nestApp init: connector');
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case 'chat': {
|
|
82
|
+
moduleLocal = require('../servers/chat.module').ChatServerModule;
|
|
83
|
+
console.log('nestApp init: chat');
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case 'gate': {
|
|
87
|
+
moduleLocal = require('../servers/gate.module').GateServerModule;
|
|
88
|
+
console.log('nestApp init: gate');
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
default:
|
|
92
|
+
console.warn(' unknow melo server type . no nestModule::', servertype);
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
console.log('servertype:', servertype, 'before create nestApp');
|
|
96
|
+
const nestApp = await NestFactory.createApplicationContext(moduleLocal);
|
|
97
|
+
console.log('servertype:', servertype, 'create nest end');
|
|
98
|
+
await nestApp.init();
|
|
99
|
+
console.log('servertype:', servertype, 'init nest end');
|
|
100
|
+
// 没有listen ,因为只是用nestjs的依赖注入
|
|
101
|
+
return nestApp;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Application, IComponent } from "@bigtyphoon/melo";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export class TestComponent implements IComponent {
|
|
5
|
+
name = "TestComponent";
|
|
6
|
+
app: Application;
|
|
7
|
+
|
|
8
|
+
constructor(app: Application) {
|
|
9
|
+
this.app = app;
|
|
10
|
+
this.app.set(this.name, this)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
start(cb: () => void) {
|
|
14
|
+
console.log("TestComponent start", this.app.getServerId())
|
|
15
|
+
cb()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
stop(force: boolean, cb: () => void) {
|
|
19
|
+
console.log("TestComponent stop", force, this.app.getServerId())
|
|
20
|
+
cb()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class MuteDao {
|
|
6
|
+
constructor(
|
|
7
|
+
@Inject("mydatabase")
|
|
8
|
+
private readonly dbConnection: any
|
|
9
|
+
) {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async checkUidMuted(uid: string) {
|
|
14
|
+
console.log("check user has been muted:", uid);
|
|
15
|
+
this.dbConnection.hget()
|
|
16
|
+
if (uid == "abc") {
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Module } from "@nestjs/common";
|
|
2
|
+
import { meloAppProvider } from "../../util/nestutil";
|
|
3
|
+
import { databaseProvider } from "../provider/db.provider";
|
|
4
|
+
import { MuteDao } from "./mute.dao";
|
|
5
|
+
import { MuteService } from "./mute.service";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@Module({
|
|
9
|
+
imports: [],
|
|
10
|
+
providers: [meloAppProvider, databaseProvider, MuteDao, MuteService,],
|
|
11
|
+
// 因为外部要用 需要需要导出
|
|
12
|
+
exports: [MuteService],
|
|
13
|
+
})
|
|
14
|
+
export class MuteModule { }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { MuteDao } from "./mute.dao";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@Injectable()
|
|
6
|
+
export class MuteService {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly muteDao: MuteDao,
|
|
9
|
+
) {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async checkUidMuted(uid: string) {
|
|
14
|
+
return this.muteDao.checkUidMuted(uid)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
// more examples
|
|
3
|
+
// https://docs.nestjs.com/fundamentals/custom-providers
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const databaseProvider = {
|
|
7
|
+
provide: "mydatabase",
|
|
8
|
+
useFactory: async () => {
|
|
9
|
+
// create redis,mongodb,mysql etc.
|
|
10
|
+
return {
|
|
11
|
+
hget: () => { console.log("mydatabase hget") },
|
|
12
|
+
hset: () => { console.log("mydatabase hset") },
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { Application } from "@bigtyphoon/melo";
|
|
3
|
+
import { getNestClass } from "../../../util/nestutil";
|
|
4
|
+
import { ChatServerModule } from "../../chat.module";
|
|
5
|
+
|
|
6
|
+
let cronInstance: CronTest
|
|
7
|
+
|
|
8
|
+
export default function (app) {
|
|
9
|
+
return getNestClass(app, CronTest, ChatServerModule)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Injectable()
|
|
13
|
+
export class CronTest {
|
|
14
|
+
constructor(app: Application) {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public async onlineCron() {
|
|
18
|
+
console.log("online cron", Date.now())
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Application, BackendSession } from '@bigtyphoon/melo';
|
|
2
|
+
import { Injectable } from '@nestjs/common';
|
|
3
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
4
|
+
import { MuteService } from '../../../logic/mutemodule/mute.service';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export default function (app: Application) {
|
|
8
|
+
return getNestClass(app, ChatHandler)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class ChatHandler {
|
|
13
|
+
constructor(
|
|
14
|
+
private app: Application,
|
|
15
|
+
private readonly muteService: MuteService,
|
|
16
|
+
) {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Send messages to users
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} msg message from client
|
|
23
|
+
* @param {Object} session
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
async send(msg: { content: string, target: string }, session: BackendSession) {
|
|
27
|
+
let rid = session.get('rid');
|
|
28
|
+
let username = session.uid.split('*')[0];
|
|
29
|
+
if (this.muteService.checkUidMuted(username)) {
|
|
30
|
+
console.log("user has been muted", username, " chage msg");
|
|
31
|
+
msg.content = "##@ user has been muted## - " + msg.content
|
|
32
|
+
}
|
|
33
|
+
let channelService = this.app.get('channelService');
|
|
34
|
+
let param = {
|
|
35
|
+
msg: msg.content,
|
|
36
|
+
from: username,
|
|
37
|
+
target: msg.target
|
|
38
|
+
};
|
|
39
|
+
let channel = channelService.getChannel(rid, false);
|
|
40
|
+
|
|
41
|
+
// the target is all users
|
|
42
|
+
if (msg.target === '*') {
|
|
43
|
+
channel.pushMessage('onChat', param);
|
|
44
|
+
}
|
|
45
|
+
// the target is specific user
|
|
46
|
+
else {
|
|
47
|
+
let tuid = msg.target + '*' + rid;
|
|
48
|
+
let tsid = channel.getMember(tuid)['sid'];
|
|
49
|
+
channelService.pushMessageByUids('onChat', param, [{
|
|
50
|
+
uid: tuid,
|
|
51
|
+
sid: tsid
|
|
52
|
+
}]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Application, ChannelService, FrontendSession, RemoterClass } from '@bigtyphoon/melo';
|
|
2
|
+
import { Injectable } from '@nestjs/common';
|
|
3
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
4
|
+
|
|
5
|
+
export default function (app: Application) {
|
|
6
|
+
return getNestClass(app, AnotherName);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// UserRpc的命名空间自动合并
|
|
10
|
+
declare global {
|
|
11
|
+
interface MergeChatRemoter {
|
|
12
|
+
anotherName: RemoterClass<null, AnotherName>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UserRpc {
|
|
16
|
+
chat: MergeChatRemoter
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Injectable()
|
|
21
|
+
export class AnotherName {
|
|
22
|
+
|
|
23
|
+
constructor(private app: Application) {
|
|
24
|
+
this.app = app;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public async zzzMethod(uid: string, sid: string, name: string) {
|
|
29
|
+
console.log("~~~~ zzzMethod ", uid, sid, name);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { Application, ChannelService, FrontendSession, RemoterClass } from '@bigtyphoon/melo';
|
|
3
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
4
|
+
|
|
5
|
+
export default function (app: Application) {
|
|
6
|
+
return getNestClass(app, ChatRemote);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// UserRpc的命名空间自动合并
|
|
11
|
+
declare global {
|
|
12
|
+
interface MergeChatRemoter {
|
|
13
|
+
chatRemote: RemoterClass<FrontendSession, ChatRemote>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface UserRpc {
|
|
17
|
+
chat: MergeChatRemoter
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Injectable()
|
|
22
|
+
export class ChatRemote {
|
|
23
|
+
|
|
24
|
+
constructor(private app: Application) {
|
|
25
|
+
this.app = app;
|
|
26
|
+
this.channelService = app.get('channelService');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private channelService: ChannelService;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Add user into chat channel.
|
|
33
|
+
*
|
|
34
|
+
* @param {String} uid unique id for user
|
|
35
|
+
* @param {String} sid server id
|
|
36
|
+
* @param {String} name channel name
|
|
37
|
+
* @param {boolean} flag channel parameter
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
public async add(uid: string, sid: string, name: string, flag: boolean) {
|
|
41
|
+
let channel = this.channelService.getChannel(name, flag);
|
|
42
|
+
let username = uid.split('*')[0];
|
|
43
|
+
let param = {
|
|
44
|
+
user: username
|
|
45
|
+
};
|
|
46
|
+
channel.pushMessage('onAdd', param);
|
|
47
|
+
|
|
48
|
+
if (!!channel) {
|
|
49
|
+
channel.add(uid, sid);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.get(name, flag);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get user from chat channel.
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} opts parameters for request
|
|
59
|
+
* @param {String} name channel name
|
|
60
|
+
* @param {boolean} flag channel parameter
|
|
61
|
+
* @return {Array} users uids in channel
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
private get(name: string, flag: boolean) {
|
|
65
|
+
let users: string[] = [];
|
|
66
|
+
let channel = this.channelService.getChannel(name, flag);
|
|
67
|
+
if (!!channel) {
|
|
68
|
+
users = channel.getMembers();
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i < users.length; i++) {
|
|
71
|
+
users[i] = users[i].split('*')[0];
|
|
72
|
+
}
|
|
73
|
+
return users;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Kick user out chat channel.
|
|
78
|
+
*
|
|
79
|
+
* @param {String} uid unique id for user
|
|
80
|
+
* @param {String} sid server id
|
|
81
|
+
* @param {String} name channel name
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
public async kick(uid: string, sid: string, name: string) {
|
|
85
|
+
let channel = this.channelService.getChannel(name, false);
|
|
86
|
+
// leave channel
|
|
87
|
+
if (!!channel) {
|
|
88
|
+
channel.leave(uid, sid);
|
|
89
|
+
}
|
|
90
|
+
let username = uid.split('*')[0];
|
|
91
|
+
let param = {
|
|
92
|
+
user: username
|
|
93
|
+
};
|
|
94
|
+
channel.pushMessage('onLeave', param);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { Application, ChannelService, FrontendSession, RemoterClass } from '@bigtyphoon/melo';
|
|
3
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
4
|
+
|
|
5
|
+
export default function (app: Application) {
|
|
6
|
+
return getNestClass(app, NotifyRemoter);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// UserRpc的命名空间自动合并
|
|
10
|
+
declare global {
|
|
11
|
+
interface MergeChatRemoter {
|
|
12
|
+
notifyRemote: RemoterClass<FrontendSession, NotifyRemoter>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UserRpc {
|
|
16
|
+
chat: MergeChatRemoter
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Injectable()
|
|
21
|
+
export class NotifyRemoter {
|
|
22
|
+
|
|
23
|
+
constructor(private app: Application) {
|
|
24
|
+
this.app = app;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public async notifyMethod(uid: string, sid: string, name: string) {
|
|
29
|
+
console.log("notifyMethod@@!!!~~", uid, sid, name)
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { MuteModule } from '../logic/mutemodule/mute.module';
|
|
3
|
+
import { meloAppProvider } from '../util/nestutil';
|
|
4
|
+
import { CronTest } from './chat/cron/cronTest';
|
|
5
|
+
import { ChatHandler } from './chat/handler/chatHandler';
|
|
6
|
+
import { AnotherName } from './chat/remote/anotherName';
|
|
7
|
+
import { ChatRemote } from './chat/remote/chatRemote';
|
|
8
|
+
import { NotifyRemoter } from './chat/remote/notifyRemote';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// 数据库 provider
|
|
12
|
+
// https://docs.nestjs.com/fundamentals/custom-providers#export-custom-provider
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@Module({
|
|
17
|
+
imports: [MuteModule],
|
|
18
|
+
controllers: [],
|
|
19
|
+
providers: [meloAppProvider, ChatHandler, AnotherName, ChatRemote, NotifyRemoter, CronTest],
|
|
20
|
+
// 因为外部要用 需要需要导出
|
|
21
|
+
exports: [ChatHandler, AnotherName, ChatRemote, NotifyRemoter, CronTest],
|
|
22
|
+
})
|
|
23
|
+
export class ChatServerModule { }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { Application } from '@bigtyphoon/melo';
|
|
3
|
+
import { FrontendSession } from '@bigtyphoon/melo';
|
|
4
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
5
|
+
|
|
6
|
+
export default function (app: Application) {
|
|
7
|
+
return getNestClass(app, EntryHandler);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class EntryHandler {
|
|
12
|
+
constructor(private app: Application) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* New client entry chat server.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} msg request message
|
|
20
|
+
* @param {Object} session current session object
|
|
21
|
+
*/
|
|
22
|
+
async enter(msg: { rid: string, username: string }, session: FrontendSession) {
|
|
23
|
+
let self = this;
|
|
24
|
+
let rid = msg.rid;
|
|
25
|
+
let uid = msg.username + '*' + rid;
|
|
26
|
+
let sessionService = self.app.get('sessionService');
|
|
27
|
+
|
|
28
|
+
// duplicate log in
|
|
29
|
+
if (!!sessionService.getByUid(uid)) {
|
|
30
|
+
return {
|
|
31
|
+
code: 500,
|
|
32
|
+
error: true
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await session.abind(uid);
|
|
37
|
+
session.set('rid', rid);
|
|
38
|
+
session.push('rid', function (err) {
|
|
39
|
+
if (err) {
|
|
40
|
+
console.error('set rid for session service failed! error is : %j', err.stack);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
session.on('closed', this.onUserLeave.bind(this));
|
|
44
|
+
|
|
45
|
+
// put user into channel
|
|
46
|
+
let users = await self.app.rpc.chat.chatRemote.add.route(session)(uid, self.app.get('serverId'), rid, true);
|
|
47
|
+
|
|
48
|
+
// test remoter
|
|
49
|
+
self.app.rpc.chat.notifyRemote.notifyMethod.to("chat-server-1")('11', '22', '33')
|
|
50
|
+
self.app.rpc.chat.anotherName.zzzMethod.to(null)('aa', 'bb', 'cc')
|
|
51
|
+
return {
|
|
52
|
+
users: users
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* User log out handler
|
|
58
|
+
*
|
|
59
|
+
* @param {Object} app current application
|
|
60
|
+
* @param {Object} session current session object
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
onUserLeave(session: FrontendSession) {
|
|
64
|
+
if (!session || !session.uid) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.app.rpc.chat.chatRemote.kick.route(session, true)(session.uid, this.app.get('serverId'), session.get('rid'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { meloAppProvider } from '../util/nestutil';
|
|
3
|
+
import { EntryHandler } from './connector/handler/entryHandler';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
imports: [],
|
|
7
|
+
controllers: [],
|
|
8
|
+
providers: [meloAppProvider, EntryHandler],
|
|
9
|
+
exports: [EntryHandler],
|
|
10
|
+
})
|
|
11
|
+
export class ConnectorServerModule { }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { dispatch } from '../../../util/dispatcher';
|
|
2
|
+
import {Application, BackendSession, FrontendSession} from '@bigtyphoon/melo';
|
|
3
|
+
import { Injectable } from '@nestjs/common';
|
|
4
|
+
import { getNestClass } from '../../../util/nestutil';
|
|
5
|
+
|
|
6
|
+
export default function (app: Application) {
|
|
7
|
+
return getNestClass(app, GateHandler);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class GateHandler {
|
|
12
|
+
constructor(private app: Application) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Gate handler that dispatch user to connectors.
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} msg message from client
|
|
19
|
+
* @param {Object} session
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
async queryEntry(msg: { uid: string }, session: BackendSession) {
|
|
23
|
+
let uid = msg.uid;
|
|
24
|
+
if (!uid) {
|
|
25
|
+
return {
|
|
26
|
+
code: 500
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// get all connectors
|
|
30
|
+
let connectors = this.app.getServersByType('connector');
|
|
31
|
+
if (!connectors || connectors.length === 0) {
|
|
32
|
+
return {
|
|
33
|
+
code: 500
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// select connector
|
|
37
|
+
let res = dispatch(uid, connectors);
|
|
38
|
+
return {
|
|
39
|
+
code: 200,
|
|
40
|
+
host: res.host,
|
|
41
|
+
port: res.clientPort
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* protobuftest include obj and map
|
|
47
|
+
* @param msg
|
|
48
|
+
* @param session
|
|
49
|
+
*/
|
|
50
|
+
async protobufTest(msg: { username: string, obj:{[key: string]: {a: string, b: number, c: boolean}},map:Map<string, {d: string, e: number, f: boolean}> }, session: FrontendSession){
|
|
51
|
+
console.log(msg);
|
|
52
|
+
return msg;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { meloAppProvider } from '../util/nestutil';
|
|
3
|
+
import { GateHandler } from './gate/handler/gateHandler';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
imports: [],
|
|
7
|
+
controllers: [],
|
|
8
|
+
providers: [meloAppProvider, GateHandler],
|
|
9
|
+
exports: [GateHandler],
|
|
10
|
+
})
|
|
11
|
+
export class GateServerModule { }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { INestApplicationContext } from "@nestjs/common";
|
|
2
|
+
import { Application, melo } from "@bigtyphoon/melo";
|
|
3
|
+
|
|
4
|
+
export function getNestClass(app: Application, classz: any, module?: any) {
|
|
5
|
+
let root: INestApplicationContext = app.get('nestjs');
|
|
6
|
+
if (module) {
|
|
7
|
+
root = root.select(module);
|
|
8
|
+
}
|
|
9
|
+
if (!root) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
let cls = root.get(classz);
|
|
14
|
+
return cls;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
// 给RPC用来读取 方法名用的
|
|
17
|
+
return classz.prototype;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// melo 需要先初始化
|
|
22
|
+
export const meloAppProvider = {
|
|
23
|
+
provide: Application,
|
|
24
|
+
useValue: melo.app,
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import { dispatch} from './dispatcher';
|
|
3
|
+
import { Session, Application } from '@bigtyphoon/melo';
|
|
4
|
+
|
|
5
|
+
export function chat(session: Session, msg: any, app: Application, cb: (err: Error , serverId ?: string) => void) {
|
|
6
|
+
let chatServers = app.getServersByType('chat');
|
|
7
|
+
|
|
8
|
+
if(!chatServers || chatServers.length === 0) {
|
|
9
|
+
cb(new Error('can not find chat servers.'));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let res = dispatch(session.get('rid'), chatServers);
|
|
14
|
+
cb(null, res.id);
|
|
15
|
+
}
|