提交 b220f2fd 编写于 作者: P peterq

finish: 完成在线聊天室

上级 33c500c0
import {newPeerConnection} from "./realtime/webRtc" import {newPeerConnection} from "./realtime/webRtc"
import RealTime from "./realtime/realtime" import RealTime from "./realtime/realtime"
import Vue from "vue" import Vue from "vue"
import State from "./util/state" import State, {dataTemplate} from "./util/state"
import {registerProxyChannelResolver} from "./lib/vnc/core/RtcWebSocket" import {registerProxyChannelResolver} from "./lib/vnc/core/RtcWebSocket"
import whatJpg from './assets/what.jpeg' import whatJpg from './assets/what.jpeg'
...@@ -54,26 +54,103 @@ $rt.onRemote("host.candidate.ok", data => { ...@@ -54,26 +54,103 @@ $rt.onRemote("host.candidate.ok", data => {
handler.pc.continueWithRemote(candidate) handler.pc.continueWithRemote(candidate)
}) })
function roomHandleUserBroadCast(room, data) {
if (data.event === 'chat') {
room.messages = room.messages.concat([{
id: +new Date,
type: 'chat',
msg: data.payload,
from: data.from
}])
}
}
function roomHandleUserTicketTurn(room, data) {
console.log(data, $state.ticket)
const {order} = data
if ($state.ticket && $state.ticket.order === order) {
$state.ticket.inService = true
let {host, slave} = data
$state.connectVnc = {
host, slave, viewOnly: false,
password: $state.ticket.ticket
}
$event.fire('operate.turn', data)
console.log(data)
}
room.messages = room.messages.concat([{
id: +new Date,
type: 'system',
evt: 'turn',
sessionId: data.sessionId,
ticket: data
}])
}
$rt.on('room.new', room => { $rt.on('room.new', room => {
// 全员群 async function getSessionInfo(ids) {
if (room.name === 'room.all.user') { let newOnes = []
room.onRemote('ticket.turn', data => { ids.forEach(id => {
console.log(data, $state.ticket) if (!$state.userSessionInfo[id]) {
const {order} = data newOnes.push(id)
if ($state.ticket && $state.ticket.order === order) { Vue.set($state.userSessionInfo, id, dataTemplate.deppClone('userSessionInfo'))
$state.ticket.inService = true
let {host, slave} = data
$state.connectVnc = {
host, slave, viewOnly: false,
password: $state.ticket.ticket
}
$event.fire('operate.turn', data)
console.log(data)
} }
}) })
let infoMap = await $rt.call('session.public.info', {sessionIds: newOnes})
for (let id in infoMap) {
$state.userSessionInfo[id] = infoMap[id]
}
}
room.messages = []
room.members = []
room.sendMsg = function (msg) {
room.broadcast('chat', msg)
room.messages = room.messages.concat([{
id: +new Date,
type: 'chat',
msg,
from: $state.userSessionInfo.self.sessionId
}])
}
$rt.call('room.members', {room: room.name})
.then(members => room.members = members)
.then(() => {
getSessionInfo(room.members)
})
room.on('leave', () => {
Vue.delete($state.roomMap, room.name)
})
room.onRemote('room.member.join', sessionId => {
getSessionInfo([sessionId])
room.messages = room.messages.concat([{
id: +new Date,
type: 'system',
evt: 'join',
sessionId
}])
room.members = room.members.concat([sessionId])
})
room.onRemote('room.member.remove', sessionId => {
room.members = room.members.filter(id => id !== sessionId)
room.messages = room.messages.concat([{
id: +new Date,
type: 'system',
evt: 'leave',
sessionId
}])
})
room.onRemote('broadcast.user', data => roomHandleUserBroadCast(room, data))
Vue.set($state.roomMap, room.name, room)
// 全员群
if (room.name === 'room.all.user') {
room.onRemote('ticket.turn', data => roomHandleUserTicketTurn(room, data))
} }
// slave 全员群 // slave 全员群
...@@ -98,6 +175,13 @@ $rt.on('room.new', room => { ...@@ -98,6 +175,13 @@ $rt.on('room.new', room => {
}) })
$rt.onRemote('session.new', async session => {
$state.resetData()
let infoMap = await $rt.call('session.public.info', {sessionIds: [session.id]})
$state.userSessionInfo.self = {...infoMap[session.id], sessionId: session.id}
$state.connected = true
})
class Host { class Host {
/** /**
* @type RTCDataChannel * @type RTCDataChannel
...@@ -315,8 +399,10 @@ async function canStart() { ...@@ -315,8 +399,10 @@ async function canStart() {
var element = new Image() var element = new Image()
Object.defineProperty(element, 'id', { Object.defineProperty(element, 'id', {
get: function () { get: function () {
fuckDebug() setTimeout(() => {
location.reload() fuckDebug()
location.reload()
})
return 0 return 0
} }
}) })
......
<template>
<div style="display: flex; flex-direction: column;">
<h2 style="text-align: center">在线聊天</h2>
<hr>
<div style="display: flex; align-items: center; padding: 10px 20px;">
<img :src="$state.userSessionInfo.self.avatar" style="border-radius: 50%;" alt="avatar" width="50"
height="50"/>
<p> {{$state.userSessionInfo.self.nickname}}</p>
</div>
<hr>
<el-tabs v-model="activeRoom" style="padding: 5px; flex: 1;">
<el-tab-pane v-for="(room, roomName) in $state.roomMap" :key="roomName" :label="getRoomLabel(roomName)"
:name="roomName">
<room :room="room" style="height: 100%"></room>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import room from './room'
export default {
data() {
return {
activeRoom: 'room.all.user'
}
},
computed: {},
components: {
room
},
methods: {
getRoomLabel(name) {
if (name === 'room.all.user') {
return '全员群'
}
return '围观群 ' + name.replace('room.slave.all.user.', '')
}
}
}
</script>
<style>
.el-tabs__content {
flex: 1;
}
.el-tabs {
display: flex;
flex-direction: column;
}
.el-tab-pane {
height: 100%;
}
</style>
<template>
<div style="display: flex; flex-direction: column;">
<el-scrollbar ref="scroll" class="msg-con" style="height: 100%;"
:native="false"
tag="section">
<div v-for="(item) in room.messages" :key="item.id">
<system-msg v-if="item.type === 'system'" :message="item"></system-msg>
<user-msg v-else-if="item.type==='chat'" :message="item"></user-msg>
</div>
</el-scrollbar>
<div style="height: 80px; display: flex;">
<el-input
style="height: 100%"
type="textarea"
placeholder="在此输入消息"
v-model="inputMsg">
</el-input>
<el-button type="primary" @click="clickSend" style="height: 100%; border-radius: 0">
发 送
</el-button>
</div>
</div>
</template>
<script>
import UserMsg from "./user-msg"
import SystemMsg from "./system-msg"
export default {
props: ['room'],
data() {
return {
inputMsg: 'hello world'
}
},
mounted() {
console.log(this.$refs.scroll)
},
computed: {},
methods: {
clickSend() {
if (!this.inputMsg) return
this.room.sendMsg(this.inputMsg)
this.inputMsg = ''
}
},
components: {SystemMsg, UserMsg},
watch: {
async ['room.messages']() {
await this.$nextTick()
let div = this.$refs.scroll.$el.querySelector('.el-scrollbar__wrap')
div.scrollTop = div.scrollHeight
this.$refs.scroll.update()
}
}
}
</script>
<style>
.el-textarea__inner {
height: 100%;
}
.msg-con {
height: calc(100% - 80px);
}
.el-scrollbar__wrap {
overflow-x: hidden !important;
}
</style>
...@@ -3,13 +3,18 @@ ...@@ -3,13 +3,18 @@
<el-header> <el-header>
pan-light 在线体验 pan-light 在线体验
</el-header> </el-header>
<el-container> <el-container class="down-con">
<el-main style="min-width: 800px"> <el-main style="min-width: 800px">
<vnc style="flex: 1;" v-if="vncShow" <vnc style="flex: 1;" v-if="vncShow"
:config="connectVnc"></vnc> :config="connectVnc"></vnc>
<host-list v-else></host-list> <host-list v-else></host-list>
</el-main> </el-main>
<el-aside width="400px">Aside</el-aside> <el-aside width="400px">
<div v-if="!$state.connected" style="height: 100%; display: flex; justify-content: center; align-items: center">
<p>聊天室初始化中...</p>
</div>
<chat-main v-else style="height: 100%"></chat-main>
</el-aside>
</el-container> </el-container>
</el-container> </el-container>
</template> </template>
...@@ -18,6 +23,7 @@ ...@@ -18,6 +23,7 @@
import vnc from './vnc' import vnc from './vnc'
import hostList from './hostList' import hostList from './hostList'
import {$state} from "../app" import {$state} from "../app"
import chatMain from './chat/chat-main'
export default { export default {
data() { data() {
...@@ -43,7 +49,7 @@ ...@@ -43,7 +49,7 @@
watch: { watch: {
}, },
components: {vnc, hostList} components: {vnc, hostList, chatMain}
} }
</script> </script>
...@@ -58,5 +64,8 @@ ...@@ -58,5 +64,8 @@
text-align: center; text-align: center;
line-height: 60px; line-height: 60px;
} }
.down-con {
height: calc(100vh - 60px);
}
</style> </style>
...@@ -31,6 +31,29 @@ class EventEmitter { ...@@ -31,6 +31,29 @@ class EventEmitter {
} }
} }
function ch2Unicdoe(str) {
if (!str) {
return
}
let unicode = ''
for (let i = 0; i < str.length; i++) {
let temp = str.charAt(i)
if (isChinese(temp)) {
unicode += '\\u' + temp.charCodeAt(0).toString(16)
}
else {
unicode += temp
}
}
return unicode
}
// 判断字符是否为汉字,
function isChinese(s) {
return /[\u4e00-\u9fa5]/.test(s)
}
export default class Rpc extends EventEmitter { export default class Rpc extends EventEmitter {
openPromise openPromise
...@@ -127,6 +150,7 @@ export default class Rpc extends EventEmitter { ...@@ -127,6 +150,7 @@ export default class Rpc extends EventEmitter {
if (!(data.type === 'call' && data.method === 'user.ping')) if (!(data.type === 'call' && data.method === 'user.ping'))
console.log('ws ->', data) console.log('ws ->', data)
let str = JSON.stringify(data) let str = JSON.stringify(data)
str = ch2Unicdoe(str)
let send = this._encrypt(str) let send = this._encrypt(str)
this.ws.send(send) this.ws.send(send)
} }
...@@ -181,6 +205,23 @@ export default class Rpc extends EventEmitter { ...@@ -181,6 +205,23 @@ export default class Rpc extends EventEmitter {
return promise return promise
} }
emit(event, payload = {}) {
event = 'user.' + event
this.wsSend({
type: 'event',
event,
payload,
})
}
broadcast(room, event, payload) {
this.emit('broadcast', {
room,
event,
payload
})
}
getRoom(name) { getRoom(name) {
return Room.roomMap[name] return Room.roomMap[name]
} }
...@@ -235,6 +276,9 @@ class Room extends EventEmitter { ...@@ -235,6 +276,9 @@ class Room extends EventEmitter {
super() super()
this.name = name this.name = name
rt.fire('room.new', this) rt.fire('room.new', this)
this.rt = function () {
return rt
}
} }
onRemote(name, cb) { onRemote(name, cb) {
...@@ -244,4 +288,8 @@ class Room extends EventEmitter { ...@@ -244,4 +288,8 @@ class Room extends EventEmitter {
handleMsg(data) { handleMsg(data) {
this.fire('$remote.' + data.event, data.payload) this.fire('$remote.' + data.event, data.payload)
} }
broadcast(event, payload) {
this.rt().broadcast(this.name, event, payload)
}
} }
const dataTemplate = { export const dataTemplate = {
ticket: { ticket: {
order: 1, order: 1,
ticket: '23', ticket: '23',
...@@ -7,21 +7,35 @@ const dataTemplate = { ...@@ -7,21 +7,35 @@ const dataTemplate = {
roomMap: { roomMap: {
'room.user.all': { 'room.user.all': {
name: 'room.user.all', name: 'room.user.all',
members: ['234'] members: [],
messages: [],
} }
}, },
connectVnc: { connectVnc: {
host: '', host: '',
slave: '', slave: '',
viewOnly: true viewOnly: true
},
userSessionInfo: {
_role: 'user',
nickname: '',
avatar: '',
sessionId: ''
},
deppClone(key) {
return JSON.parse(JSON.stringify(this[key]))
} }
} }
function data() { function initialData() {
return { return {
connected: false,
loading: { loading: {
getTicket: false, getTicket: false,
}, },
userSessionInfo: {
self: {...dataTemplate.userSessionInfo},
},
ticket: null, // tpl: ticket ticket: null, // tpl: ticket
roomMap: {}, // tpl roomMap roomMap: {}, // tpl roomMap
timestamp: 0, timestamp: 0,
...@@ -37,12 +51,20 @@ function data() { ...@@ -37,12 +51,20 @@ function data() {
export default { export default {
data() { data() {
return data() return initialData()
}, },
created() { created() {
window.debugObj.$state = this window.debugObj.$state = this
setInterval(() => { setInterval(() => {
this.timestamp++ this.timestamp++
}, 100) }, 100)
},
methods: {
resetData() {
let data = initialData()
for (let k in data) {
this[k] = data[k]
}
}
} }
} }
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
func Init(router iris.Party, conf map[interface{}]interface{}) { func Init(router iris.Party, conf map[interface{}]interface{}) {
// 静态页 // 静态页
router.StaticWeb("/", "../static/noVNC") router.StaticWeb("/", "./static/demo")
hosts := map[string]string{} hosts := map[string]string{}
for _, host := range conf["hosts"].([]interface{}) { for _, host := range conf["hosts"].([]interface{}) {
hosts[host.(map[interface{}]interface{})["name"].(string)] = host.(map[interface{}]interface{})["password"].(string) hosts[host.(map[interface{}]interface{})["name"].(string)] = host.(map[interface{}]interface{})["password"].(string)
......
package nickname
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"sync"
"time"
)
type taskItem struct {
book string
nickname string
images []string
img []byte
}
// 搜索图像
func FetchAndSaveAvatarFromInternet() {
avatarInit()
nicknameChan := make(chan *taskItem)
imageChan := make(chan *taskItem)
resultChan := make(chan *taskItem)
searchGroup := new(sync.WaitGroup)
searchGroup.Add(10)
for i := 0; i < 10; i++ {
go searchImageLoop(nicknameChan, imageChan, searchGroup)
}
faceCheckGroup := new(sync.WaitGroup)
faceCheckGroup.Add(10)
for i := 0; i < 10; i++ {
go faceCheckLoop(imageChan, resultChan, faceCheckGroup)
}
nicknameChan <- &taskItem{
book: "飞狐外传",
nickname: "马春花",
images: []string{},
}
close(nicknameChan)
go func() {
// 处理完成关闭相关通道
searchGroup.Wait()
close(imageChan)
faceCheckGroup.Wait()
close(resultChan)
}()
for itemResult := range resultChan {
handleItemResult(itemResult)
}
log.Println("处理完成")
}
func handleItemResult(item *taskItem) {
log.Println("result", item.nickname)
}
func searchImageLoop(nicknameChan chan *taskItem, imageChan chan *taskItem, wg *sync.WaitGroup) {
go func() {
for item := range nicknameChan {
log.Println("search item", item.nickname)
item.images = searchImage(item.book + " " + item.nickname)
imageChan <- item
}
wg.Done()
}()
return
}
func faceCheckLoop(imageChan chan *taskItem, resultChan chan *taskItem, wg *sync.WaitGroup) {
go func() {
for item := range imageChan {
log.Println("check face", item.nickname, item.images)
for _, img := range item.images {
resp, err := http.Get(img)
if err != nil {
continue
}
bin, err := ioutil.ReadAll(resp.Body)
if err != nil {
continue
}
item.img = bin
checkFace(bin)
break
}
resultChan <- item
}
wg.Done()
}()
return
}
var searchHttpClient http.Client
var faceHttpClient http.Client
func avatarInit() {
jar, _ := cookiejar.New(nil)
jar1, _ := cookiejar.New(nil)
parallel := 20
searchHttpClient = http.Client{
Transport: &http.Transport{
MaxIdleConns: parallel,
MaxConnsPerHost: parallel,
},
CheckRedirect: nil,
Jar: jar,
Timeout: 0,
}
faceHttpClient = searchHttpClient
faceHttpClient.Jar = jar1
req := &http.Request{}
req.URL, _ = url.Parse("http://kan.msxiaobing.com/V3/Portal?task=yanzhi&ftid=")
req.Method = "GET"
req.Header = http.Header{}
req.Header.Set("Referer", "http://kan.msxiaobing.com/V3/Portal?task=yanzhi&ftid=")
req.Header.Set("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Mobile Safari/537.36")
faceHttpClient.Do(req)
}
type gson = map[string]interface{}
func searchImage(keyword string) (result []string) {
req := &http.Request{}
req.URL, _ = url.Parse("https://m.baidu.com/sf/vsearch/image/search/wisesearchresult")
params := map[string]interface{}{
"tn": "wisejsonala",
"ie": "utf-8",
"fromsf": "1",
"word": keyword,
"pn": 0,
"rn": 3,
"gsm": "3c",
"searchtype": "0",
"prefresh": "undefined",
"fromfilter": "0",
}
q := req.URL.Query()
for k, v := range params {
q.Set(k, fmt.Sprint(v))
req.URL.RawQuery = q.Encode()
}
req.Method = "GET"
req.Header = http.Header{}
req.Header.Set("Referer", "https://m.baidu.com/sf/vsearch")
req.Header.Set("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Mobile Safari/537.36")
resp, err := searchHttpClient.Do(req)
if err != nil {
log.Println(err)
return
}
defer resp.Body.Close()
bin, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
return
}
var data gson
err = json.Unmarshal(bin, &data)
if err != nil {
log.Println(err, string(bin))
return
}
linkData := data["linkData"].([]interface{})
for _, item := range linkData {
result = append(result, item.(gson)["objurl"].(string))
}
return
}
func checkFace(img []byte) (result []string) {
link := upImg(img)
formData := url.Values{}
formData.Add("MsgId", fmt.Sprint(time.Now().Unix()*1000))
formData.Add("CreateTime", fmt.Sprint(time.Now().Unix()))
formData.Add("Content[imageUrl]", link)
req, _ := http.NewRequest("POST", "https://kan.msxiaobing.com/Api/ImageAnalyze/Process?service=beauty&tid=", strings.NewReader(formData.Encode()))
req.Header.Set("Referer", "https://kan.msxiaobing.com/ImageGame/Portal?task=beauty&feid=")
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
resp, err := faceHttpClient.Do(req)
if err != nil {
log.Println(err)
return
}
defer resp.Body.Close()
bin, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
return
}
var data gson
err = json.Unmarshal(bin, &data)
if err != nil {
log.Println(err, string(bin))
return
}
log.Println(data, string(bin))
return
}
func upImg(img []byte) (link string) {
str := base64.StdEncoding.EncodeToString(img)
req, _ := http.NewRequest("POST", "https://kan.msxiaobing.com/Api/Image/UploadBase64", strings.NewReader(str))
req.Header.Set("Referer", "https://kan.msxiaobing.com/ImageGame/Portal?task=beauty&feid=")
resp, err := faceHttpClient.Do(req)
if err != nil {
log.Println(err)
return
}
defer resp.Body.Close()
bin, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
return
}
var data gson
err = json.Unmarshal(bin, &data)
if err != nil {
log.Println(err, string(bin))
return
}
return data["Host"].(string) + data["Url"].(string)
}
package nickname package nickname
import ( import (
"fmt"
"math/rand" "math/rand"
"regexp"
"strings" "strings"
"sync"
"time"
) )
var nicknames []string var nicknameMap = map[string][]string{} // 数据格式 {book_name: [person]}
var idx = 0
var doc = ` var doc = `
《飞狐外传》人物(共有112人)  《飞狐外传》人物(共有112人) 
马行空 马春花 徐铮 商宝震 何思豪 阎基 田归农 苗人凤 南仁通 补锅匠 脚夫 车夫 蒋调侯 店伴 钟兆文 钟兆英 钟兆能 南兰 苗若兰 商老太 平四 胡斐 张总管 王剑英 王剑杰 陈禹 古若般 殷仲翔 福康安 赵半山 孙刚峰 吕小妹 钟四嫂 易吉钟小二 钟阿四 胖商人 瘦商人 凤南天 凤七 俞朝奉 蛇皮张 邝宝官 凤一鸣 大汉 孙伏虎 尉迟连 杨宾 中年武师 程灵素同桌后生 袁紫衣 刘鹤真 崔百胜 曹猛 蓝秦 王仲萍 张飞雄 慕容景岳 姜铁山 薛鹊 王铁匠 姜小铁 田青文 张管家 聂钺 上官 褚轰 汪铁鹗 周铁鹤 曾铁鸥 秦耐之 姬晓峰 张九 任通武 相国夫人 蔡威 汤沛 无青子 海兰弼 大智禅师 欧阳公政 西灵道人 文醉翁 周隆 郭玉堂 齐伯涛 陈高波 安提督 宗雄 桑飞虹 倪不大 倪不小 常赫志 常伯志 上官铁生 哈赤大师 心砚 石双英 刘之余 童怀道 李廷豹 石万嗔 木文察 陈家洛 无尘道长 德布 李沅芷 余鱼同 司徒雷 谢不当 黄希节  马行空 马春花 徐铮 商宝震 何思豪 阎基 田归农 苗人凤 南仁通 补锅匠 脚夫 车夫 蒋调侯 店伴 钟兆文 钟兆英 钟兆能 南兰 苗若兰 商老太 平四 胡斐 张总管 王剑英 王剑杰 陈禹 古若般 殷仲翔 福康安 赵半山 孙刚峰 吕小妹 钟四嫂 易吉钟小二 钟阿四 胖商人 瘦商人 凤南天 凤七 俞朝奉 蛇皮张 邝宝官 凤一鸣 大汉 孙伏虎 尉迟连 杨宾 中年武师 程灵素同桌后生 袁紫衣 刘鹤真 崔百胜 曹猛 蓝秦 王仲萍 张飞雄 慕容景岳 姜铁山 薛鹊 王铁匠 姜小铁 田青文 张管家 聂钺 上官 褚轰 汪铁鹗 周铁鹤 曾铁鸥 秦耐之 姬晓峰 张九 任通武 相国夫人 蔡威 汤沛 无青子 海兰弼 大智禅师 欧阳公政 西灵道人 文醉翁 周隆 郭玉堂 齐伯涛 陈高波 安提督 宗雄 桑飞虹 倪不大 倪不小 常赫志 常伯志 上官铁生 哈赤大师 心砚 石双英 刘之余 童怀道 李廷豹 石万嗔 木文察 陈家洛 无尘道长 德布 李沅芷 余鱼同 司徒雷 谢不当 黄希节 
...@@ -38,35 +42,46 @@ var doc = ` ...@@ -38,35 +42,46 @@ var doc = `
《鸳鸯刀》人物(共有15人)  《鸳鸯刀》人物(共有15人) 
任飞燕 刘於义 杨夫人 花剑影 林玉龙 周威信 卓天雄 逍遥子 袁夫人 袁冠南 常长风 盖一鸣 萧半和 萧中慧(杨中慧) 书僮 任飞燕 刘於义 杨夫人 花剑影 林玉龙 周威信 卓天雄 逍遥子 袁夫人 袁冠南 常长风 盖一鸣 萧半和 萧中慧(杨中慧) 书僮
` `
var books = []string{}
func init() { func parseNicknameDoc() {
lns := strings.Split(doc, "\n") bookReg := regexp.MustCompile(`《(.*)》`)
for i, ln := range lns { lns := strings.Split(strings.Trim(doc, "\n"), "\n")
if i%2 == 0 { bookName := "book"
continue for _, ln := range lns {
find := bookReg.FindStringSubmatch(ln)
if len(find) == 2 {
bookName = find[1]
books = append(books, bookName)
} else {
names := strings.Split(strings.Trim(ln, " "), " ")
if old, ok := nicknameMap[bookName]; ok {
nicknameMap[bookName] = append(old, names...)
} else {
nicknameMap[bookName] = names
}
} }
names := strings.Split(ln, " ")
nicknames = append(nicknames, names...)
} }
idx = rand.Intn(len(nicknames))
} }
func Get() string { var l = new(sync.Mutex)
idx++ var bookIdx, nicknameIdx = 0, 0
if idx >= len(nicknames) {
idx = 0 func init() {
} rand.Seed(time.Now().UnixNano())
return nicknames[idx] parseNicknameDoc()
bookIdx = rand.Intn(len(books))
} }
var a = ` func Get() (string, string) {
GET / HTTP/1.1 l.Lock()
Host: sale.haogu.127.0.0.1.xip.io defer l.Unlock()
Connection: keep-alive if nicknameIdx >= len(nicknameMap[books[bookIdx]]) {
Upgrade-Insecure-Requests: 1 nicknameIdx = 0
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36 bookIdx = (bookIdx + 1) % len(books)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 }
Accept-Encoding: gzip, deflate book := books[bookIdx]
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 nickname := nicknameMap[book][nicknameIdx]
Cookie: pigcms_sessionid=ec43cd5c99f9cc21b9d4bebf439b9a16 nicknameIdx++
` return nickname, fmt.Sprintf("/demo/avatar/%s/%s.jpg", book, nickname)
}
...@@ -40,12 +40,13 @@ var hostRpcMap = map[string]realtime.RpcHandler{ ...@@ -40,12 +40,13 @@ var hostRpcMap = map[string]realtime.RpcHandler{
"sessionId": state.session.Id(), "sessionId": state.session.Id(),
} }
manager.lastInServiceOrder = state.order manager.lastInServiceOrder = state.order
server.RoomByName("room.slave.all.user." + slaveName).Join(state.session.Id())
server.RoomByName("room.all.user").Broadcast("ticket.turn", gson{ server.RoomByName("room.all.user").Broadcast("ticket.turn", gson{
"order": state.order, "order": state.order,
"host": host.name, "sessionId": state.session.Id(),
"slave": slaveName, "host": host.name,
"slave": slaveName,
}) })
server.RoomByName("room.slave.all.user." + slaveName).Join(state.session.Id())
slave.userWaitState = state slave.userWaitState = state
slave.state = slaveStateStarting slave.state = slaveStateStarting
return return
......
...@@ -29,6 +29,7 @@ type roleUser struct { ...@@ -29,6 +29,7 @@ type roleUser struct {
session *realtime.Session session *realtime.Session
nickname string // 随机分配花名 nickname string // 随机分配花名
avatar string // 随机分配花名
waitState *waitState waitState *waitState
} }
...@@ -36,6 +37,7 @@ type roleUser struct { ...@@ -36,6 +37,7 @@ type roleUser struct {
func (user *roleUser) publicInfo() gson { func (user *roleUser) publicInfo() gson {
return gson{ return gson{
"nickname": user.nickname, "nickname": user.nickname,
"avatar": user.avatar,
} }
} }
......
...@@ -121,7 +121,7 @@ func onNewSession(ss *realtime.Session) error { ...@@ -121,7 +121,7 @@ func onNewSession(ss *realtime.Session) error {
if role == "user" { if role == "user" {
server.RoomByName("room.all.user").Join(ss.Id()) server.RoomByName("room.all.user").Join(ss.Id())
ss.Data.(*roleUser).nickname = nickname.Get() ss.Data.(*roleUser).nickname, ss.Data.(*roleUser).avatar = nickname.Get()
} }
if role == "host" { if role == "host" {
......
...@@ -95,21 +95,16 @@ var userRpcMap = map[string]realtime.RpcHandler{ ...@@ -95,21 +95,16 @@ var userRpcMap = map[string]realtime.RpcHandler{
server.RoomByName(roomName).Remove(ss.Id()) server.RoomByName(roomName).Remove(ss.Id())
return return
}), }),
"user.room.members": realtime.RpcHandleFunc(func(ss *realtime.Session, data gson) (result interface{}, err error) {
roomName := data["room"].(string)
if server.RoomExist(roomName) {
return server.RoomByName(roomName).Members(), nil
}
return nil, errors.New("room not exist")
}),
"user.session.public.info": sessionPublicInfo, "user.session.public.info": sessionPublicInfo,
} }
var userEventMap = map[string]realtime.EventHandler{ var userEventMap = map[string]realtime.EventHandler{
"user.chat.msg": realtime.EventHandleFunc(func(ss *realtime.Session, data interface{}) {
payload := data.(gson)
room := payload["room"].(string)
msg := payload["msg"]
if ss.InRoom(room) {
server.RoomByName(room).Broadcast("chat.msg.new", gson{
"from": ss.Id(),
"msg": msg,
"room": room,
}, ss.Id())
}
}),
"user.broadcast": roleBroadcast, "user.broadcast": roleBroadcast,
} }
...@@ -83,6 +83,11 @@ func (r *Room) Remove(id SessionId) { ...@@ -83,6 +83,11 @@ func (r *Room) Remove(id SessionId) {
return return
} }
go r.Broadcast("room.member.remove", id) go r.Broadcast("room.member.remove", id)
go func() {
if ss, ok := r.server.SessionById(id); ok {
ss.Emit("room.leave", r.name)
}
}()
if idx == len(r.members)-1 { if idx == len(r.members)-1 {
r.members = r.members[:idx] r.members = r.members[:idx]
return return
...@@ -92,11 +97,6 @@ func (r *Room) Remove(id SessionId) { ...@@ -92,11 +97,6 @@ func (r *Room) Remove(id SessionId) {
return return
} }
r.members = append(r.members[:idx], r.members[idx+1:]...) r.members = append(r.members[:idx], r.members[idx+1:]...)
go func() {
if ss, ok := r.server.SessionById(id); ok {
ss.Emit("room.leave", r.name)
}
}()
} }
func (r *Room) Members() []SessionId { func (r *Room) Members() []SessionId {
......
...@@ -178,6 +178,13 @@ func (s *Server) RoomByName(name string) *Room { ...@@ -178,6 +178,13 @@ func (s *Server) RoomByName(name string) *Room {
return room return room
} }
func (s *Server) RoomExist(name string) bool {
s.roomMapLock.Lock()
defer s.roomMapLock.Unlock()
_, ok := s.roomMap[name]
return ok
}
func (s *Server) handleWsConn(conn *websocket.Conn) { func (s *Server) handleWsConn(conn *websocket.Conn) {
log.Println("new ws conn", conn.RemoteAddr()) log.Println("new ws conn", conn.RemoteAddr())
var err error var err error
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册