From e72af2c4f7c277923d789e45c76499e9dd7286e8 Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 22 May 2019 01:11:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E5=AD=97=E6=B6=88?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 3 + blivedm | 1 + chat.py | 92 +++++ frontend/src/components/Room.vue | 491 +++++++++++++++++++++++- frontend/src/components/TextMessage.vue | 24 ++ main.py | 5 +- 6 files changed, 613 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 160000 blivedm create mode 100644 chat.py create mode 100644 frontend/src/components/TextMessage.vue diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5cc0821 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "blivedm"] + path = blivedm + url = https://github.com/xfgryujk/blivedm.git diff --git a/blivedm b/blivedm new file mode 160000 index 0000000..f755468 --- /dev/null +++ b/blivedm @@ -0,0 +1 @@ +Subproject commit f755468908586d39a3325e9f1b0eced42a37ecc2 diff --git a/chat.py b/chat.py new file mode 100644 index 0000000..ca1d964 --- /dev/null +++ b/chat.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +import enum +import json +from typing import * + +import tornado.websocket + +import blivedm.blivedm as blivedm + + +class Command(enum.IntEnum): + JOIN_ROOM = 0 + ADD_TEXT = 1 + ADD_GIFT = 2 + ADD_VIP = 3 + + +class Room(blivedm.BLiveClient): + def __init__(self, room_id): + super().__init__(room_id) + self.future = None + self.clients: List['ChatHandler'] = [] + + def start(self): + self.future = self.run() + + def stop(self): + if self.future is not None: + self.future.cancel() + + def send_message(self, cmd, data): + body = json.dumps({'cmd': cmd, 'data': data}) + for client in self.clients: + client.write_message(body) + + async def _on_get_danmaku(self, content, user_name): + # TODO + data = { + 'content': content, + 'authorName': user_name + } + self.send_message(Command.ADD_TEXT, data) + + +class RoomManager: + def __init__(self): + self._rooms: Dict[int, Room] = {} + + def add_client(self, room_id, client): + if room_id in self._rooms: + room = self._rooms[room_id] + else: + room = Room(room_id) + self._rooms[room_id] = room + room.start() + room.clients.append(client) + + def del_client(self, room_id, client: 'ChatHandler'): + if room_id not in self._rooms: + return + room = self._rooms[room_id] + room.clients.remove(client) + if not room.clients: + room.stop() + del self._rooms[room_id] + + +room_manager = RoomManager() + + +# noinspection PyAbstractClass +class ChatHandler(tornado.websocket.WebSocketHandler): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.room_id = None + + def on_message(self, message): + if self.room_id is not None: + return + body = json.loads(message) + if body['cmd'] == Command.JOIN_ROOM: + room_id = body['data']['roomId'] + room_manager.add_client(room_id, self) + + def on_close(self): + if self.room_id is not None: + room_manager.del_client(self.room_id, self) + + # 测试用 + def check_origin(self, origin): + return True diff --git a/frontend/src/components/Room.vue b/frontend/src/components/Room.vue index a2084fe..683e6a6 100644 --- a/frontend/src/components/Room.vue +++ b/frontend/src/components/Room.vue @@ -1,9 +1,496 @@ + + diff --git a/frontend/src/components/TextMessage.vue b/frontend/src/components/TextMessage.vue new file mode 100644 index 0000000..a65c5e7 --- /dev/null +++ b/frontend/src/components/TextMessage.vue @@ -0,0 +1,24 @@ + + + diff --git a/main.py b/main.py index 8201a62..b5b0c54 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,8 @@ import os import tornado.ioloop import tornado.web +import chat + WEB_ROOT = os.path.join(os.path.dirname(__file__), 'frontend', 'dist') @@ -17,10 +19,11 @@ class MainHandler(tornado.web.StaticFileHandler): def main(): app = tornado.web.Application([ + (r'/chat', chat.ChatHandler), (r'/((css|img|js)/.*)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}), (r'/(favicon\.ico)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}), (r'/.*', MainHandler, {'path': WEB_ROOT}) - ]) + ], websocket_ping_interval=30) app.listen(80, '127.0.0.1') tornado.ioloop.IOLoop.current().start()