From 0d7c17b4869a8418e2861233fad43dd5400a7a78 Mon Sep 17 00:00:00 2001 From: Zhao Zuohong <1040110848@qq.com> Date: Sun, 4 Sep 2022 11:49:56 +0800 Subject: [PATCH] :sparkles: first commit --- .gitignore | 160 +++++++++++++++++++++++++++++++++++++++++++++++ README.md | 56 +++++++++++++++++ main.py | 38 +++++++++++ requirements.txt | 33 ++++++++++ 4 files changed, 287 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 main.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b069eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e9c9a9 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# Bili-Danmu + +将 BiliBili 直播间的弹幕通过 [ServerTap](https://servertap.io/) 转发到 Spigot 服务器中 + +## ServerTap 设置 + +从 [ServerTap 的 GitHub Release](https://github.com/phybros/servertap/releases/tag/v0.3.0) 下载,放到 `plugins` 文件夹中,启动服务器,生成配置。 + +脚本**暂未支持 TLS 认证,仅支持 HTTP + KeyAuth**。在 ServerTap 的配置文件(`plugins/ServerTap/config.yml`)中,修改端口与 key,记下备用。 + +## 运行脚本 + +### 安装依赖 + +建议使用虚拟环境: + +```bash +python3 -m venv env +source env/bin/activate +pip install -r requirements.txt +``` + +### 参数说明 + +#### 使用示例 + +ServerTap 的默认设置是开启 KeyAuth,密钥为 `change_me`,可以直接用以下命令连接,其中 `room_id` 是直播间房间号: + +``` +./main.py --room --key change_me +``` + +如果脚本与 ServerTap 不在同一台机器上,或改变了 ServerTap 的端口号,可以通过以下参数调整: + +| 参数 | 说明 | +| ------ | -------------------------------------------------- | +| --room | 直播房间号,**必须** | +| --host | ServerTap 的主机名,默认为 `127.0.0.1` | +| --port | ServerTap 的端口,默认为 `4567` | +| --key | ServerTap 的认证 Key,如果不设置认证则不需要此参数 | + +脚本自带帮助: + +``` +$ ./main.py -h +usage: main.py [-h] --room ROOM [--host HOST] [--port PORT] [--key KEY] + +将 B 站直播间弹幕通过 ServerTap 转发到 Spigot 服务器 + +optional arguments: + -h, --help show this help message and exit + --room ROOM 直播房间号 + --host HOST ServerTap 的 IP + --port PORT ServerTap 的端口 + --key KEY ServerTap 的认证信息 +``` diff --git a/main.py b/main.py new file mode 100755 index 0000000..a1311fd --- /dev/null +++ b/main.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +import argparse +import asyncio +import httpx +from bilibili_api import live, sync + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="将 B 站直播间弹幕通过 ServerTap 转发到 Spigot 服务器" + ) + parser.add_argument("--room", type=int, required=True, help="直播房间号") + parser.add_argument("--host", type=str, help="ServerTap 的 IP") + parser.add_argument("--port", type=str, help="ServerTap 的端口") + parser.add_argument("--key", type=str, help="ServerTap 的认证信息") + args = parser.parse_args() + + room = live.LiveDanmaku(args.room) + headers = {"key": args.key} if args.key else {} + host = args.host if args.host else "127.0.0.1" + port = args.port if args.port else "4567" + + @room.on("DANMU_MSG") + async def on_danmaku(event): + danmu = event["data"]["info"][1] + user = event["data"]["info"][2][1] + msg = f"[直播间弹幕]<{user}>{danmu}" + async with httpx.AsyncClient() as client: + response = await client.post( + f"http://{host}:{port}/v1/chat/broadcast", + headers=headers, + data={"message": msg}, + ) + if response.status_code != 200: + print(msg) + print(response.text) + + sync(room.connect()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..78a581a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,33 @@ +aiohttp==3.8.1 +aiosignal==1.2.0 +anyio==3.6.1 +async-timeout==4.0.2 +attrs==22.1.0 +beautifulsoup4==4.9.3 +bilibili-api-python==12.1.0 +bilibili-storytree==0.1.1 +Brotli==1.0.9 +certifi==2022.6.15 +charset-normalizer==2.1.1 +colorama==0.4.5 +frozenlist==1.3.1 +h11==0.12.0 +httpcore==0.14.7 +httpx==0.22.0 +idna==3.3 +keyboard==0.13.5 +lxml==4.9.1 +multidict==6.0.2 +nest-asyncio==1.5.5 +Pillow==9.1.1 +pycryptodome==3.15.0 +PyExecJS==1.5.1 +PyYAML==5.4.1 +qrcode==7.3.1 +requests==2.28.1 +rfc3986==1.5.0 +six==1.16.0 +sniffio==1.3.0 +soupsieve==2.3.2.post1 +urllib3==1.26.12 +yarl==1.8.1