Compare commits
362 Commits
v0.1.2-alp
...
master
Author | SHA1 | Date | |
---|---|---|---|
3d796ce447 | |||
a0fa46355b | |||
41afd11036 | |||
58ef92792f | |||
db6e0be776 | |||
95c984573f | |||
5840b75b24 | |||
ce701816b9 | |||
d83761afc0 | |||
798af607bb | |||
3096df86b2 | |||
0505aeaace | |||
551a8b1f18 | |||
e646085f0b | |||
b8d76f6273 | |||
29d23a38d2 | |||
bf2b8956ef | |||
f14860703f | |||
8d98918e39 | |||
9198413cd9 | |||
04fb6e956f | |||
|
8ed3e71539 | ||
1feed57b4e | |||
b1f45ee90d | |||
2facc798cd | |||
1e24129ee7 | |||
0723817bc8 | |||
d882b03e12 | |||
8a810d1869 | |||
3e49fa59bb | |||
f4d65e9595 | |||
d36e7e2c5c | |||
c83c984509 | |||
821244a0c5 | |||
11a73f1aca | |||
734a7204f8 | |||
27f4d25591 | |||
8bbb74eae9 | |||
8fbe139ba0 | |||
|
81dad07fd5 | ||
|
30a91a38f9 | ||
0b4068b9e9 | |||
302b4d4596 | |||
d64639af20 | |||
9e1b725c0c | |||
ecdcde9230 | |||
977cb9877f | |||
6b1a4a7b0a | |||
2281f872bf | |||
bf5c4f760a | |||
5ee9a63a4e | |||
be194f4b64 | |||
b72437758f | |||
0e00579e13 | |||
5cf4ab2fc1 | |||
6f9616ccf3 | |||
7beddaf91e | |||
e0736f1658 | |||
9c5d14213e | |||
88012002a5 | |||
290767dc29 | |||
c8d8ba8435 | |||
e10c1ff928 | |||
28a62ae6c3 | |||
09564f1748 | |||
47baa8b2e4 | |||
df4c3a34b1 | |||
b38431bf4c | |||
3b7943ca23 | |||
632c0ff3ca | |||
c31e3a8106 | |||
1cc824d624 | |||
113c8f2a53 | |||
9d7939061c | |||
44b026f5ae | |||
d0a6aadb56 | |||
47cccb4aa8 | |||
9e9cb58838 | |||
866b789a3d | |||
0260fce845 | |||
3ae8176abb | |||
3225952c69 | |||
44211bcbc9 | |||
bd4082f690 | |||
9b69e90021 | |||
5a72550598 | |||
7893bb0cd5 | |||
0add87dfa8 | |||
4ef018a34b | |||
db961deace | |||
9757051c89 | |||
7102a45382 | |||
27e5224b6c | |||
d9d0778834 | |||
18c02b5156 | |||
cadfe922c0 | |||
53fd5c3f65 | |||
179dc18ec8 | |||
0f81dfd030 | |||
11843661c0 | |||
e36eec9dac | |||
81dbc119da | |||
39318a4cc9 | |||
68fecca012 | |||
cf5913e281 | |||
bb5fa72f50 | |||
74120850a4 | |||
0f71209fe8 | |||
fdd809fdc2 | |||
02562b63dc | |||
6b0433138a | |||
fbeff099d0 | |||
17f0f4aa4e | |||
0643fe0076 | |||
ff90542cc0 | |||
ab545da6cd | |||
b3fb7dca43 | |||
e29ef65d71 | |||
6a2288a45d | |||
6a482af97c | |||
ce152f617e | |||
6d4127c90b | |||
ee9556548d | |||
107309c043 | |||
d0b630262f | |||
ce23a67b59 | |||
7586432907 | |||
5351641144 | |||
f971380b5f | |||
cae988e0fe | |||
ff53afffb5 | |||
8f1893fdb1 | |||
c335e45852 | |||
81fe49daec | |||
c4f2776239 | |||
7200f28cca | |||
ea7620bced | |||
1590729b51 | |||
5c0ed5e13f | |||
d327a230b2 | |||
560baf1b01 | |||
d3cce09a7a | |||
a3fec20b52 | |||
c4e2d8ee14 | |||
9d246dfcba | |||
d051250959 | |||
452e1da468 | |||
3096f742d5 | |||
58991a8c43 | |||
3cdd12644e | |||
f598a5da05 | |||
372953b3e0 | |||
37fdd0fa9a | |||
2d6a723be0 | |||
3cd2db8f7b | |||
28ed1df26b | |||
608f6924e3 | |||
e8b981e7df | |||
d742edaff4 | |||
0e37230f69 | |||
a14d1361bb | |||
4da7e0c85d | |||
a3b9f52684 | |||
e402595a75 | |||
|
b15428af21 | ||
e1eaf45e58 | |||
d5f7306e59 | |||
de8cda6846 | |||
637046c4ef | |||
96c68dc608 | |||
fb25a21c4c | |||
c8198bf246 | |||
f0f3316714 | |||
|
cd03b04cf7 | ||
e3fa5d9de0 | |||
8520a36be2 | |||
65be98f6b8 | |||
53bda4d853 | |||
|
1c7840c10d | ||
96fc50498c | |||
6acc94b7c5 | |||
|
ca7dc40b03 | ||
f96dd9448b | |||
9fb552e6dc | |||
9b2f1a744f | |||
172e82ba54 | |||
2b0adbb81a | |||
83af0df5d4 | |||
f80a44f1ac | |||
f8a602e6a3 | |||
adc6e10df1 | |||
64fbe010ef | |||
204d8342bb | |||
0fc33fccff | |||
cf169021c6 | |||
a307760dcc | |||
ae08a4398a | |||
f6501ca698 | |||
3be383c750 | |||
6536acb10e | |||
|
586ef37874 | ||
8f20250dee | |||
b9d9a8c435 | |||
2554b537e8 | |||
a0824785e5 | |||
f25aac1fd9 | |||
325e781758 | |||
997fa950fd | |||
081649ab58 | |||
71e6f829c5 | |||
9e78994c03 | |||
359b4b43c7 | |||
e1c9beb872 | |||
add5a4654c | |||
95565c33ec | |||
|
3e3881022e | ||
76f280172b | |||
182c97fb84 | |||
ee7ddbb1de | |||
0cb3987380 | |||
567bf5f002 | |||
fecd35844f | |||
b4559f6771 | |||
708218d34a | |||
a3d9e17a71 | |||
89e9410810 | |||
a6aafd0ef2 | |||
6f1563cfb6 | |||
f5971c8429 | |||
1677afd975 | |||
22925398da | |||
f1615957bc | |||
b61bd4c70c | |||
f4bc6d847d | |||
c1141c366a | |||
ef0fe2cb04 | |||
46b3500faa | |||
1f07e1046c | |||
251c1e53fc | |||
84a283b4c2 | |||
4389016b95 | |||
f1b4a878a5 | |||
43e161ebb6 | |||
ed3ab5dc4f | |||
2099321f0b | |||
4ea19b4ff4 | |||
1644f52eb0 | |||
f607f11b82 | |||
c4c6b1a752 | |||
99926827f1 | |||
03ce8df291 | |||
5c1f712900 | |||
d17d0bd534 | |||
e520e39b72 | |||
b3162b1ed5 | |||
69b594cf8e | |||
86e4aa483f | |||
17d2cc4ebd | |||
1ec9f3c922 | |||
9f075077ba | |||
ba40134219 | |||
1ca7226cfe | |||
e50ca2fd5a | |||
a9ecd1e7ab | |||
987c7aef01 | |||
21009f6b51 | |||
035e71185a | |||
2a51593cc3 | |||
b813129410 | |||
6c02b965b0 | |||
e77fa5d6ad | |||
e066048e9f | |||
612a9185eb | |||
a6fa88b981 | |||
a6662450de | |||
86fbf31120 | |||
ef7d4c8d3e | |||
9f999c013e | |||
78fe5582e6 | |||
14430e79ef | |||
5e3f9e9aee | |||
b55686d095 | |||
c3a965f284 | |||
99d148666e | |||
be1a1df00b | |||
ce819185eb | |||
16c68e5ceb | |||
5fa4ee929e | |||
00190468a8 | |||
b9b0994f4c | |||
f8d4be5385 | |||
90f6e8e1cb | |||
3c872b0484 | |||
|
5f949ccf34 | ||
2750c9d25b | |||
6842961d42 | |||
c89f84a44f | |||
5ee60d3dc7 | |||
4c25ea3410 | |||
6cbaa384dc | |||
c9c962f646 | |||
4d54e3dd6d | |||
dd08229ff1 | |||
11161c4b71 | |||
07d42c558a | |||
bf8d3b48cb | |||
80ac42075e | |||
9a3d3bd048 | |||
9a74b2b6e5 | |||
9316b1e855 | |||
054c143e66 | |||
041580e1ab | |||
73d1dc6cf2 | |||
7692757091 | |||
426f4d6273 | |||
4c9d04f175 | |||
|
7bc0b85ae5 | ||
|
179b808de6 | ||
|
19d48ed324 | ||
|
d1124a9370 | ||
d9627a3ced | |||
1e039fb1c9 | |||
|
bfbbe06cd2 | ||
767b4728b5 | |||
dee41be85d | |||
1e1654a4b8 | |||
b9b24fe7c6 | |||
216c9085c1 | |||
0fd44117ec | |||
ed718fa438 | |||
|
8a61170fbf | ||
fa7a9bc102 | |||
35d97a77b1 | |||
48eccd68c5 | |||
362f5c51d3 | |||
0219d5d1aa | |||
530522f51c | |||
b8b793e292 | |||
e4fef3df33 | |||
54fa20c4f7 | |||
89edd10dc2 | |||
ebe01566c0 | |||
a0f76eb00b | |||
f81c2811ce | |||
|
c12d8cf4bb | ||
77d7f35d25 | |||
84ca4d0a62 | |||
4a59cbcf82 | |||
1b920fa55c | |||
81f730ea68 | |||
|
a1cfc9b914 | ||
|
81763fdf37 | ||
|
884122b007 | ||
8c0320c97e | |||
14525ee76e | |||
cd4d7605f5 | |||
5da70e81f9 | |||
|
f7727a3c39 | ||
e46e4ec0d7 | |||
a4f4c10efc | |||
82b076df3f | |||
cf8cbaae8c |
5
.env
Normal file
5
.env
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FLASK_ENV=development
|
||||||
|
FLASK_DEBUG=False
|
||||||
|
FLASK_RUN_PORT=5000
|
||||||
|
FLASK_RUN_HOST=0.0.0.0
|
||||||
|
FLASK_APP=WebMain.py
|
183
.gitignore
vendored
Normal file
183
.gitignore
vendored
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Python template
|
||||||
|
# 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/
|
||||||
|
*.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/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
### VirtualEnv template
|
||||||
|
# Virtualenv
|
||||||
|
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
||||||
|
.Python
|
||||||
|
[Bb]in
|
||||||
|
[Ii]nclude
|
||||||
|
[Ll]ib
|
||||||
|
[Ll]ib64
|
||||||
|
[Ll]ocal
|
||||||
|
[Ss]cripts
|
||||||
|
pyvenv.cfg
|
||||||
|
.venv
|
||||||
|
pip-selfcheck.json
|
||||||
|
*.mp4
|
||||||
|
*.flv
|
||||||
|
config*
|
||||||
|
.*
|
2
CHANGELOG
Normal file
2
CHANGELOG
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# 接口版本9.4.2(94214)
|
||||||
|
弹幕接口改为`/webcast/im/fetch/`,发现会先连接websocket,然而websocket又是魔改protobuf,实在是弄不懂
|
23
Chat.py
23
Chat.py
@ -1,23 +0,0 @@
|
|||||||
from User import User
|
|
||||||
|
|
||||||
class Chat:
|
|
||||||
|
|
||||||
content:str=""
|
|
||||||
user:User=None
|
|
||||||
|
|
||||||
def __init__(self, json=None):
|
|
||||||
if json:
|
|
||||||
self.parse(json)
|
|
||||||
|
|
||||||
def parse(self, json):
|
|
||||||
self.user = User(json)
|
|
||||||
if "Msg" in json:
|
|
||||||
if "content" in json["Msg"]:
|
|
||||||
self.content = json["Msg"]['content']
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "{} : {}".format(self.user,self.content)
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
478
Common.py
Normal file
478
Common.py
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
import os
|
||||||
|
import queue
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import psutil
|
||||||
|
from api import XiGuaLiveApi
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
from bilibili import Bilibili, VideoPart
|
||||||
|
|
||||||
|
# 默认设置
|
||||||
|
config = {
|
||||||
|
# 录像的主播ID
|
||||||
|
"l_u": "97621754276",
|
||||||
|
# 视频位置
|
||||||
|
"path": ".",
|
||||||
|
# 标题及预留时间位置
|
||||||
|
"t_t": "【永恒de草薙直播录播】直播于 {}",
|
||||||
|
# 标签
|
||||||
|
"tag": ["永恒de草薙", "三国", "三国战记", "直播录像", "录播", "怀旧", "街机"],
|
||||||
|
# 描述
|
||||||
|
"des": "西瓜直播 https://live.ixigua.com/userlive/97621754276 \n自动投递\n原主播:永恒de草薙\n直播时间:晚上6点多到凌晨4点左右",
|
||||||
|
# 来源, 空则为自制
|
||||||
|
"src": "",
|
||||||
|
# Log条数
|
||||||
|
"l_c": 5,
|
||||||
|
# 错误Log条数
|
||||||
|
"elc": 10,
|
||||||
|
# 每一chunk大小
|
||||||
|
"c_s": 16 * 1024,
|
||||||
|
# 每一块视频大小
|
||||||
|
"p_s": 2141000000,
|
||||||
|
# 忽略的大小
|
||||||
|
"i_s": 2048000,
|
||||||
|
"max": 75,
|
||||||
|
"dow": "echo 'clean'",
|
||||||
|
# 仅下载
|
||||||
|
"dlO": True,
|
||||||
|
# 下播延迟投稿
|
||||||
|
"dly": 30,
|
||||||
|
# 短的时间的格式
|
||||||
|
"sdf": "%Y%m%d",
|
||||||
|
"enc": "ffmpeg -i {f} -c:v copy -c:a copy -f mp4 {t} -y"
|
||||||
|
}
|
||||||
|
doCleanTime = datetime.fromtimestamp(0)
|
||||||
|
loginTime = datetime.fromtimestamp(0)
|
||||||
|
_clean_flag = None
|
||||||
|
delay = datetime.fromtimestamp(0)
|
||||||
|
b = Bilibili()
|
||||||
|
|
||||||
|
network = [{
|
||||||
|
"currentTime": datetime.now(),
|
||||||
|
"out": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_sent,
|
||||||
|
},
|
||||||
|
"in": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_recv,
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"currentTime": datetime.now(),
|
||||||
|
"out": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_sent,
|
||||||
|
},
|
||||||
|
"in": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_recv,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
|
def reloadConfig():
|
||||||
|
global config
|
||||||
|
if os.path.exists('config.json'):
|
||||||
|
_config_fp = open("config.json", "r", encoding="utf8")
|
||||||
|
_config = json.load(_config_fp)
|
||||||
|
config.update(_config)
|
||||||
|
_config_fp.close()
|
||||||
|
|
||||||
|
|
||||||
|
def resetDelay():
|
||||||
|
global delay
|
||||||
|
delay = datetime.now() + timedelta(minutes=int(config['dly']))
|
||||||
|
|
||||||
|
|
||||||
|
def doDelay():
|
||||||
|
global delay
|
||||||
|
if -60 < getTimeDelta(datetime.now(), delay) < 60:
|
||||||
|
delay = datetime.fromtimestamp(0)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def updateNetwork():
|
||||||
|
global network
|
||||||
|
network.append({
|
||||||
|
"currentTime": datetime.now(),
|
||||||
|
"out": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_sent,
|
||||||
|
},
|
||||||
|
"in": {
|
||||||
|
"currentByte": psutil.net_io_counters().bytes_recv,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
network = network[-3:]
|
||||||
|
|
||||||
|
|
||||||
|
def getTimeDelta(a, b):
|
||||||
|
return (a - b).total_seconds()
|
||||||
|
|
||||||
|
|
||||||
|
def _doClean(_force=False):
|
||||||
|
global doCleanTime, _clean_flag
|
||||||
|
_disk = psutil.disk_usage(".")
|
||||||
|
if _disk.percent > config["max"] or _force:
|
||||||
|
_clean_flag = True
|
||||||
|
doCleanTime = datetime.now()
|
||||||
|
appendOperation("执行配置的清理命令")
|
||||||
|
os.system(config["dow"])
|
||||||
|
appendOperation("执行配置的清理命令完毕")
|
||||||
|
doCleanTime = datetime.now()
|
||||||
|
_clean_flag = False
|
||||||
|
|
||||||
|
|
||||||
|
def doClean(_force=False):
|
||||||
|
if _clean_flag:
|
||||||
|
return
|
||||||
|
p = threading.Thread(target=_doClean, args=(_force,))
|
||||||
|
p.setDaemon(True)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
|
||||||
|
def getCurrentStatus():
|
||||||
|
_disk = psutil.disk_usage(".")
|
||||||
|
_mem = psutil.virtual_memory()
|
||||||
|
_net = psutil.net_io_counters()
|
||||||
|
_delta = getTimeDelta(network[-1]["currentTime"], network[-2]["currentTime"])
|
||||||
|
if 60 > _delta > 1:
|
||||||
|
_inSpeed = (network[-1]["in"]["currentByte"] - network[-2]["in"]["currentByte"]) / _delta
|
||||||
|
_outSpeed = (network[-1]["out"]["currentByte"] - network[-2]["out"]["currentByte"]) / _delta
|
||||||
|
else:
|
||||||
|
_outSpeed = (network[-1]["in"]["currentByte"] - network[-2]["in"]["currentByte"])
|
||||||
|
_inSpeed = (network[-1]["out"]["currentByte"] - network[-2]["out"]["currentByte"])
|
||||||
|
updateNetwork()
|
||||||
|
return {
|
||||||
|
"memTotal": parseSize(_mem.total),
|
||||||
|
"memUsed": parseSize(_mem.used),
|
||||||
|
"memUsage": _mem.percent,
|
||||||
|
"diskTotal": parseSize(_disk.total),
|
||||||
|
"diskUsed": parseSize(_disk.used),
|
||||||
|
"diskUsage": _disk.percent,
|
||||||
|
"cpu": psutil.cpu_percent(),
|
||||||
|
"outSpeed": parseSize(_outSpeed),
|
||||||
|
"inSpeed": parseSize(_inSpeed),
|
||||||
|
"doCleanTime": datetime.strftime(doCleanTime, dt_format),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dt_format = "%Y/%m/%d %H:%M:%S"
|
||||||
|
reloadConfig()
|
||||||
|
broadcaster = ""
|
||||||
|
streamUrl = ""
|
||||||
|
|
||||||
|
forceNotDownload = False
|
||||||
|
forceNotBroadcasting = False
|
||||||
|
forceNotUpload = False
|
||||||
|
forceNotEncode = False
|
||||||
|
if config["dlO"] is True:
|
||||||
|
forceNotUpload = True
|
||||||
|
forceNotEncode = True
|
||||||
|
forceStartEncodeThread = False
|
||||||
|
forceStartUploadThread = False
|
||||||
|
|
||||||
|
uploadQueue = queue.Queue()
|
||||||
|
encodeQueue = queue.Queue()
|
||||||
|
|
||||||
|
uploadStatus = []
|
||||||
|
downloadStatus = []
|
||||||
|
encodeStatus = []
|
||||||
|
errors = []
|
||||||
|
operations = []
|
||||||
|
|
||||||
|
|
||||||
|
def appendOperation(obj):
|
||||||
|
global operations
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
operations.append(obj)
|
||||||
|
else:
|
||||||
|
operations.append({
|
||||||
|
"datetime": datetime.strftime(datetime.now(), dt_format),
|
||||||
|
"message": str(obj)
|
||||||
|
})
|
||||||
|
operations = operations[-config["elc"]:]
|
||||||
|
|
||||||
|
|
||||||
|
def parseSize(size):
|
||||||
|
K = size / 1024.0
|
||||||
|
if K > 1000:
|
||||||
|
M = K / 1024.0
|
||||||
|
if M > 1000:
|
||||||
|
return "{:.2f}GB".format(M / 1024.0)
|
||||||
|
else:
|
||||||
|
return "{:.2f}MB".format(M)
|
||||||
|
else:
|
||||||
|
return "{:.2f}KB".format(K)
|
||||||
|
|
||||||
|
|
||||||
|
def appendUploadStatus(obj):
|
||||||
|
global uploadStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
uploadStatus.append(obj)
|
||||||
|
else:
|
||||||
|
uploadStatus.append({
|
||||||
|
"datetime": datetime.strftime(datetime.now(), dt_format),
|
||||||
|
"message": str(obj)
|
||||||
|
})
|
||||||
|
uploadStatus = uploadStatus[-config["l_c"]:]
|
||||||
|
|
||||||
|
|
||||||
|
def modifyLastUploadStatus(obj):
|
||||||
|
global uploadStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
uploadStatus[-1] = obj
|
||||||
|
else:
|
||||||
|
uploadStatus[-1]["message"] = str(obj)
|
||||||
|
uploadStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
|
||||||
|
|
||||||
|
def appendEncodeStatus(obj):
|
||||||
|
global encodeStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
encodeStatus.append(obj)
|
||||||
|
else:
|
||||||
|
encodeStatus.append({
|
||||||
|
"datetime": datetime.strftime(datetime.now(), dt_format),
|
||||||
|
"message": str(obj)
|
||||||
|
})
|
||||||
|
encodeStatus = encodeStatus[-config["l_c"]:]
|
||||||
|
|
||||||
|
|
||||||
|
def modifyLastEncodeStatus(obj):
|
||||||
|
global encodeStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
encodeStatus[-1] = obj
|
||||||
|
else:
|
||||||
|
encodeStatus[-1]["message"] = str(obj)
|
||||||
|
encodeStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
|
||||||
|
|
||||||
|
def appendDownloadStatus(obj):
|
||||||
|
global downloadStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
downloadStatus.append(obj)
|
||||||
|
else:
|
||||||
|
downloadStatus.append({
|
||||||
|
"datetime": datetime.strftime(datetime.now(), dt_format),
|
||||||
|
"message": str(obj)
|
||||||
|
})
|
||||||
|
downloadStatus = downloadStatus[-config["l_c"]:]
|
||||||
|
|
||||||
|
|
||||||
|
def modifyLastDownloadStatus(obj):
|
||||||
|
global downloadStatus
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
downloadStatus[-1] = obj
|
||||||
|
else:
|
||||||
|
downloadStatus[-1]["message"] = str(obj)
|
||||||
|
downloadStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
|
||||||
|
|
||||||
|
def appendError(obj):
|
||||||
|
global errors
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
if "datetime" not in obj:
|
||||||
|
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
|
||||||
|
errors.append(obj)
|
||||||
|
else:
|
||||||
|
errors.append({
|
||||||
|
"datetime": datetime.strftime(datetime.now(), dt_format),
|
||||||
|
"message": str(obj)
|
||||||
|
})
|
||||||
|
errors = errors[-config["elc"]:]
|
||||||
|
|
||||||
|
|
||||||
|
def loginBilibili(force=False):
|
||||||
|
if config["dlO"] is False or forceNotUpload is False:
|
||||||
|
global loginTime
|
||||||
|
global b
|
||||||
|
if getTimeDelta(datetime.now(), loginTime) < 86400 * 10 and not force:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
b.login()
|
||||||
|
loginTime = datetime.now()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
appendError(e)
|
||||||
|
appendOperation("登录失败")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
appendOperation("设置了不上传,所以不会登陆")
|
||||||
|
|
||||||
|
|
||||||
|
class downloader(XiGuaLiveApi):
|
||||||
|
__playlist = None
|
||||||
|
__danmakuFile = None
|
||||||
|
__danmakuBiasTime = None
|
||||||
|
|
||||||
|
def getDanmaku(self):
|
||||||
|
super(downloader, self).getDanmaku()
|
||||||
|
if self.__danmakuFile is not None and self.__danmakuFile.writable():
|
||||||
|
self.__danmakuFile.flush()
|
||||||
|
|
||||||
|
def onPresentEnd(self, gift):
|
||||||
|
if self.__danmakuFile is not None and self.__danmakuFile.writable():
|
||||||
|
now = datetime.now()
|
||||||
|
if self.__danmakuBiasTime is None:
|
||||||
|
return
|
||||||
|
ts = (now - self.__danmakuBiasTime).total_seconds()
|
||||||
|
_c = """<gift ts="{:.2f}" user="{}" giftname="{}" giftcount="{}"></gift>\r\n""".format(ts, gift.user.name, gift.name, gift.count)
|
||||||
|
self.__danmakuFile.write(_c.encode("UTF-8"))
|
||||||
|
|
||||||
|
def onChat(self, chat):
|
||||||
|
if self.__danmakuFile is not None and self.__danmakuFile.writable():
|
||||||
|
now = datetime.now()
|
||||||
|
if self.__danmakuBiasTime is None:
|
||||||
|
return
|
||||||
|
ts = (now - self.__danmakuBiasTime).total_seconds()
|
||||||
|
_c = """<d p="{:.2f},1,24,16777215,{:.0f},0,{},0" user="{}">{}</d>\r\n""".format(ts, now.timestamp()*1000, chat.user.ID, chat.user.name, chat.content)
|
||||||
|
self.__danmakuFile.write(_c.encode("UTF-8"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def playlist(self):
|
||||||
|
return self.__playlist
|
||||||
|
|
||||||
|
@playlist.setter
|
||||||
|
def playlist(self, value):
|
||||||
|
global streamUrl
|
||||||
|
self.__playlist = value
|
||||||
|
streamUrl = value
|
||||||
|
|
||||||
|
def _checkUsernameIsMatched(self, compare=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def updRoomInfo(self, force=False):
|
||||||
|
global broadcaster
|
||||||
|
_prev_status = self.isLive
|
||||||
|
doClean()
|
||||||
|
if not force and self.isLive:
|
||||||
|
return _prev_status
|
||||||
|
_result = super(downloader, self).updRoomInfo(force)
|
||||||
|
if _prev_status != self.isLive and not self.isLive:
|
||||||
|
# 及时保存
|
||||||
|
self.__danmakuFile.close()
|
||||||
|
self.__danmakuFile = None
|
||||||
|
self.__danmakuBiasTime = None
|
||||||
|
resetDelay()
|
||||||
|
broadcaster = self.broadcaster
|
||||||
|
if _result:
|
||||||
|
if self.isLive:
|
||||||
|
self.updPlayList()
|
||||||
|
else:
|
||||||
|
self.playlist = False
|
||||||
|
return _result
|
||||||
|
|
||||||
|
def updPlayList(self):
|
||||||
|
if self.isLive and "stream_url" in self._rawRoomInfo:
|
||||||
|
if 'rtmp_pull_url' in self._rawRoomInfo["stream_url"]:
|
||||||
|
self.playlist = self._rawRoomInfo["stream_url"]['rtmp_pull_url']
|
||||||
|
elif 'flv_pull_url' in self._rawRoomInfo["stream_url"]:
|
||||||
|
_playlist = self._rawRoomInfo["stream_url"]["flv_pull_url"]
|
||||||
|
if type(_playlist) is dict:
|
||||||
|
for _ in _playlist.values():
|
||||||
|
self.playlist = _
|
||||||
|
break
|
||||||
|
self.playlist = self.playlist.replace("_hd5", "").replace("_sd5", "").replace("_ld5", "").replace("_md", "")
|
||||||
|
else:
|
||||||
|
self.playlist = None
|
||||||
|
|
||||||
|
def initSave(self, f):
|
||||||
|
if self.__danmakuFile is not None and not self.__danmakuFile.closed:
|
||||||
|
self.__danmakuFile.close()
|
||||||
|
self.__danmakuBiasTime = datetime.now()
|
||||||
|
self.__danmakuFile = open(f, "wb")
|
||||||
|
|
||||||
|
|
||||||
|
api = downloader(config["l_u"])
|
||||||
|
|
||||||
|
|
||||||
|
def doUpdatePlaylist(_force=False):
|
||||||
|
p = threading.Thread(target=api.updRoomInfo, args=(_force,))
|
||||||
|
p.setDaemon(True)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
|
||||||
|
def refreshDownloader():
|
||||||
|
global api
|
||||||
|
api = downloader(config["l_u"])
|
||||||
|
|
||||||
|
|
||||||
|
def uploadVideo(name):
|
||||||
|
if not os.path.exists(name):
|
||||||
|
appendError("Upload File Not Exist {}".format(name))
|
||||||
|
return
|
||||||
|
loginBilibili()
|
||||||
|
doClean()
|
||||||
|
if forceNotUpload is False:
|
||||||
|
b.preUpload(VideoPart(path=name, title=os.path.basename(name)))
|
||||||
|
else:
|
||||||
|
appendUploadStatus("设置了不上传,所以[{}]不会上传了".format(name))
|
||||||
|
if not forceNotEncode:
|
||||||
|
os.remove(name)
|
||||||
|
|
||||||
|
|
||||||
|
def publishVideo(date):
|
||||||
|
if forceNotUpload is False:
|
||||||
|
b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"],
|
||||||
|
source=config["src"], no_reprint=0)
|
||||||
|
b.clear()
|
||||||
|
else:
|
||||||
|
appendUploadStatus("设置了不上传,所以[{}]的录播不会投了".format(date))
|
||||||
|
|
||||||
|
|
||||||
|
def encodeVideo(name):
|
||||||
|
if forceNotEncode:
|
||||||
|
appendEncodeStatus("设置了不编码,所以[{}]不会编码".format(name))
|
||||||
|
return False
|
||||||
|
if not os.path.exists(name):
|
||||||
|
appendEncodeStatus("文件[{}]不存在".format(name))
|
||||||
|
return False
|
||||||
|
if os.path.getsize(name) < 8 * 1024 * 1024:
|
||||||
|
appendEncodeStatus("Encoded File >{}< is too small, will ignore it".format(name))
|
||||||
|
return False
|
||||||
|
appendEncodeStatus("Encoding >{}< Start".format(name))
|
||||||
|
_new_name = os.path.splitext(name)[0] + ".mp4"
|
||||||
|
_code = os.system(config["enc"].format(f=name, t=_new_name))
|
||||||
|
if _code != 0:
|
||||||
|
appendError("Encode {} with Non-Zero Return.".format(name))
|
||||||
|
return False
|
||||||
|
modifyLastEncodeStatus("Encode >{}< Finished".format(name))
|
||||||
|
uploadQueue.put(_new_name)
|
||||||
|
|
||||||
|
|
||||||
|
def collectInfomation():
|
||||||
|
return {
|
||||||
|
"download": downloadStatus,
|
||||||
|
"encode": encodeStatus,
|
||||||
|
"encodeQueueSize": encodeQueue.qsize(),
|
||||||
|
"upload": uploadStatus,
|
||||||
|
"uploadQueueSize": uploadQueue.qsize(),
|
||||||
|
"error": errors,
|
||||||
|
"operation": operations,
|
||||||
|
"broadcast": {
|
||||||
|
"broadcaster": broadcaster.__str__(),
|
||||||
|
"isBroadcasting": api.isLive,
|
||||||
|
"streamUrl": streamUrl,
|
||||||
|
"updateTime": api.updateAt.strftime(dt_format),
|
||||||
|
"delayTime": delay.strftime(dt_format)
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"forceNotBroadcasting": forceNotBroadcasting,
|
||||||
|
"forceNotDownload": forceNotDownload,
|
||||||
|
"forceNotUpload": forceNotUpload,
|
||||||
|
"forceNotEncode": forceNotEncode,
|
||||||
|
"downloadOnly": config['dlO'],
|
||||||
|
},
|
||||||
|
}
|
BIN
Demo/242_.txt
Normal file
BIN
Demo/242_.txt
Normal file
Binary file not shown.
15
Demo/Xigua.proto
Executable file
15
Demo/Xigua.proto
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
message XiguaLive {
|
||||||
|
message Data {
|
||||||
|
// WebcastChatMessage 聊天
|
||||||
|
// WebcastGiftMessage 礼物
|
||||||
|
required string method = 1;
|
||||||
|
required bytes raw = 2;
|
||||||
|
}
|
||||||
|
repeated Data data = 1;
|
||||||
|
required string cursor = 2;
|
||||||
|
optional int32 fetch_interval = 3;
|
||||||
|
optional int32 now = 4;
|
||||||
|
required string internal_ext = 5;
|
||||||
|
}
|
10
Demo/XiguaGift.proto
Normal file
10
Demo/XiguaGift.proto
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
// 礼物
|
||||||
|
message Gift {
|
||||||
|
required string id = 1;
|
||||||
|
required string name = 2;
|
||||||
|
}
|
||||||
|
message GiftPack {
|
||||||
|
required int32 id = 1;
|
||||||
|
required Gift gift = 2;
|
||||||
|
}
|
89
Demo/XiguaMessage.proto
Normal file
89
Demo/XiguaMessage.proto
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
import "XiguaUser.proto";
|
||||||
|
import "XiguaGift.proto";
|
||||||
|
message Message {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
}
|
||||||
|
message FansClubMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
// 升级是1,加入是2
|
||||||
|
required int32 type = 2;
|
||||||
|
// 提示文字
|
||||||
|
required string content = 3;
|
||||||
|
required User user = 4;
|
||||||
|
}
|
||||||
|
message FansClubStatsMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required string title = 2;
|
||||||
|
required int32 count = 3;
|
||||||
|
}
|
||||||
|
message UserSeqMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required string popularityText = 4;
|
||||||
|
required int32 popularity = 6;
|
||||||
|
}
|
||||||
|
message DailyRankMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required int32 ranking = 10;
|
||||||
|
}
|
||||||
|
message ChatMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required User user = 2;
|
||||||
|
required string content = 3;
|
||||||
|
}
|
||||||
|
message MemberMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required User user = 2;
|
||||||
|
required string popularityText = 14;
|
||||||
|
}
|
||||||
|
message GiftMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required int32 giftId = 2;
|
||||||
|
// 可能是GroupId之类的东西
|
||||||
|
// required int32 UNKNOWN_INT = 3;
|
||||||
|
required int32 content4 = 4;
|
||||||
|
required int32 repeated = 5;
|
||||||
|
required int32 combo = 6;
|
||||||
|
optional User user = 7;
|
||||||
|
// 是否发完了,注:不可连击的也是没有发完的
|
||||||
|
optional bool isFinished = 9 [ default = false ];
|
||||||
|
}
|
||||||
|
message SocialMessage {
|
||||||
|
required CommonInfo commonInfo = 1;
|
||||||
|
required User user = 2;
|
||||||
|
required int32 int4 = 4;
|
||||||
|
required int32 fansCount = 6;
|
||||||
|
}
|
||||||
|
// 样式
|
||||||
|
message Style {
|
||||||
|
optional string color = 1;
|
||||||
|
optional int32 fontWeight = 4;
|
||||||
|
}
|
||||||
|
// 参数
|
||||||
|
message Params {
|
||||||
|
// 1 字符串
|
||||||
|
// 11 用户
|
||||||
|
// 12 礼物
|
||||||
|
required int32 type = 1;
|
||||||
|
optional Style style = 2;
|
||||||
|
optional string string = 11;
|
||||||
|
optional UserPack users = 21;
|
||||||
|
optional GiftPack gifts = 22;
|
||||||
|
}
|
||||||
|
// 自定义显示信息
|
||||||
|
message DisplayText {
|
||||||
|
// 参数
|
||||||
|
required string method = 1;
|
||||||
|
required string format = 2;
|
||||||
|
optional Style bgStyle = 3;
|
||||||
|
required Params params = 4;
|
||||||
|
}
|
||||||
|
// 通用定义
|
||||||
|
message CommonInfo {
|
||||||
|
required string method = 1;
|
||||||
|
required int32 msg_id = 2;
|
||||||
|
required int32 room_id = 3;
|
||||||
|
required int32 create_time = 4;
|
||||||
|
optional int32 someEnum = 6;
|
||||||
|
optional DisplayText displayText = 8;
|
||||||
|
}
|
81
Demo/XiguaUser.proto
Normal file
81
Demo/XiguaUser.proto
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
message UserPack {
|
||||||
|
required User user = 1;
|
||||||
|
}
|
||||||
|
// 头衔
|
||||||
|
message Badge {
|
||||||
|
message FanClubText {
|
||||||
|
required string text = 1;
|
||||||
|
optional string color = 2;
|
||||||
|
required int32 level = 3;
|
||||||
|
}
|
||||||
|
repeated string url = 1;
|
||||||
|
// optional string localUrl = 2;
|
||||||
|
optional int32 height = 3;
|
||||||
|
optional int32 width = 4;
|
||||||
|
// 3 房管
|
||||||
|
// 6 贵族
|
||||||
|
// 7 粉丝团
|
||||||
|
optional int32 type = 6;
|
||||||
|
optional string clickTo = 7;
|
||||||
|
optional FanClubText fanClubText = 8;
|
||||||
|
}
|
||||||
|
message FansClubPack {
|
||||||
|
message FansClub {
|
||||||
|
required string title = 1 [default = ''];
|
||||||
|
required int32 level = 2 [default = 0];
|
||||||
|
optional int32 someEnum = 3;
|
||||||
|
}
|
||||||
|
required FansClub fansClub = 1;
|
||||||
|
}
|
||||||
|
// 用户信息
|
||||||
|
message User {
|
||||||
|
// 头像
|
||||||
|
message Avatar {
|
||||||
|
required string url = 1;
|
||||||
|
optional string id = 2;
|
||||||
|
}
|
||||||
|
// 粉丝和粉
|
||||||
|
message Follow {
|
||||||
|
optional int32 following = 1 [default = 0];
|
||||||
|
optional int32 follower = 2 [default = 0];
|
||||||
|
}
|
||||||
|
// 花钱等级
|
||||||
|
message PayGrade {
|
||||||
|
required int32 current = 1;
|
||||||
|
required int32 level = 6;
|
||||||
|
optional int32 currentLevelNeed = 10;
|
||||||
|
optional int32 nextLevelNeed = 11;
|
||||||
|
optional string content = 13;
|
||||||
|
required Badge badge = 19;
|
||||||
|
optional int32 toNextLevelNeed = 21;
|
||||||
|
}
|
||||||
|
// 荣誉等级
|
||||||
|
message HonorLevel {
|
||||||
|
required Badge badge = 19;
|
||||||
|
}
|
||||||
|
// 贵族
|
||||||
|
message Noble {
|
||||||
|
message NobleBoarder {
|
||||||
|
repeated string urlList = 1;
|
||||||
|
required string uri = 2;
|
||||||
|
optional int32 height = 3;
|
||||||
|
optional int32 width = 4;
|
||||||
|
}
|
||||||
|
required string content = 4;
|
||||||
|
optional NobleBoarder boarder = 8;
|
||||||
|
}
|
||||||
|
required int64 id = 1;
|
||||||
|
required string nickname = 3;
|
||||||
|
required int32 gender = 4;
|
||||||
|
// 这个顺序可能有点迷,不是很清楚
|
||||||
|
required Avatar avatarThumb = 9;
|
||||||
|
optional Avatar avatarMedium = 10;
|
||||||
|
optional Avatar avatarLarge = 11;
|
||||||
|
repeated Badge badge = 21;
|
||||||
|
optional Follow follow = 22;
|
||||||
|
required PayGrade payGrade = 23;
|
||||||
|
required FansClubPack fansClub = 24;
|
||||||
|
required int32 totalPaid = 34;
|
||||||
|
}
|
BIN
Demo/a.txt
Normal file
BIN
Demo/a.txt
Normal file
Binary file not shown.
BIN
Demo/fst.txt
Normal file
BIN
Demo/fst.txt
Normal file
Binary file not shown.
997
Demo/guanzhu.txt
Normal file
997
Demo/guanzhu.txt
Normal file
@ -0,0 +1,997 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2: 6787717978657360643
|
||||||
|
3: 6787691314156276488
|
||||||
|
4: 1580388803763
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "webcast_xigua_gift_message"
|
||||||
|
2: "{0:user} \351\200\201\347\273\231\344\270\273\346\222\255{2:string}\344\270\252{1:gift}"
|
||||||
|
3 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#ffffd600"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 12
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 10001
|
||||||
|
2 {
|
||||||
|
1: "live_gift_10001"
|
||||||
|
2: "\350\245\277\347\223\234"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 1
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
11: "18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: 10001
|
||||||
|
3: 4997044
|
||||||
|
4: 1
|
||||||
|
5: 18
|
||||||
|
6: 18
|
||||||
|
7 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
11: 1580388797
|
||||||
|
12: 7453182
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastSocialMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastSocialMessage"
|
||||||
|
2: 6787718225754295054
|
||||||
|
3: 6787691314156276488
|
||||||
|
4: 1580388803802
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 111036833136
|
||||||
|
3: "\347\224\250\346\210\2679627521617519"
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3796/2975850990~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 1
|
||||||
|
2: 19
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAApZHNJdD-IbL7CES631w87jSXrSyXZfqETb-HYnYx6Ug"
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
4: 1
|
||||||
|
6: 169079
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2: 6787718023417531148
|
||||||
|
3: 6787691314156276488
|
||||||
|
4: 1580388804048
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "webcast_xigua_gift_message"
|
||||||
|
2: "{0:user} \351\200\201\347\273\231\344\270\273\346\222\255{2:string}\344\270\252{1:gift}"
|
||||||
|
3 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#ffffd600"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 12
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 10001
|
||||||
|
2 {
|
||||||
|
1: "live_gift_10001"
|
||||||
|
2: "\350\245\277\347\223\234"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 1
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
11: "19"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: 10001
|
||||||
|
3: 4997044
|
||||||
|
4: 1
|
||||||
|
5: 19
|
||||||
|
6: 19
|
||||||
|
7 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
11: 1580388797
|
||||||
|
12: 7453182
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2: 6787718227533761294
|
||||||
|
3: 6787691314156276488
|
||||||
|
4: 1580388804226
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 9999
|
||||||
|
2 {
|
||||||
|
1: 4719119436
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/6368/3857576856~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 9998
|
||||||
|
2 {
|
||||||
|
1: 60374191432
|
||||||
|
2: 259345
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/da99000fd41edfb7daa6~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1699
|
||||||
|
2 {
|
||||||
|
1: 3544417251634206
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/830d7e15f45946aa9b757a500cc6dcbe~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 3
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1099
|
||||||
|
2 {
|
||||||
|
1: 4261353838881501
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/c24df9dffd6d45929c227c5da22fe406~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 4
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 2933125236921479
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/2e1c9d64f34a4a3e8a326fe5394659fd~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 5
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 300
|
||||||
|
2 {
|
||||||
|
1: 3927095572170669
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/daaa001914e0039994ae"
|
||||||
|
2: "daaa001914e0039994ae"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 6
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 120
|
||||||
|
2 {
|
||||||
|
1: 153552343543981
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3033762272~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 7
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 99
|
||||||
|
2 {
|
||||||
|
1: 1732418933370259
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/5941f17833524bfa9316a648c39c990f~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 8
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 99
|
||||||
|
2 {
|
||||||
|
1: 104372509299
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/da920004cd041ec12061"
|
||||||
|
2: "da920004cd041ec12061"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 9
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 60
|
||||||
|
2 {
|
||||||
|
1: 60518722952
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/0f9162a614bd474f9fbda57614a0c9f1~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 10
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 30
|
||||||
|
2 {
|
||||||
|
1: 1261881879167767
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3044413937~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 11
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 22
|
||||||
|
2 {
|
||||||
|
1: 1173933315333736
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/a181c0707ff540aba16f43af049a3791~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 12
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 20
|
||||||
|
2 {
|
||||||
|
1: 3949047076102647
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/187afa353816402cb827e9fae386ca2a~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 13
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: 65771610619
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3793/3131589739~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 99827340042
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/da74000192436fc5db6e"
|
||||||
|
2: "da74000192436fc5db6e"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 99482502045
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3793/3114521287~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 16
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 98103952579
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3793/3131589739~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 17
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 9746464842
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/6ad34237256e4471b16810eb098224c0~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 18
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 97221408269
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3793/3131589739~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 19
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 971618215795604
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3797/2889309425~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 20
|
||||||
|
}
|
||||||
|
3: 461
|
||||||
|
4: "15\344\270\207\344\272\272\346\260\224"
|
||||||
|
6: 158310
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastGiftMessage"
|
||||||
|
2: 6787717971278351115
|
||||||
|
3: 6787691314156276488
|
||||||
|
4: 1580388804414
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "webcast_xigua_gift_message"
|
||||||
|
2: "{0:user} \351\200\201\347\273\231\344\270\273\346\222\255{2:string}\344\270\252{1:gift}"
|
||||||
|
3 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#ffffd600"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 12
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 10001
|
||||||
|
2 {
|
||||||
|
1: "live_gift_10001"
|
||||||
|
2: "\350\245\277\347\223\234"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 1
|
||||||
|
2 {
|
||||||
|
1: "#ffff9d5c"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
11: "20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: 10001
|
||||||
|
3: 4997044
|
||||||
|
4: 1
|
||||||
|
5: 20
|
||||||
|
6: 20
|
||||||
|
7 {
|
||||||
|
1: 105855829073
|
||||||
|
3: "\345\260\217\350\234\234\346\237\240\346\252\254\350\214\266"
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
10 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
11 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
15: 1
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 2
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
1: 62
|
||||||
|
6: 5
|
||||||
|
10: 51
|
||||||
|
11: 99
|
||||||
|
13: "\350\267\235\347\246\2736\347\272\247\350\277\230\345\267\25638\351\222\273\347\237\263"
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21: 38
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
34: 62
|
||||||
|
37: 1
|
||||||
|
38: "0"
|
||||||
|
44: ""
|
||||||
|
46: "MS4wLjABAAAAd4R7mC-c8FCTjCqTIhJ0CoydF_FMweyatdS66xud0hY"
|
||||||
|
48: ""
|
||||||
|
1028: "105855829073"
|
||||||
|
}
|
||||||
|
11: 1580388797
|
||||||
|
12: 7453184
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "6787717971278351115_1580388804554_6787718002764073739_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1580388804554
|
||||||
|
5: "fetch_time:1580388804554|start_time:1580388804048|ack_ids:6787718023417531148_1b2|fetch_id:6787718004823608078|flag:1|seq:141"
|
165
Demo/jingyan.txt
Normal file
165
Demo/jingyan.txt
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6787727734057011981
|
||||||
|
3: 6787691314156276488
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "member_silence_toast_3"
|
||||||
|
2: "{0:user} \350\242\253\347\256\241\347\220\206\345\221\230 {1:user} \347\246\201\350\250\200\344\272\206"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 53536270159
|
||||||
|
3: "\350\243\244\350\243\206\351\207\214\347\232\204\345\244\247\345\256\235\345\211\221"
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAtH9p-LupXO1oQVJtlefmpryPoXqWzKs3_Nad9BlAREA"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 2721997823950523
|
||||||
|
3: "\350\257\267\345\217\253\346\210\221\347\226\257\345\255\220\345\205\255"
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAA1KKMtPQlRg_wecgX0G2Wl-ZIcWe-Yos95-IBwF1AzhSYzL5-zXCa4lciHj2HZho5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 53536270159
|
||||||
|
3: "\350\243\244\350\243\206\351\207\214\347\232\204\345\244\247\345\256\235\345\211\221"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/1bf40000bd6dc5335b2d"
|
||||||
|
2: "1bf40000bd6dc5335b2d"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_9.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_7.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 1
|
||||||
|
2: 17
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 9
|
||||||
|
19 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_9.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\346\260\270\346\201\222"
|
||||||
|
2: 7
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_7.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_7.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\346\260\270\346\201\222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32 {
|
||||||
|
1: 1
|
||||||
|
}
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAtH9p-LupXO1oQVJtlefmpryPoXqWzKs3_Nad9BlAREA"
|
||||||
|
50 {
|
||||||
|
1 {
|
||||||
|
3: 1008
|
||||||
|
4: 1125
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
3: 105
|
||||||
|
4: 111
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fnoble%2Fnoble_privilege_intro%2Findex.html%3Fforbid_right_back%3D1&type=fullscreen&hide_nav_bar=1&status_bar_color=white&status_bar_bg_color=%2300000000&noble_intercept=1&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
4: "\346\231\256\351\200\232\347\224\250\346\210\267"
|
||||||
|
6 {
|
||||||
|
3: 366
|
||||||
|
4: 615
|
||||||
|
}
|
||||||
|
7 {
|
||||||
|
3: 60
|
||||||
|
4: 108
|
||||||
|
}
|
||||||
|
8 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
2: "webcast/noble_boarder.png"
|
||||||
|
3: 64
|
||||||
|
4: 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
3: 555
|
||||||
|
4 {
|
||||||
|
1: 2721997823950523
|
||||||
|
3: "\350\257\267\345\217\253\346\210\221\347\226\257\345\255\220\345\205\255"
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAA1KKMtPQlRg_wecgX0G2Wl-ZIcWe-Yos95-IBwF1AzhSYzL5-zXCa4lciHj2HZho5"
|
||||||
|
}
|
||||||
|
10: 9
|
||||||
|
14: "16\344\270\207\344\272\272\346\260\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "6787727734057011981_1580391018357_6787727537927867150_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1580391018357
|
||||||
|
5: "fetch_time:1580391018357|start_time:1580391017508|ack_ids:6787727734057011981_1296|fetch_id:6787727723432626957|flag:1|seq:126"
|
605
Demo/result5.txt
Normal file
605
Demo/result5.txt
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2: 6776883976293452551
|
||||||
|
3: 6776859660747344653
|
||||||
|
4: 1577866267927
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "webcast_chat_display_text"
|
||||||
|
2: "{0:user}{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#ff36c0cf"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#60000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 51510235218
|
||||||
|
3: "\351\222\242\346\236\252\345\205\204\345\274\237\350\266\205\345\223\245"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/2e8b032f45854441bd5e539ea892e00f~120x256.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_16.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 45
|
||||||
|
2: 17
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 16
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_16.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: 15
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32 {
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAALx1qtwLJiLVbuWXt7ZYTxHxVFvZz2PITy5YfQidfGp4"
|
||||||
|
50 {
|
||||||
|
1 {
|
||||||
|
3: 1008
|
||||||
|
4: 1125
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
3: 105
|
||||||
|
4: 111
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fnoble%2Fnoble_privilege_intro%2Findex.html%3Fforbid_right_back%3D1&status_bar_bg_color=%2300000000&noble_intercept=1&__live_platform__=webcast&type=fullscreen&hide_nav_bar=1&status_bar_color=white"
|
||||||
|
}
|
||||||
|
4: "\346\231\256\351\200\232\347\224\250\346\210\267"
|
||||||
|
6 {
|
||||||
|
3: 366
|
||||||
|
4: 615
|
||||||
|
}
|
||||||
|
7 {
|
||||||
|
3: 60
|
||||||
|
4: 108
|
||||||
|
}
|
||||||
|
8 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
2: "webcast/noble_boarder.png"
|
||||||
|
3: 64
|
||||||
|
4: 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 1
|
||||||
|
11: "\350\277\231\346\263\242\346\223\215\344\275\234\343\200\202\346\254\272\350\264\237\344\272\272\345\221\200"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 51510235218
|
||||||
|
3: "\351\222\242\346\236\252\345\205\204\345\274\237\350\266\205\345\223\245"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/2e8b032f45854441bd5e539ea892e00f~120x256.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_16.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 45
|
||||||
|
2: 17
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 16
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_16.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_16.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: 15
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32 {
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAALx1qtwLJiLVbuWXt7ZYTxHxVFvZz2PITy5YfQidfGp4"
|
||||||
|
50 {
|
||||||
|
1 {
|
||||||
|
3: 1008
|
||||||
|
4: 1125
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
3: 105
|
||||||
|
4: 111
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fnoble%2Fnoble_privilege_intro%2Findex.html%3Fforbid_right_back%3D1&status_bar_bg_color=%2300000000&noble_intercept=1&__live_platform__=webcast&type=fullscreen&hide_nav_bar=1&status_bar_color=white"
|
||||||
|
}
|
||||||
|
4: "\346\231\256\351\200\232\347\224\250\346\210\267"
|
||||||
|
6 {
|
||||||
|
3: 366
|
||||||
|
4: 615
|
||||||
|
}
|
||||||
|
7 {
|
||||||
|
3: 60
|
||||||
|
4: 108
|
||||||
|
}
|
||||||
|
8 {
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
2: "webcast/noble_boarder.png"
|
||||||
|
3: 64
|
||||||
|
4: 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: "\350\277\231\346\263\242\346\223\215\344\275\234\343\200\202\346\254\272\350\264\237\344\272\272\345\221\200"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2: 6776883987831969295
|
||||||
|
3: 6776859660747344653
|
||||||
|
4: 1577866267933
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 100902326983
|
||||||
|
3: "\346\211\254\345\256\266\345\206\233\347\201\254\344\272\232\351\243\236"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/aade000f6df1961243c5~120x256.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_9.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_4.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 45
|
||||||
|
2: 7
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 9
|
||||||
|
19 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_9.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_9.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
2: 4
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_4.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_4.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\351\222\242\346\236\252\346\211\213"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAArfQQ4YVnKMKthzbKgv2swkggu8Ovv8eQCp56JmvvRvE"
|
||||||
|
50 {
|
||||||
|
1 {
|
||||||
|
3: 1008
|
||||||
|
4: 1125
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
3: 105
|
||||||
|
4: 111
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fnoble%2Fnoble_privilege_intro%2Findex.html%3Fforbid_right_back%3D1&type=fullscreen&hide_nav_bar=1&status_bar_color=white&status_bar_bg_color=%2300000000&noble_intercept=1&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
4: "\346\231\256\351\200\232\347\224\250\346\210\267"
|
||||||
|
6 {
|
||||||
|
3: 366
|
||||||
|
4: 615
|
||||||
|
}
|
||||||
|
7 {
|
||||||
|
3: 60
|
||||||
|
4: 108
|
||||||
|
}
|
||||||
|
8 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
2: "webcast/noble_boarder.png"
|
||||||
|
3: 64
|
||||||
|
4: 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: "\351\230\277\344\274\237\345\220\271\347\211\233\346\257\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2: 6776884008732789507
|
||||||
|
3: 6776859660747344653
|
||||||
|
4: 1577866268029
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1975
|
||||||
|
2 {
|
||||||
|
1: 479033461313651
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/49b2bd0b157e4787917b029da02d2622~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 999
|
||||||
|
2 {
|
||||||
|
1: 3962278245043603
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/241f1001013a2e8505175~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 571
|
||||||
|
2 {
|
||||||
|
1: 53231054839
|
||||||
|
9 {
|
||||||
|
1: "http://wx.qlogo.cn/mmopen/XFJ8HdGGwGDwy1reeaMqlfQrUh81uSv81HqUsESBK8YsNQ2oEIct3ibwdq1k55HLC7m43nfFiaX3EYpw2lKH4wibw/64"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 3
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 88336033429
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/647c6fcddfa84d328d9c51f0294599d0~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 4
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 58722717092
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/8a4dc6f002b545bca632615290f4527d~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 5
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 297
|
||||||
|
2 {
|
||||||
|
1: 52379408873
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/24990023eae5e3325fcc~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 6
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 140
|
||||||
|
2 {
|
||||||
|
1: 57254508132
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/216c00283d70176a9e97~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 7
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 128
|
||||||
|
2 {
|
||||||
|
1: 3056263838569380
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/fe8f000122d925f9a0fb~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 8
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 99
|
||||||
|
2 {
|
||||||
|
1: 23239313505
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/5d4700073713949f592e~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 9
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 35
|
||||||
|
2 {
|
||||||
|
1: 3239311302
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/737/6093229802~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 10
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 30
|
||||||
|
2 {
|
||||||
|
1: 822069738617544
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/2b5f6e3d331443b3bf51875567fa2b5d~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 11
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 22
|
||||||
|
2 {
|
||||||
|
1: 83166975758782
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/0baffeeb3d2d4fa8898b275968f18564~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 12
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 14
|
||||||
|
2 {
|
||||||
|
1: 104729678256
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/db140012b3f29800ab6d~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 13
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: 5538311676
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/dad300141ece34b4e3c7~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 8
|
||||||
|
2 {
|
||||||
|
1: 109675723458
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/9cf549b429f740f6a90c41e4b5b632b9~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 6
|
||||||
|
2 {
|
||||||
|
1: 81425804261
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/9fd60005b91e43cc85e2~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 16
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 5
|
||||||
|
2 {
|
||||||
|
1: 2115111742610984
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/b20c086a5b644a6f919dfdd3dad442e6~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 17
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 3
|
||||||
|
2 {
|
||||||
|
1: 100743319316
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/6d8e7bba2195468fb24a4e3ea7992b92~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 18
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: 51035982268
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/d041e17415bc42c9a9815a8aaa2c3d8b~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 19
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1
|
||||||
|
2 {
|
||||||
|
1: 1772009086784855
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/9fe0aa53dc254c0081a0fc2ce65f1559~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 20
|
||||||
|
}
|
||||||
|
3: 826
|
||||||
|
4: "13\344\270\207\344\272\272\346\260\224"
|
||||||
|
6: 136763
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "6776884008732789507_1577866268700_1_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1577866268700
|
||||||
|
5: "fetch_time:1577866268700|start_time:1577866263586|fetch_id:6776884010443557636|flag:0|seq:22"
|
234
Demo/resulta.txt
Normal file
234
Demo/resulta.txt
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2: 6776963484661500684
|
||||||
|
3: 6776943780420389640
|
||||||
|
4: 1577884770601
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 132
|
||||||
|
2 {
|
||||||
|
1: 3962279791967276
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/278ac6165ba34b7aa371e1df5ea337b3~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 66
|
||||||
|
2 {
|
||||||
|
1: 2933125236921479
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/2e1c9d64f34a4a3e8a326fe5394659fd~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 45
|
||||||
|
2 {
|
||||||
|
1: 50230797308
|
||||||
|
9 {
|
||||||
|
1: "http://p9-xg.bytecdn.cn/thumb/dac400045e7008dbd42d"
|
||||||
|
2: "dac400045e7008dbd42d"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 3
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 5
|
||||||
|
2 {
|
||||||
|
1: 9746464842
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/6ad34237256e4471b16810eb098224c0~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 4
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 5
|
||||||
|
2 {
|
||||||
|
1: 111552853752
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3792/5112637127~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 5
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 3
|
||||||
|
2 {
|
||||||
|
1: 16665341581
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/da80000309bef5b49fa0"
|
||||||
|
2: "da80000309bef5b49fa0"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 6
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 97942455882
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3792/5112637127~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 7
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 97363408846
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/dab00018fc4fda3b5a21"
|
||||||
|
2: "dab00018fc4fda3b5a21"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 8
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 96959753387
|
||||||
|
9 {
|
||||||
|
1: "http://p9-xg.bytecdn.cn/thumb/173b600285dcf9f649150"
|
||||||
|
2: "173b600285dcf9f649150"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 9
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 96119123780
|
||||||
|
9 {
|
||||||
|
1: "http://p9-xg.bytecdn.cn/thumb/241ef00000e3f17f517d7"
|
||||||
|
2: "241ef00000e3f17f517d7"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 10
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 9609510451
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/da51000807963daceae0"
|
||||||
|
2: "da51000807963daceae0"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 11
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 95931639233
|
||||||
|
9 {
|
||||||
|
1: "http://p9-xg.bytecdn.cn/thumb/71a30006cf20be61eb9b"
|
||||||
|
2: "71a30006cf20be61eb9b"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 12
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 94602295110
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/173b70008753becec983c"
|
||||||
|
2: "173b70008753becec983c"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 13
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 94432960458
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3047680722~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 94385438443
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/6593000eb2048e45ee0b"
|
||||||
|
2: "6593000eb2048e45ee0b"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 94193267099
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/da57000b43a72cedd2fc~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 16
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 93948536567
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/fe7300005f28e10f3c52~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 17
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 93175525403
|
||||||
|
9 {
|
||||||
|
1: "http://p9-xg.bytecdn.cn/thumb/da83000d9328094b90d6"
|
||||||
|
2: "da83000d9328094b90d6"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 18
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 93064266997
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/6588002a7fcd121c60f6~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 19
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
2 {
|
||||||
|
1: 92866340217
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3044413937~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 20
|
||||||
|
}
|
||||||
|
3: 365
|
||||||
|
4: "5.6\344\270\207\344\272\272\346\260\224"
|
||||||
|
6: 56661
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "6776963484661500684_1577884771191_6776957423184169736_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1577884771191
|
||||||
|
5: "fetch_time:1577884771191|start_time:1577884288940|fetch_id:6776963481247042317|flag:0|seq:1283"
|
4732
Demo/resultb.txt
Normal file
4732
Demo/resultb.txt
Normal file
File diff suppressed because it is too large
Load Diff
4489
Demo/resultc.txt
Normal file
4489
Demo/resultc.txt
Normal file
File diff suppressed because it is too large
Load Diff
862
Demo/resultfst.txt
Normal file
862
Demo/resultfst.txt
Normal file
@ -0,0 +1,862 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6776965782439283463
|
||||||
|
3: 6776895930592398094
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 1587335753631549
|
||||||
|
3: "\345\260\217\345\244\251\346\211\215\350\264\235\345\243\263"
|
||||||
|
9 {
|
||||||
|
1: "http://p3.pstatp.com/thumb/3793/3131589739"
|
||||||
|
2: "3793/3131589739"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 33
|
||||||
|
2: 2
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAh0jOEAHZj6-a55dwsKu6i0ilHwHcWPx8mLImJ5iDJzfgkYhU0mFv-oLZ6yx6wNi0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1587335753631549
|
||||||
|
3: "\345\260\217\345\244\251\346\211\215\350\264\235\345\243\263"
|
||||||
|
9 {
|
||||||
|
1: "http://p3.pstatp.com/thumb/3793/3131589739"
|
||||||
|
2: "3793/3131589739"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 33
|
||||||
|
2: 2
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAh0jOEAHZj6-a55dwsKu6i0ilHwHcWPx8mLImJ5iDJzfgkYhU0mFv-oLZ6yx6wNi0"
|
||||||
|
}
|
||||||
|
3: 15103
|
||||||
|
10: 1
|
||||||
|
14: "132\344\270\207\344\272\272\346\260\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6776965783190555404
|
||||||
|
3: 6776895930592398094
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 50909397248
|
||||||
|
3: "\347\214\223\347\214\223\347\214\223\345\255\220"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p1.pstatp.com/thumb/96b002412f02c3d2735"
|
||||||
|
2: "96b002412f02c3d2735"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 24
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 5
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAwlVH0meNefJYE9l5cBWj5vZX8ooB9bII44Cf2CRXp9s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 50909397248
|
||||||
|
3: "\347\214\223\347\214\223\347\214\223\345\255\220"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p1.pstatp.com/thumb/96b002412f02c3d2735"
|
||||||
|
2: "96b002412f02c3d2735"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 24
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 5
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_5.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_5.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAwlVH0meNefJYE9l5cBWj5vZX8ooB9bII44Cf2CRXp9s"
|
||||||
|
}
|
||||||
|
3: 15103
|
||||||
|
10: 1
|
||||||
|
14: "132\344\270\207\344\272\272\346\260\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastRoomUserSeqMessage"
|
||||||
|
2: 6776965783814933256
|
||||||
|
3: 6776895930592398094
|
||||||
|
4: 1577885306057
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 2997
|
||||||
|
2 {
|
||||||
|
1: 92747501043
|
||||||
|
2: 517409
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/feaa00016eaa01bf172e~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 2198
|
||||||
|
2 {
|
||||||
|
1: 1182693581391939
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/dae10014972e8d70953e~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1998
|
||||||
|
2 {
|
||||||
|
1: 5981054057
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/75660014ae3215bae055~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 3
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1099
|
||||||
|
2 {
|
||||||
|
1: 3836408254
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/6620/5484795979~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 4
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 999
|
||||||
|
2 {
|
||||||
|
1: 830872766922279
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/5a67caf5ae404432aa0524c33001241c~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 5
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 999
|
||||||
|
2 {
|
||||||
|
1: 7185332641
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/754e3527d08540089a3adf6495845240~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 6
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 93127918477
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3044413937~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 7
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 50073154686
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/da790015e9c75441ff34"
|
||||||
|
2: "da790015e9c75441ff34"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 8
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 520
|
||||||
|
2 {
|
||||||
|
1: 104620584571
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/daa30018abcde9559b55~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 9
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 120
|
||||||
|
2 {
|
||||||
|
1: 5994520551
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/aae5000ffc17e4f1f5da"
|
||||||
|
2: "aae5000ffc17e4f1f5da"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 10
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 100
|
||||||
|
2 {
|
||||||
|
1: 54883854814
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/da68001693847d505008~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 11
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 99
|
||||||
|
2 {
|
||||||
|
1: 82020236564
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/5042000ff6673790f6d2~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 12
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 66
|
||||||
|
2 {
|
||||||
|
1: 3688188102
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/e590005f1b8bdbd812c~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 13
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 38
|
||||||
|
2 {
|
||||||
|
1: 75972230499
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/173b400272ba1269fb7d8~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 20
|
||||||
|
2 {
|
||||||
|
1: 654947037492940
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/2e549000299b4f464f99f~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 17
|
||||||
|
2 {
|
||||||
|
1: 6896749077
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/5046000873dbc5a8f31f~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 16
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 14
|
||||||
|
2 {
|
||||||
|
1: 50569473736
|
||||||
|
9 {
|
||||||
|
1: "http://p3-xg.bytecdn.cn/thumb/5d4b0002a7134afffa47"
|
||||||
|
2: "5d4b0002a7134afffa47"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 17
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 14
|
||||||
|
2 {
|
||||||
|
1: 2581241782866604
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/51c85ec9c5754938b89504217ae5bbbc~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 18
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 13
|
||||||
|
2 {
|
||||||
|
1: 50651928991
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/f81fee15e94a4405acc921916bfaff09~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 19
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: 106001804992
|
||||||
|
9 {
|
||||||
|
1: "http://sf6-ttcdn-tos.pstatp.com/img/mosaic-legacy/fe5f000080632ba520f5~120x256.image"
|
||||||
|
}
|
||||||
|
23: ""
|
||||||
|
}
|
||||||
|
3: 20
|
||||||
|
}
|
||||||
|
3: 15094
|
||||||
|
4: "132\344\270\207\344\272\272\346\260\224"
|
||||||
|
6: 1329944
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2: 6776965784796482315
|
||||||
|
3: 6776895930592398094
|
||||||
|
4: 1577885306078
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 52120728008
|
||||||
|
3: "\346\234\250\345\255\2202910"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p1.pstatp.com/thumb/ef6000df19086df2853"
|
||||||
|
2: "ef6000df19086df2853"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_3.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 65
|
||||||
|
2: 16
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 3
|
||||||
|
19 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_paygrade_level_3.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_3.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&__live_platform__=webcast&type=popup&gravity=bottom&height=400&radius=8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAD4OSjJ5hRbYDzZI0GJT_usTlLPEBYFrtPEYzBwLiIzQ"
|
||||||
|
50 {
|
||||||
|
1 {
|
||||||
|
3: 1008
|
||||||
|
4: 1125
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
3: 105
|
||||||
|
4: 111
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fnoble%2Fnoble_privilege_intro%2Findex.html%3Fforbid_right_back%3D1&type=fullscreen&hide_nav_bar=1&status_bar_color=white&status_bar_bg_color=%2300000000&noble_intercept=1&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
4: "\346\231\256\351\200\232\347\224\250\346\210\267"
|
||||||
|
6 {
|
||||||
|
3: 366
|
||||||
|
4: 615
|
||||||
|
}
|
||||||
|
7 {
|
||||||
|
3: 60
|
||||||
|
4: 108
|
||||||
|
}
|
||||||
|
8 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/noble_boarder.png~tplv-obj.image"
|
||||||
|
2: "webcast/noble_boarder.png"
|
||||||
|
3: 64
|
||||||
|
4: 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: "\350\277\231\346\230\257\345\267\247\345\205\213\345\212\233\345\270\275\345\255\220\357\274\237"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6776965784520887054
|
||||||
|
3: 6776895930592398094
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 71581494772
|
||||||
|
3: "\345\217\253\346\210\221\350\221\211\345\220\214\345\255\246"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3792/5112637127~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 6
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAfgxQATVlN1REs0ezLccSYBNp34sVcfh3EZHMu5Fi8uE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 71581494772
|
||||||
|
3: "\345\217\253\346\210\221\350\221\211\345\220\214\345\255\246"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://sf3-ttcdn-tos.pstatp.com/img/mosaic-legacy/3792/5112637127~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 6
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAfgxQATVlN1REs0ezLccSYBNp34sVcfh3EZHMu5Fi8uE"
|
||||||
|
}
|
||||||
|
3: 15103
|
||||||
|
10: 1
|
||||||
|
14: "132\344\270\207\344\272\272\346\260\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6776965785094048520
|
||||||
|
3: 6776895930592398094
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 6205145196
|
||||||
|
3: "\346\210\221\344\270\215\346\230\257\350\200\201\351\211\204"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/249a001395445a62671d"
|
||||||
|
2: "249a001395445a62671d"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_8.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 15
|
||||||
|
2: 54
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 8
|
||||||
|
19 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_8.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAGMn5pO7qE_ZZu6ETuJmfSW8KLhLOtRkLnr3IiLE2e6A"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 6205145196
|
||||||
|
3: "\346\210\221\344\270\215\346\230\257\350\200\201\351\211\204"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "http://p1-xg.bytecdn.cn/thumb/249a001395445a62671d"
|
||||||
|
2: "249a001395445a62671d"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_8.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 15
|
||||||
|
2: 54
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 8
|
||||||
|
19 {
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/xigua_paygrade_level_8.png~tplv-obj.png"
|
||||||
|
2: "webcast/xigua_paygrade_level_8.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2FhonorLevel%2Findex.html&type=popup&gravity=bottom&height=400&radius=8&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
2: 14
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p9-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-xgcdn.byteimg.com/img/webcast/xigua_fansclub_medal_14.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_14.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAGMn5pO7qE_ZZu6ETuJmfSW8KLhLOtRkLnr3IiLE2e6A"
|
||||||
|
}
|
||||||
|
3: 15103
|
||||||
|
10: 1
|
||||||
|
14: "132\344\270\207\344\272\272\346\260\224"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastFansclubStatisticsMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastFansclubStatisticsMessage"
|
||||||
|
2: 6776950071441869579
|
||||||
|
3: 6776895930592398094
|
||||||
|
4: 1577885306430
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
3: 19325
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastFansclubMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastFansclubMessage"
|
||||||
|
2: 6776950071441885963
|
||||||
|
3: 6776895930592398094
|
||||||
|
4: 1577885306441
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2: 2
|
||||||
|
3: "\346\201\255\345\226\234 \347\210\261\345\220\203\351\261\274\347\232\204\347\213\256\345\255\220\351\270\255 \346\210\220\344\270\272\347\254\25419325\345\220\215\347\262\211\344\270\235\345\233\242\346\210\220\345\221\230"
|
||||||
|
4 {
|
||||||
|
1: 109556646111
|
||||||
|
3: "\347\210\261\345\220\203\351\261\274\347\232\204\347\213\256\345\255\220\351\270\255"
|
||||||
|
9 {
|
||||||
|
1: "http://sf1-ttcdn-tos.pstatp.com/img/tos-cn-i-0022/66d462f176c841a0a4939ad355fe8c00~120x256.image"
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
2: 1
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "https://p1.pstatp.com/obj/webcast/xigua_fansclub_1.png"
|
||||||
|
2: "webcast/xigua_fansclub_1.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\345\270\203\344\270\200\347\217\255"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "6776950071441885963_1577885306619_6776965731513060100_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1577885306619
|
||||||
|
5: "fetch_time:1577885306619|start_time:1577885302380|fetch_id:6776965761064883715|flag:0|seq:387"
|
1036
Demo/v926.txt
Normal file
1036
Demo/v926.txt
Normal file
File diff suppressed because it is too large
Load Diff
256
Demo/v926_fg.txt
Normal file
256
Demo/v926_fg.txt
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastChatMessage"
|
||||||
|
2: 6902669212519992068
|
||||||
|
3: 6902629276546566925
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "webcast_chat_display_text"
|
||||||
|
2: "{0:user}{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#ff36c0cf"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#60000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 5518138898
|
||||||
|
3: "\345\247\232\345\247\232\347\220\263\347\232\2042\345\247\220\345\244\253"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "https://p1-dy.bytexservice.com/img/user-avatar/deb96a5e7e07f60a613531670a570736~300x300.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 13
|
||||||
|
2: 86
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 25
|
||||||
|
19 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: 15
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1: "\010\002\022\342\001\nZhttp://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image\nZhttp://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image\022#webcast/xigua_fansclub_medal_15.png\0300 \226\001"
|
||||||
|
2: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
}
|
||||||
|
6: 61788610240
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32 {
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAKkWCgUKAN3GtNdQ0jqr8zAt3KtIc9kAc1GaJ32VcH3E"
|
||||||
|
54: 3
|
||||||
|
61 {
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 1
|
||||||
|
11: "@\345\247\232\345\256\266\344\272\214\345\247\221\345\207\211 \346\210\221\345\211\215\345\244\251\346\235\245\346\267\261\345\234\263\344\272\206"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11: 31003
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 5518138898
|
||||||
|
3: "\345\247\232\345\247\232\347\220\263\347\232\2042\345\247\220\345\244\253"
|
||||||
|
4: 1
|
||||||
|
9 {
|
||||||
|
1: "https://p1-dy.bytexservice.com/img/user-avatar/deb96a5e7e07f60a613531670a570736~300x300.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 13
|
||||||
|
2: 86
|
||||||
|
3: 2
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 25
|
||||||
|
19 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: 15
|
||||||
|
3: 1
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 2
|
||||||
|
2 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
3: 48
|
||||||
|
4: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
}
|
||||||
|
6: 61788610240
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32 {
|
||||||
|
2: 1
|
||||||
|
}
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAKkWCgUKAN3GtNdQ0jqr8zAt3KtIc9kAc1GaJ32VcH3E"
|
||||||
|
54: 3
|
||||||
|
61 {
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_admin_badge_v2.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_admin_badge_v2.png"
|
||||||
|
3: 16
|
||||||
|
4: 28
|
||||||
|
6: 3
|
||||||
|
}
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p9-webcast-ttcdn.byteimg.com/img/webcast/25_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/25_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast&type=fullscreen"
|
||||||
|
}
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/xigua_fansclub_medal_15.png~tplv-obj.image"
|
||||||
|
2: "webcast/xigua_fansclub_medal_15.png"
|
||||||
|
6: 7
|
||||||
|
8 {
|
||||||
|
1: "\345\247\232\345\247\232\347\220\263"
|
||||||
|
2: "#FFFFFF"
|
||||||
|
3: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: "@\345\247\232\345\256\266\344\272\214\345\247\221\345\207\211 \346\210\221\345\211\215\345\244\251\346\235\245\346\267\261\345\234\263\344\272\206"
|
||||||
|
9 {
|
||||||
|
1 {
|
||||||
|
1: "http://p3-webcast-ttcdn.byteimg.com/img/webcast/userlabel_regular_chat.png~tplv-obj.image"
|
||||||
|
1: "http://p6-webcast-ttcdn.byteimg.com/img/webcast/userlabel_regular_chat.png~tplv-obj.image"
|
||||||
|
2: "webcast/userlabel_regular_chat.png"
|
||||||
|
5: "#E0BCD4"
|
||||||
|
}
|
||||||
|
2: 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: 6902669212519992068
|
||||||
|
}
|
||||||
|
2: "1607153101490_6902670004165030044_6902669995575083008_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1607153101490
|
||||||
|
5: "fetch_time:1607153101490|start_time:0|fetch_id:6902670004165030042|flag:0|seq:2080|next_cursor:1607153101490_6902670004165030044_6902669995575083008_1"
|
364
Demo/v926_leave.txt
Normal file
364
Demo/v926_leave.txt
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
1 {
|
||||||
|
1: "WebcastControlMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastControlMessage"
|
||||||
|
2: 6902672961476774663
|
||||||
|
3: 6902629276546566925
|
||||||
|
4: 1607153789195
|
||||||
|
6: 1
|
||||||
|
}
|
||||||
|
2: 3
|
||||||
|
}
|
||||||
|
3: 6902672961476774663
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6902672961728662285
|
||||||
|
3: 6902629276546566925
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 2638466963214383
|
||||||
|
2: 1520817
|
||||||
|
3: "\350\213\261\345\256\207girl"
|
||||||
|
9 {
|
||||||
|
1: "https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/a15266741ef770c810e18e5e6d073da9~300x300.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 60
|
||||||
|
2: 120
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 3
|
||||||
|
19 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1: "\010\000\022\000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "1520817"
|
||||||
|
46: "MS4wLjABAAAATNQnQSVI6ePiovK48LHJHvefLO_4RAmla1Hkn0GYTWc8oE5u0a0VZnmPM3VKnaSh"
|
||||||
|
54: 3
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
9: 1
|
||||||
|
10: 1
|
||||||
|
11: 42000
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 2638466963214383
|
||||||
|
2: 1520817
|
||||||
|
3: "\350\213\261\345\256\207girl"
|
||||||
|
9 {
|
||||||
|
1: "https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/a15266741ef770c810e18e5e6d073da9~300x300.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 60
|
||||||
|
2: 120
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 3
|
||||||
|
19 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "1520817"
|
||||||
|
46: "MS4wLjABAAAATNQnQSVI6ePiovK48LHJHvefLO_4RAmla1Hkn0GYTWc8oE5u0a0VZnmPM3VKnaSh"
|
||||||
|
54: 3
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: 31
|
||||||
|
10: 1
|
||||||
|
14: "0\344\272\272"
|
||||||
|
18 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 2638466963214383
|
||||||
|
2: 1520817
|
||||||
|
3: "\350\213\261\345\256\207girl"
|
||||||
|
9 {
|
||||||
|
1: "https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/a15266741ef770c810e18e5e6d073da9~300x300.image"
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 60
|
||||||
|
2: 120
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
6: 3
|
||||||
|
19 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "1520817"
|
||||||
|
46: "MS4wLjABAAAATNQnQSVI6ePiovK48LHJHvefLO_4RAmla1Hkn0GYTWc8oE5u0a0VZnmPM3VKnaSh"
|
||||||
|
54: 3
|
||||||
|
61 {
|
||||||
|
1: "http://p1-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
1: "http://p3-webcast-xgcdn.byteimg.com/img/webcast/3_xigua_honor_level.png~tplv-obj.png"
|
||||||
|
2: "webcast/3_xigua_honor_level.png"
|
||||||
|
3: 16
|
||||||
|
4: 30
|
||||||
|
6: 1
|
||||||
|
7: "sslocal://webcast_webview?url=https%3A%2F%2Fwebcast.ixigua.com%2Ffalcon%2Fwebcast_xigua%2Fpage%2Fhonor_level%2Fuser%2Findex.html&type=fullscreen&hide_nav_bar=1&hide_status_bar=0&__live_platform__=webcast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: 6902672961728662285
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2 {
|
||||||
|
1 {
|
||||||
|
1: "WebcastMemberMessage"
|
||||||
|
2: 6902672961866681091
|
||||||
|
3: 6902629276546566925
|
||||||
|
6: 1
|
||||||
|
8 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 1015537608169303
|
||||||
|
3: "\347\224\250\346\210\267525366763846"
|
||||||
|
9 {
|
||||||
|
1: "https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 31
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1: "\010\000\022\000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAXDp4yUHFF_sA3Uf9T4OPkW0dk-9SUYxbFNFrs7CcyhAcjYzdsYFYE5vuUdaHbo9R"
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
9: 1
|
||||||
|
10: 1
|
||||||
|
11: 42000
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
1: 1015537608169303
|
||||||
|
3: "\347\224\250\346\210\267525366763846"
|
||||||
|
9 {
|
||||||
|
1: "https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 31
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAXDp4yUHFF_sA3Uf9T4OPkW0dk-9SUYxbFNFrs7CcyhAcjYzdsYFYE5vuUdaHbo9R"
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
10: 1
|
||||||
|
14: "0\344\272\272"
|
||||||
|
18 {
|
||||||
|
1: "live_room_enter_toast"
|
||||||
|
2: "{0:user} \346\235\245\344\272\206{1:string}"
|
||||||
|
3 {
|
||||||
|
1: "#de000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
4 {
|
||||||
|
1: 11
|
||||||
|
2 {
|
||||||
|
1: "#61000000"
|
||||||
|
4: 400
|
||||||
|
}
|
||||||
|
21 {
|
||||||
|
1 {
|
||||||
|
1: 1015537608169303
|
||||||
|
3: "\347\224\250\346\210\267525366763846"
|
||||||
|
9 {
|
||||||
|
1: "https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3791/5070639578~120x256.image"
|
||||||
|
}
|
||||||
|
22 {
|
||||||
|
1: 31
|
||||||
|
}
|
||||||
|
23 {
|
||||||
|
19: ""
|
||||||
|
}
|
||||||
|
24 {
|
||||||
|
1 {
|
||||||
|
4 {
|
||||||
|
1 {
|
||||||
|
1: 0
|
||||||
|
2: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32: ""
|
||||||
|
38: "0"
|
||||||
|
46: "MS4wLjABAAAAXDp4yUHFF_sA3Uf9T4OPkW0dk-9SUYxbFNFrs7CcyhAcjYzdsYFYE5vuUdaHbo9R"
|
||||||
|
54: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3: 6902672961866681091
|
||||||
|
}
|
||||||
|
2: "1607153789923_6902672963397497753_6902669995575083008_1"
|
||||||
|
3: 1000
|
||||||
|
4: 1607153789923
|
||||||
|
5: "fetch_time:1607153789923|start_time:0|fetch_id:6902672959102530453|flag:0|seq:2684|next_cursor:1607153789923_6902672963397497753_6902669995575083008_1"
|
48
Gift.py
48
Gift.py
@ -1,48 +0,0 @@
|
|||||||
import requests
|
|
||||||
from User import User
|
|
||||||
|
|
||||||
|
|
||||||
class Gift:
|
|
||||||
ID:int = 0
|
|
||||||
count:int = 0
|
|
||||||
roomID:int = 0
|
|
||||||
giftList:dict = {10001: {"Name": "西瓜", "Price": 0}}
|
|
||||||
amount:int = 0
|
|
||||||
user:User = None
|
|
||||||
|
|
||||||
def __init__(self, json=None):
|
|
||||||
if json:
|
|
||||||
self.parse(json)
|
|
||||||
|
|
||||||
def parse(self, json):
|
|
||||||
self.user = User(json)
|
|
||||||
if "Msg" in json:
|
|
||||||
if "present_end_info" in json["Msg"]:
|
|
||||||
self.ID = json["Msg"]['present_end_info']['id']
|
|
||||||
self.count = json["Msg"]['present_end_info']['count']
|
|
||||||
elif "present_info" in json["Msg"]:
|
|
||||||
self.ID = json["Msg"]['present_info']['id']
|
|
||||||
self.count = json["Msg"]['present_info']['repeat_count']
|
|
||||||
if self.ID in self.giftList:
|
|
||||||
self.amount = self.giftList[self.ID]["Price"] * self.count
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def update(roomID):
|
|
||||||
Gift.roomID = roomID
|
|
||||||
p = requests.get("https://live.ixigua.com/api/gifts/{roomID}".format(roomID= roomID))
|
|
||||||
d = p.json()
|
|
||||||
if isinstance(d, int) or "data" not in d:
|
|
||||||
print("错误:礼物更新失败")
|
|
||||||
else:
|
|
||||||
for i in d["data"]:
|
|
||||||
Gift.giftList[i["ID"]] = {"Name": i["Name"], "Price": i["DiamondCount"]}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.ID in self.giftList:
|
|
||||||
giftN = self.giftList[self.ID]["Name"]
|
|
||||||
else:
|
|
||||||
giftN = "未知礼物[{}]".format(self.ID)
|
|
||||||
return "{user} 送出的 {count} 个 {name}".format(user= self.user, count= self.count, name= giftN)
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.__str__()
|
|
13
LICENSE
Normal file
13
LICENSE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
33
README.md
33
README.md
@ -1,8 +1,31 @@
|
|||||||
# XiguaLiveDanmakuHelper
|
# XiguaLiveDanmakuHelper
|
||||||
### 西瓜直播弹幕助手
|
|
||||||
|
|
||||||
因个人能力有限,不懂C#,无法做出界面版,只好用控制台版先顶着
|
## 现在西瓜视频搜索接口无法使用,建议开发者自己找到自己的用户ID,写死加载即可
|
||||||
|
|
||||||
### 计划更新:
|
### 因西瓜直播弹幕接口换成了ProtoBuf,已经尝试解析出了部分proto
|
||||||
- 使用android app协议,避免出现网页版协议更改后无法使用
|
|
||||||
- 闲的无聊的时候看一看有没有好用的GUI轮子可以用用
|
### 从安卓9.4版本后 *(大概是)* 发现需要连接Websocket才能获取弹幕,且又是魔改protobuf(搞不懂),手动断开Websocket后才会轮询请求
|
||||||
|
|
||||||
|
### ~~西瓜直播弹幕助手--界面版~~
|
||||||
|
|
||||||
|
> 界面版:[q792602257/XiguaDanmakuHelperGUI](https://github.com/q792602257/XiguaDanmakuHelperGUI "C# ver")
|
||||||
|
> #### 该项目已经荒废,除非你知道如何开发,否则不建议使用
|
||||||
|
|
||||||
|
### 西瓜直播弹幕接口```api.py```
|
||||||
|
|
||||||
|
> - 基于安卓9.6.6(96615)
|
||||||
|
|
||||||
|
### 西瓜直播弹幕助手--礼物端```WinMain.py```
|
||||||
|
|
||||||
|
### 西瓜直播弹幕助手--录播端```WebMain.py```
|
||||||
|
|
||||||
|
> - 能够自动进行ffmpeg转码
|
||||||
|
> - 转码后自动上传至B站
|
||||||
|
> - 顺便还能自己清理录播的文件(移动到一个位置,执行shell命令,上传百度云)
|
||||||
|
> - 把录像文件分一定大小保存(B站有限制,但是不知道是多少)
|
||||||
|
> - 少部分错误包容机制
|
||||||
|
> - 有一个简单的WEB页面,及简单的控制接口
|
||||||
|
|
||||||
|
### ~~计划更新~~
|
||||||
|
|
||||||
|
### 随缘更新
|
||||||
|
40
Struct/Chat.py
Normal file
40
Struct/Chat.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from .User import User
|
||||||
|
from .Lottery import Lottery
|
||||||
|
from XiguaMessage_pb2 import ChatMessage
|
||||||
|
|
||||||
|
class Chat:
|
||||||
|
content = ""
|
||||||
|
user = None
|
||||||
|
filterString = ["", ]
|
||||||
|
isFiltered = False
|
||||||
|
|
||||||
|
def __init__(self, json=None, lottery: Lottery = None):
|
||||||
|
if lottery:
|
||||||
|
self.filterString.append(lottery.content)
|
||||||
|
if json:
|
||||||
|
if type(json) == bytes:
|
||||||
|
self.parsePb(json)
|
||||||
|
else:
|
||||||
|
self.parse(json)
|
||||||
|
|
||||||
|
def parsePb(self, raw):
|
||||||
|
_message = ChatMessage()
|
||||||
|
_message.ParseFromString(raw)
|
||||||
|
self.user = User(_message.user)
|
||||||
|
self.content = _message.content
|
||||||
|
if self.content in self.filterString:
|
||||||
|
self.isFiltered = True
|
||||||
|
|
||||||
|
def parse(self, json):
|
||||||
|
self.user = User(json)
|
||||||
|
if "extra" in json:
|
||||||
|
if "content" in json["extra"]:
|
||||||
|
self.content = json["extra"]['content']
|
||||||
|
if self.content in self.filterString:
|
||||||
|
self.isFiltered = True
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{} : {}".format(self.user, self.content)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.__str__()
|
0
Struct/Digg.py
Normal file
0
Struct/Digg.py
Normal file
73
Struct/Gift.py
Normal file
73
Struct/Gift.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import requests
|
||||||
|
from .User import User
|
||||||
|
from XiguaMessage_pb2 import GiftMessage
|
||||||
|
|
||||||
|
|
||||||
|
class Gift:
|
||||||
|
giftList = {}
|
||||||
|
|
||||||
|
def __init__(self, json=None):
|
||||||
|
self.ID = 0
|
||||||
|
self.count = 0
|
||||||
|
self.user = None
|
||||||
|
self.isFinished = False
|
||||||
|
self.backupName = None
|
||||||
|
if json:
|
||||||
|
if type(json) == bytes:
|
||||||
|
self.parsePb(json)
|
||||||
|
else:
|
||||||
|
self.parse(json)
|
||||||
|
|
||||||
|
def parsePb(self, raw):
|
||||||
|
_message = GiftMessage()
|
||||||
|
_message.ParseFromString(raw)
|
||||||
|
self.user = User(_message.user)
|
||||||
|
self.ID = _message.giftId
|
||||||
|
self.count = _message.repeated
|
||||||
|
self.isFinished = _message.isFinished
|
||||||
|
self.backupName = _message.commonInfo.displayText.params.gifts.gift.name
|
||||||
|
|
||||||
|
def parse(self, json):
|
||||||
|
self.user = User(json)
|
||||||
|
if "extra" in json and json["extra"] is not None:
|
||||||
|
if "present_info" in json["extra"] and json["extra"]['present_info'] is not None:
|
||||||
|
self.ID = int(json["extra"]['present_info']['id'])
|
||||||
|
self.count = json["extra"]['present_info']['repeat_count']
|
||||||
|
elif "present_end_info" in json["extra"] and json["extra"]['present_end_info'] is not None:
|
||||||
|
self.ID = int(json["extra"]['present_end_info']['id'])
|
||||||
|
self.count = json["extra"]['present_end_info']['count']
|
||||||
|
|
||||||
|
def isAnimate(self):
|
||||||
|
if self.ID != 0 and self.ID in self.giftList:
|
||||||
|
if 'combo' in self.giftList[self.ID]:
|
||||||
|
return self.giftList[self.ID]["combo"] == False
|
||||||
|
elif 'meta' in self.giftList[self.ID] and 'combo' in self.giftList[self.ID]['meta']:
|
||||||
|
return self.giftList[self.ID]['meta']["combo"] == False
|
||||||
|
elif 'type' in self.giftList[self.ID]:
|
||||||
|
return self.giftList[self.ID]["type"] == 2
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
if self.ID in self.giftList:
|
||||||
|
return self.giftList[self.ID]["name"]
|
||||||
|
elif self.backupName is not None:
|
||||||
|
return self.backupName
|
||||||
|
else:
|
||||||
|
return "未知礼物[{}]".format(self.ID)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{user} 送出的 {count} 个 {name}".format(user=self.user, count=self.count, name=self.name)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "西瓜礼物【{}(ID:{})】".format(self.name, self.ID)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def addGift(cls, _gift):
|
||||||
|
if 'id' not in _gift:
|
||||||
|
return
|
||||||
|
_id = int(_gift["id"])
|
||||||
|
cls.giftList[_id] = _gift
|
71
Struct/Lottery.py
Normal file
71
Struct/Lottery.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
from .LuckyUser import LuckyUser
|
||||||
|
|
||||||
|
|
||||||
|
class Lottery:
|
||||||
|
ID = 0
|
||||||
|
isActive = False
|
||||||
|
content = ""
|
||||||
|
isFinished = False
|
||||||
|
luckyUsers = []
|
||||||
|
joinedUserCount = 0
|
||||||
|
prizeName = ""
|
||||||
|
finish = 0
|
||||||
|
|
||||||
|
def __init__(self, json=None):
|
||||||
|
if json:
|
||||||
|
self.parse(json)
|
||||||
|
|
||||||
|
def parse(self, json):
|
||||||
|
if "lottery_info" in json and json["lottery_info"] is not None:
|
||||||
|
self.isActive = int(json["lottery_info"]["status"]) > 0
|
||||||
|
self.ID = json["lottery_info"]["lottery_id"]
|
||||||
|
for i in json["lottery_info"]['conditions']:
|
||||||
|
if i['type'] != 3:
|
||||||
|
continue
|
||||||
|
self.content = i["content"]
|
||||||
|
self.joinedUserCount = int(json["lottery_info"]["candidate_num"])
|
||||||
|
self.prizeName = json["lottery_info"]["prize_info"]["name"]
|
||||||
|
_delta = int(json["lottery_info"]["draw_time"]) - int(json["lottery_info"]["current_time"])
|
||||||
|
self.finish = time.time()+_delta+1
|
||||||
|
elif "extra" in json and json["extra"] is not None:
|
||||||
|
if "lottery_info" in json["extra"] and json["extra"]["lottery_info"] is not None:
|
||||||
|
return self.parse(json["extra"])
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if self.isActive:
|
||||||
|
if not self.isFinished and self.finish > time.time():
|
||||||
|
self.checkFinished()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def checkFinished(self):
|
||||||
|
p = requests.get("https://i.snssdk.com/videolive/lottery/check_user_right?lottery_id={}"
|
||||||
|
"&version_code=730&device_platform=android".format(
|
||||||
|
self.ID
|
||||||
|
))
|
||||||
|
d = p.json()
|
||||||
|
if d["base_resp"]["status_code"] != 0:
|
||||||
|
self.isActive = False
|
||||||
|
self.isFinished = False
|
||||||
|
return
|
||||||
|
self.isActive = int(d["lottery_info"]["status"]) > 0
|
||||||
|
self.isFinished = int(d["lottery_info"]["status"]) == 2
|
||||||
|
self.joinedUserCount = int(d["lottery_info"]["candidate_num"])
|
||||||
|
if self.isFinished:
|
||||||
|
self.luckyUsers = [ LuckyUser(i) for i in d["lottery_info"]["lucky_users"] ]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.isFinished:
|
||||||
|
ret = "恭喜以下中奖用户:\n"
|
||||||
|
for i in self.luckyUsers:
|
||||||
|
ret += "> {} {}\n".format(i,self.prizeName)
|
||||||
|
ret += "> 参与人数:{}".format(self.joinedUserCount)
|
||||||
|
return ret
|
||||||
|
elif self.isActive:
|
||||||
|
return "正在抽奖中。。。\n" \
|
||||||
|
"> 参与人数:{}".format(self.joinedUserCount)
|
||||||
|
else:
|
||||||
|
return "抽奖已失效"
|
19
Struct/LuckyUser.py
Normal file
19
Struct/LuckyUser.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from .User import User
|
||||||
|
|
||||||
|
class LuckyUser:
|
||||||
|
|
||||||
|
user = None
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
def __init__(self, json=None):
|
||||||
|
if json:
|
||||||
|
self.parse(json)
|
||||||
|
|
||||||
|
def parse(self, json):
|
||||||
|
self.user = User()
|
||||||
|
self.user.ID = json['user_id']
|
||||||
|
self.user.name = json['user_name']
|
||||||
|
self.count = int(json["grant_count"])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "用户 {} 获得了 {} 个".format(self.user,self.count)
|
@ -1,10 +1,10 @@
|
|||||||
from User import User
|
from .User import User
|
||||||
|
|
||||||
|
|
||||||
class MemberMsg:
|
class MemberMsg:
|
||||||
type:int = 0
|
type = 0
|
||||||
content:str = ""
|
content = ""
|
||||||
user:User = None
|
user = None
|
||||||
|
|
||||||
def __init__(self, json=None):
|
def __init__(self, json=None):
|
||||||
if json:
|
if json:
|
||||||
@ -12,11 +12,11 @@ class MemberMsg:
|
|||||||
|
|
||||||
def parse(self, json):
|
def parse(self, json):
|
||||||
self.user = User(json)
|
self.user = User(json)
|
||||||
if "Msg" in json:
|
if "extra" in json:
|
||||||
if "action" in json["Msg"]:
|
if "action" in json["extra"]:
|
||||||
self.type = json["Msg"]['action']
|
self.type = json["extra"]['action']
|
||||||
elif "content" in json["Msg"]:
|
elif "content" in json["extra"]:
|
||||||
self.content = json["Msg"]['content']
|
self.content = json["extra"]['content']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.type == 3:
|
if self.type == 3:
|
||||||
@ -28,6 +28,8 @@ class MemberMsg:
|
|||||||
elif self.type == 1:
|
elif self.type == 1:
|
||||||
return "{} 进入了房间".format(self.user)
|
return "{} 进入了房间".format(self.user)
|
||||||
else:
|
else:
|
||||||
|
if self.content == "":
|
||||||
|
return "未知消息{} 关于用户 {}".format(self.type, self.user)
|
||||||
return self.content.format(self.user)
|
return self.content.format(self.user)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
77
Struct/User.py
Normal file
77
Struct/User.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
from XiguaUser_pb2 import User as UserPb
|
||||||
|
|
||||||
|
|
||||||
|
class User:
|
||||||
|
def __init__(self, json=None):
|
||||||
|
self.ID = 0
|
||||||
|
self.name = ""
|
||||||
|
self.brand = ""
|
||||||
|
self.level = 0
|
||||||
|
self.type = 0
|
||||||
|
self.block = False
|
||||||
|
self.mute = False
|
||||||
|
if json:
|
||||||
|
if type(json) == bytes:
|
||||||
|
self.parsePb(json)
|
||||||
|
elif type(json) == UserPb:
|
||||||
|
self.parseUserPb(json)
|
||||||
|
else:
|
||||||
|
self.parse(json)
|
||||||
|
|
||||||
|
def parseUserPb(self, _user):
|
||||||
|
self.ID = _user.id
|
||||||
|
self.name = _user.nickname
|
||||||
|
self.brand = _user.fansClub.fansClub.title
|
||||||
|
self.level = _user.fansClub.fansClub.level
|
||||||
|
|
||||||
|
def parsePb(self, raw):
|
||||||
|
_user = UserPb()
|
||||||
|
_user.ParseFromString(raw)
|
||||||
|
self.parseUserPb(_user)
|
||||||
|
|
||||||
|
def parse(self, json):
|
||||||
|
if "extra" in json:
|
||||||
|
if "user" in json["extra"] and json["extra"]["user"] is not None:
|
||||||
|
self.ID = json["extra"]['user']['user_id']
|
||||||
|
self.name = json["extra"]['user']['name']
|
||||||
|
if "im_discipulus_info" in json["extra"] and json["extra"]["im_discipulus_info"] is not None:
|
||||||
|
self.level = json["extra"]["im_discipulus_info"]["level"]
|
||||||
|
self.brand = json["extra"]["im_discipulus_info"]["discipulus_group_title"]
|
||||||
|
if "user_room_auth_status" in json["extra"] and json["extra"]["user_room_auth_status"] is not None:
|
||||||
|
self.type = json["extra"]["user_room_auth_status"]["user_type"]
|
||||||
|
self.block = json["extra"]["user_room_auth_status"]["is_block"]
|
||||||
|
self.mute = json["extra"]["user_room_auth_status"]["is_silence"]
|
||||||
|
if "user_info" in json and json["user_info"] is not None:
|
||||||
|
self.ID = json['user_info']['user_id']
|
||||||
|
self.name = json['user_info']['name']
|
||||||
|
if "anchor" in json and json["anchor"] is not None:
|
||||||
|
if "user_info" in json["anchor"] and json["anchor"]['user_info'] is not None:
|
||||||
|
self.ID = json["anchor"]['user_info']['user_id']
|
||||||
|
self.name = json["anchor"]['user_info']['name']
|
||||||
|
if "user_id" in json:
|
||||||
|
self.ID = json["user_id"]
|
||||||
|
if "user_name" in json:
|
||||||
|
self.name = json["user_name"]
|
||||||
|
if self.type is None:
|
||||||
|
self.type = 0
|
||||||
|
if isinstance(self.level, str):
|
||||||
|
self.level = int(self.level)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.level == 0:
|
||||||
|
if self.type == 1:
|
||||||
|
return "[房管]{}".format(self.name)
|
||||||
|
elif self.type == 3:
|
||||||
|
return "[主播]{}".format(self.name)
|
||||||
|
else:
|
||||||
|
return "{}".format(self.name)
|
||||||
|
else:
|
||||||
|
if self.type != 0:
|
||||||
|
return "[{}{}]{}".format(self.brand, self.level, self.name)
|
||||||
|
return "<{}{}>{}".format(self.brand, self.level, self.name)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "西瓜用户【{}(ID:{})】".format(self.name, self.ID)
|
42
User.py
42
User.py
@ -1,42 +0,0 @@
|
|||||||
class User:
|
|
||||||
ID: int = 0
|
|
||||||
name: str = ""
|
|
||||||
brand: str = ""
|
|
||||||
level: int = 0
|
|
||||||
type: int = 0
|
|
||||||
|
|
||||||
def __init__(self, json=None):
|
|
||||||
if json:
|
|
||||||
self.parse(json)
|
|
||||||
|
|
||||||
def parse(self, json):
|
|
||||||
if "Msg" in json:
|
|
||||||
if "user" in json["Msg"]:
|
|
||||||
self.ID = json["Msg"]['user']['user_id']
|
|
||||||
self.name = json["Msg"]['user']['name']
|
|
||||||
if "discipulus_info" in json["Msg"]:
|
|
||||||
self.level = json["Msg"]["discipulus_info"]["level"]
|
|
||||||
self.brand = json["Msg"]["discipulus_info"]["discipulus_group_title"]
|
|
||||||
elif "data" in json:
|
|
||||||
if "anchorInfo" in json["data"]:
|
|
||||||
self.ID = json["data"]['anchorInfo']['id']
|
|
||||||
self.name = json["data"]['anchorInfo']['name']
|
|
||||||
if self.type is None:
|
|
||||||
self.type = 0
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.level == 0:
|
|
||||||
if self.type == 1:
|
|
||||||
return "[房管]{}".format(self.name)
|
|
||||||
elif self.type == 3:
|
|
||||||
return "[主播]{}".format(self.name)
|
|
||||||
else:
|
|
||||||
return "{}".format(self.name)
|
|
||||||
else:
|
|
||||||
if self.type != 0:
|
|
||||||
return "[{}{}]{}".format(self.brand, self.level, self.name)
|
|
||||||
return "<{}{}>{}".format(self.brand,self.level,self.name)
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
198
WebMain.py
Normal file
198
WebMain.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from time import sleep
|
||||||
|
from flask_cors import CORS
|
||||||
|
from flask import Flask, jsonify, request, render_template, Response, send_file
|
||||||
|
import Common
|
||||||
|
import threading
|
||||||
|
from liveDownloader import run as RUN
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['JSON_AS_ASCII'] = False
|
||||||
|
CORS(app, supports_credentials=True)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/config", methods=["GET"])
|
||||||
|
def readConfig():
|
||||||
|
config = Common.config.copy()
|
||||||
|
return jsonify(config)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/config", methods=["POST"])
|
||||||
|
def writeConfig():
|
||||||
|
# TODO : 完善
|
||||||
|
Common.appendOperation("更新配置")
|
||||||
|
Common.reloadConfig()
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": request.form})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/not/upload", methods=["POST"])
|
||||||
|
def toggleForceNotUpload():
|
||||||
|
Common.forceNotUpload = not Common.forceNotUpload
|
||||||
|
Common.appendOperation("将强制不上传的值改为:{}".format(Common.forceNotUpload))
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"forceNotUpload": Common.forceNotUpload,
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/not/encode", methods=["POST"])
|
||||||
|
def toggleForceNotEncode():
|
||||||
|
Common.forceNotEncode = not Common.forceNotEncode
|
||||||
|
Common.appendOperation("将强制不编码的值改为:{}".format(Common.forceNotEncode))
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"forceNotEncode": Common.forceNotEncode,
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/not/download", methods=["POST"])
|
||||||
|
def toggleForceNotDownload():
|
||||||
|
Common.forceNotDownload = not Common.forceNotDownload
|
||||||
|
Common.appendOperation("将强制不下载的值改为:{}".format(Common.forceNotDownload))
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"forceNotDownload": Common.forceNotDownload,
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/not/broadcast", methods=["POST"])
|
||||||
|
def toggleForceNotBroadcast():
|
||||||
|
Common.forceNotBroadcasting = not Common.forceNotBroadcasting
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"forceNotBroadcasting": Common.forceNotBroadcasting,
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/start/encode", methods=["POST"])
|
||||||
|
def toggleForceStartEncodeThread():
|
||||||
|
Common.forceStartEncodeThread = True
|
||||||
|
Common.appendOperation("强制运行编码线程")
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/start/upload", methods=["POST"])
|
||||||
|
def toggleForceStartUploadThread():
|
||||||
|
Common.forceStartUploadThread = True
|
||||||
|
Common.appendOperation("强制运行上传线程")
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/force/start/clean", methods=["POST"])
|
||||||
|
def startForceCleanDisk():
|
||||||
|
Common.doClean(True)
|
||||||
|
Common.appendOperation("强制执行清理程序")
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/encode/insert", methods=["POST"])
|
||||||
|
def insertEncode():
|
||||||
|
if "filename" in request.form and os.path.exists(request.form["filename"]):
|
||||||
|
Common.appendOperation("添加编码文件:{}".format(request.form["filename"]))
|
||||||
|
Common.encodeQueue.put(request.form["filename"])
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0})
|
||||||
|
else:
|
||||||
|
return jsonify({"message": "no filename specific", "code": 400, "status": 1})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/upload/insert", methods=["POST"])
|
||||||
|
def insertUpload():
|
||||||
|
if "filename" in request.form and os.path.exists(request.form["filename"]):
|
||||||
|
Common.appendOperation("添加上传文件:{}".format(request.form["filename"]))
|
||||||
|
Common.uploadQueue.put(request.form["filename"])
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0})
|
||||||
|
else:
|
||||||
|
return jsonify({"message": "no filename specific", "code": 400, "status": 1})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/upload/discard", methods=["POST"])
|
||||||
|
def discardUpload():
|
||||||
|
Common.uploadQueue.empty()
|
||||||
|
Common.b.clear()
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/upload/finish", methods=["POST"])
|
||||||
|
def finishUpload():
|
||||||
|
Common.appendOperation("设置当前已完成上传")
|
||||||
|
Common.uploadQueue.put(True)
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/stats", methods=["GET"])
|
||||||
|
def getAllStats():
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": Common.collectInfomation()})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/stats/device", methods=["GET"])
|
||||||
|
def getDeviceStatus():
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"status": Common.getCurrentStatus(),
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/stats/config", methods=["GET"])
|
||||||
|
def getConfigStats():
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {
|
||||||
|
"config": {
|
||||||
|
"forceNotBroadcasting": Common.forceNotBroadcasting,
|
||||||
|
"forceNotDownload": Common.forceNotDownload,
|
||||||
|
"forceNotUpload": Common.forceNotUpload,
|
||||||
|
"forceNotEncode": Common.forceNotEncode,
|
||||||
|
"downloadOnly": Common.config['dlO'],
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/account/reLogin", methods=["POST"])
|
||||||
|
def accountRelogin():
|
||||||
|
res = Common.loginBilibili(True)
|
||||||
|
return jsonify({"message": "ok", "code": 200, "status": 0, "data": {"result": res}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/files/", methods=["GET"])
|
||||||
|
def fileIndex():
|
||||||
|
a = []
|
||||||
|
for i in (glob("*.mp4") + glob("*.flv")):
|
||||||
|
a.append({
|
||||||
|
"name": i,
|
||||||
|
"size": Common.parseSize(os.path.getsize(i))
|
||||||
|
})
|
||||||
|
return render_template("files.html", files=a)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/files/download/<path>", methods=["GET"])
|
||||||
|
def fileDownload(path):
|
||||||
|
if not (".mp4" in path or ".flv" in path):
|
||||||
|
return Response(status=404)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return send_file(path, as_attachment=True)
|
||||||
|
else:
|
||||||
|
return Response(status=404)
|
||||||
|
|
||||||
|
|
||||||
|
def SubThread():
|
||||||
|
t = threading.Thread(target=RUN, args=())
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
while True:
|
||||||
|
if t.is_alive():
|
||||||
|
sleep(240)
|
||||||
|
else:
|
||||||
|
t = threading.Thread(target=RUN, args=())
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
|
||||||
|
if not app.debug:
|
||||||
|
p = threading.Thread(target=SubThread)
|
||||||
|
p.setDaemon(True)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
130
WinMain.py
130
WinMain.py
@ -2,24 +2,28 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from Gift import Gift
|
import requests
|
||||||
from MemberMsg import MemberMsg
|
|
||||||
from User import User
|
|
||||||
|
|
||||||
from Chat import Chat
|
from Struct.MemberMsg import MemberMsg
|
||||||
|
from Struct.User import User
|
||||||
|
from Struct.Gift import Gift
|
||||||
|
from Struct.Chat import Chat
|
||||||
|
from Struct.Lottery import Lottery
|
||||||
from api import XiGuaLiveApi as Api
|
from api import XiGuaLiveApi as Api
|
||||||
|
from api import public_hello
|
||||||
import msvcrt
|
import msvcrt
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
||||||
SHOW_ALL = False
|
SHOW_ALL = False
|
||||||
|
|
||||||
|
|
||||||
def readInput(caption, default, timeout: int = 5):
|
def readInput(caption, default, timeout: int = 5):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
print('{}({})\r\n>'.format(caption, default), end="")
|
print('{}({})\r\n>'.format(caption, default), end="")
|
||||||
input = ''
|
input = ''
|
||||||
while True:
|
while True:
|
||||||
if msvcrt.kbhit():
|
if msvcrt.kbhit():
|
||||||
chr = msvcrt.getche()
|
chr = msvcrt.getwche()
|
||||||
if ord(chr) == 13: # enter_key
|
if ord(chr) == 13: # enter_key
|
||||||
break
|
break
|
||||||
elif ord(chr) == 27:
|
elif ord(chr) == 27:
|
||||||
@ -28,11 +32,15 @@ def readInput(caption, default, timeout: int = 5):
|
|||||||
if input != "":
|
if input != "":
|
||||||
input = input[:-1]
|
input = input[:-1]
|
||||||
msvcrt.putch(b" ")
|
msvcrt.putch(b" ")
|
||||||
|
msvcrt.putch(b" ")
|
||||||
|
msvcrt.putch(b"\b")
|
||||||
msvcrt.putch(b"\b")
|
msvcrt.putch(b"\b")
|
||||||
if len(input) == 0:
|
if len(input) == 0:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
elif 32 <= ord(chr) <= 126: # space_char
|
elif 32 > ord(chr) or 255 > ord(chr) > 126: # space_char
|
||||||
input += chr.decode("utf8")
|
continue
|
||||||
|
else:
|
||||||
|
input += chr
|
||||||
if len(input) == 0 and (time.time() - start_time) > timeout:
|
if len(input) == 0 and (time.time() - start_time) > timeout:
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -70,8 +78,9 @@ FOREGROUND_YELLOW = 0x0e # yellow.
|
|||||||
FOREGROUND_WHITE = 0x0f # white.
|
FOREGROUND_WHITE = 0x0f # white.
|
||||||
|
|
||||||
# Windows CMD命令行 背景颜色定义 background colors
|
# Windows CMD命令行 背景颜色定义 background colors
|
||||||
BACKGROUND_BLUE = 0x10 # dark blue.
|
BACKGROUND_BLACK = 0x00 # dark blue.
|
||||||
BACKGROUND_GREEN = 0x20 # dark green.
|
BACKGROUND_DARKBLUE = 0x10 # dark blue.
|
||||||
|
BACKGROUND_DARKGREEN = 0x20 # dark green.
|
||||||
BACKGROUND_DARKSKYBLUE = 0x30 # dark skyblue.
|
BACKGROUND_DARKSKYBLUE = 0x30 # dark skyblue.
|
||||||
BACKGROUND_DARKRED = 0x40 # dark red.
|
BACKGROUND_DARKRED = 0x40 # dark red.
|
||||||
BACKGROUND_DARKPINK = 0x50 # dark pink.
|
BACKGROUND_DARKPINK = 0x50 # dark pink.
|
||||||
@ -93,7 +102,7 @@ def set_cmd_text_color(color, handle=std_out_handle):
|
|||||||
|
|
||||||
|
|
||||||
def resetColor():
|
def resetColor():
|
||||||
set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_WHITE)
|
||||||
|
|
||||||
|
|
||||||
class WinMain(Api):
|
class WinMain(Api):
|
||||||
@ -103,61 +112,74 @@ class WinMain(Api):
|
|||||||
self._tmp += 1
|
self._tmp += 1
|
||||||
if self._tmp > 10:
|
if self._tmp > 10:
|
||||||
self._tmp = 0
|
self._tmp = 0
|
||||||
if self._tmp < 5 :
|
if self._tmp < 5:
|
||||||
return "{} {} --弹幕助手 by JerryYan".format(self.roomLiver, "的直播间")
|
return "{} 的直播间 --弹幕助手 by JerryYan".format(self.broadcaster)
|
||||||
else:
|
else:
|
||||||
if self.roomPopularity == 0:
|
if self.roomPopularity == 0:
|
||||||
self._tmp = 0
|
self._tmp = 0
|
||||||
return self.getTitle()
|
return self.getTitle()
|
||||||
else:
|
else:
|
||||||
if self.roomMember > 0:
|
return "人气:{} --弹幕助手 by JerryYan".format(self.roomPopularity)
|
||||||
return "观看:{} 人气:{} --弹幕助手 by JerryYan".format(self.roomMember, self.roomPopularity)
|
|
||||||
else:
|
|
||||||
return "观看:待刷新 人气:{} --弹幕助手 by JerryYan".format(self.roomPopularity)
|
|
||||||
|
|
||||||
|
|
||||||
def onMessage(self, msg: str):
|
def onMessage(self, msg: str):
|
||||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
if SHOW_ALL:
|
||||||
print("消息 : ", msg)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||||
|
print("消息 : ", msg, end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onJoin(self, user: User):
|
def onJoin(self, user: User):
|
||||||
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
||||||
print("感谢", user, "加入了粉丝团")
|
print("欢迎", user, "加入了粉丝团", end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onSubscribe(self, user: User):
|
def onSubscribe(self, user: User):
|
||||||
if SHOW_ALL:
|
if SHOW_ALL:
|
||||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||||
print("用户", user, "关注了主播")
|
print("用户", user, "关注了主播", end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onEnter(self, msg:MemberMsg):
|
def onEnter(self, msg:MemberMsg):
|
||||||
if SHOW_ALL:
|
if SHOW_ALL:
|
||||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||||
print("提示 :", msg)
|
print("提示 :", msg, end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onChat(self, chat: Chat):
|
def onChat(self, chat: Chat):
|
||||||
if SHOW_ALL:
|
if SHOW_ALL:
|
||||||
print(chat)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_WHITE)
|
||||||
|
if not chat.isFiltered:
|
||||||
|
print(chat, end="")
|
||||||
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
|
def onLottery(self, i:Lottery):
|
||||||
|
set_cmd_text_color(FOREGROUND_WHITE | BACKGROUND_DARKGRAY)
|
||||||
|
print(i, end="")
|
||||||
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onPresent(self, gift: Gift):
|
def onPresent(self, gift: Gift):
|
||||||
if SHOW_ALL:
|
if SHOW_ALL:
|
||||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||||
print("连击 :", gift)
|
print("连击 :", gift)
|
||||||
resetColor()
|
resetColor()
|
||||||
|
|
||||||
def onPresentEnd(self, gift: Gift):
|
def onPresentEnd(self, gift: Gift):
|
||||||
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
||||||
print("感谢", gift)
|
print("感谢", gift, end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onLike(self, user: User):
|
def onLike(self, user: User):
|
||||||
if SHOW_ALL:
|
if SHOW_ALL:
|
||||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||||
print("用户", user, "点了喜欢")
|
print("用户", user, "点了喜欢", end="")
|
||||||
resetColor()
|
resetColor()
|
||||||
|
print()
|
||||||
|
|
||||||
def onLeave(self, json: any):
|
def onLeave(self, json: any):
|
||||||
return
|
return
|
||||||
@ -168,41 +190,47 @@ def warning(*args):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
room = 97621754276 # 永恒
|
name = "97621754276"
|
||||||
# room = 75366565294
|
if len(sys.argv) > 2:
|
||||||
# room = 83940182312 #Dae
|
|
||||||
resetColor()
|
|
||||||
print("西瓜直播弹幕助手 by JerryYan")
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
if sys.argv[-1] == "a":
|
if sys.argv[-1] == "a":
|
||||||
SHOW_ALL = True
|
SHOW_ALL = True
|
||||||
try:
|
name = sys.argv[1]
|
||||||
room = int(sys.argv[1])
|
resetColor()
|
||||||
except:
|
public_hello()
|
||||||
pass
|
print("搜索【", name, "】", end="\t", flush=True)
|
||||||
else:
|
api = WinMain(name)
|
||||||
try:
|
if not api.isValidUser:
|
||||||
room = int(readInput("请输入用户ID号,默认为永恒的ID号", room, 3))
|
input("用户不存在")
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
api = WinMain(room)
|
|
||||||
print("进入", api.roomLiver, "的直播间")
|
|
||||||
if not api.isValidRoom:
|
|
||||||
input("房间不存在")
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
print("OK")
|
||||||
|
print(api.broadcaster.__repr__())
|
||||||
|
print("更新房间信息,请稍后", end="\t", flush=True)
|
||||||
os.system("title {}".format(api.getTitle()))
|
os.system("title {}".format(api.getTitle()))
|
||||||
|
if api.updRoomInfo(True):
|
||||||
|
print("OK")
|
||||||
|
else:
|
||||||
|
print("FAIL")
|
||||||
|
print("更新房间礼物信息", end="\t", flush=True)
|
||||||
|
__res = api.updGiftInfo()
|
||||||
|
if __res < 0:
|
||||||
|
print("FAIL")
|
||||||
|
else:
|
||||||
|
print('OK\n礼物种数:', __res)
|
||||||
print("=" * 30)
|
print("=" * 30)
|
||||||
while True:
|
while True:
|
||||||
if api.isLive:
|
if api.isLive:
|
||||||
try:
|
|
||||||
os.system("title {}".format(api.getTitle()))
|
os.system("title {}".format(api.getTitle()))
|
||||||
|
try:
|
||||||
api.getDanmaku()
|
api.getDanmaku()
|
||||||
|
except requests.exceptions.BaseHTTPError:
|
||||||
|
print("网络错误,请确认网络")
|
||||||
|
time.sleep(5)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warning(e)
|
print(e.__str__())
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
else:
|
else:
|
||||||
set_cmd_text_color(FOREGROUND_RED)
|
set_cmd_text_color(FOREGROUND_RED)
|
||||||
print("主播未开播,等待1分钟后重试")
|
print("主播未开播,等待1分钟后重试")
|
||||||
resetColor()
|
resetColor()
|
||||||
time.sleep(60)
|
time.sleep(60)
|
||||||
api.updRoomInfo()
|
api.updRoomInfo(True)
|
||||||
|
33
WinMain.spec
Normal file
33
WinMain.spec
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['WinMain.py'],
|
||||||
|
pathex=['E:\\XiGuaLiveDanmakuHelper',r'C:\\Program Files (x86)\\Windows Kits\\10\\Redist\\10.0.17763.0\\ucrt\\DLLs\\x86'],
|
||||||
|
binaries=[],
|
||||||
|
datas=[],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=["xml", "_tkinter", "pydoc", "lib2to3"],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='西瓜直播礼物助手',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=False,
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=True,
|
||||||
|
icon='./ico.ico' )
|
122
XiguaGift_pb2.py
Normal file
122
XiguaGift_pb2.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: XiguaGift.proto
|
||||||
|
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
|
name='XiguaGift.proto',
|
||||||
|
package='',
|
||||||
|
syntax='proto2',
|
||||||
|
serialized_options=None,
|
||||||
|
serialized_pb=b'\n\x0fXiguaGift.proto\" \n\x04Gift\x12\n\n\x02id\x18\x01 \x02(\t\x12\x0c\n\x04name\x18\x02 \x02(\t\"+\n\x08GiftPack\x12\n\n\x02id\x18\x01 \x02(\x05\x12\x13\n\x04gift\x18\x02 \x02(\x0b\x32\x05.Gift'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_GIFT = _descriptor.Descriptor(
|
||||||
|
name='Gift',
|
||||||
|
full_name='Gift',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='id', full_name='Gift.id', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='name', full_name='Gift.name', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=19,
|
||||||
|
serialized_end=51,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_GIFTPACK = _descriptor.Descriptor(
|
||||||
|
name='GiftPack',
|
||||||
|
full_name='GiftPack',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='id', full_name='GiftPack.id', index=0,
|
||||||
|
number=1, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='gift', full_name='GiftPack.gift', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=53,
|
||||||
|
serialized_end=96,
|
||||||
|
)
|
||||||
|
|
||||||
|
_GIFTPACK.fields_by_name['gift'].message_type = _GIFT
|
||||||
|
DESCRIPTOR.message_types_by_name['Gift'] = _GIFT
|
||||||
|
DESCRIPTOR.message_types_by_name['GiftPack'] = _GIFTPACK
|
||||||
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
|
Gift = _reflection.GeneratedProtocolMessageType('Gift', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _GIFT,
|
||||||
|
'__module__' : 'XiguaGift_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Gift)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(Gift)
|
||||||
|
|
||||||
|
GiftPack = _reflection.GeneratedProtocolMessageType('GiftPack', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _GIFTPACK,
|
||||||
|
'__module__' : 'XiguaGift_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:GiftPack)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(GiftPack)
|
||||||
|
|
||||||
|
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
797
XiguaMessage_pb2.py
Normal file
797
XiguaMessage_pb2.py
Normal file
@ -0,0 +1,797 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: XiguaMessage.proto
|
||||||
|
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
import XiguaUser_pb2 as XiguaUser__pb2
|
||||||
|
import XiguaGift_pb2 as XiguaGift__pb2
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
|
name='XiguaMessage.proto',
|
||||||
|
package='',
|
||||||
|
syntax='proto2',
|
||||||
|
serialized_options=None,
|
||||||
|
serialized_pb=b'\n\x12XiguaMessage.proto\x1a\x0fXiguaUser.proto\x1a\x0fXiguaGift.proto\"*\n\x07Message\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\"f\n\x0f\x46\x61nsClubMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x0c\n\x04type\x18\x02 \x02(\x05\x12\x0f\n\x07\x63ontent\x18\x03 \x02(\t\x12\x13\n\x04user\x18\x04 \x02(\x0b\x32\x05.User\"U\n\x14\x46\x61nsClubStatsMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\r\n\x05title\x18\x02 \x02(\t\x12\r\n\x05\x63ount\x18\x03 \x02(\x05\"]\n\x0eUserSeqMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x16\n\x0epopularityText\x18\x04 \x02(\t\x12\x12\n\npopularity\x18\x06 \x02(\x05\"D\n\x10\x44\x61ilyRankMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x0f\n\x07ranking\x18\n \x02(\x05\"T\n\x0b\x43hatMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x13\n\x04user\x18\x02 \x02(\x0b\x32\x05.User\x12\x0f\n\x07\x63ontent\x18\x03 \x02(\t\"]\n\rMemberMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x13\n\x04user\x18\x02 \x02(\x0b\x32\x05.User\x12\x16\n\x0epopularityText\x18\x0e \x02(\t\"\xa1\x01\n\x0bGiftMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x0e\n\x06giftId\x18\x02 \x02(\x05\x12\x10\n\x08\x63ontent4\x18\x04 \x02(\x05\x12\x10\n\x08repeated\x18\x05 \x02(\x05\x12\r\n\x05\x63ombo\x18\x06 \x02(\x05\x12\x13\n\x04user\x18\x07 \x01(\x0b\x32\x05.User\x12\x19\n\nisFinished\x18\t \x01(\x08:\x05\x66\x61lse\"f\n\rSocialMessage\x12\x1f\n\ncommonInfo\x18\x01 \x02(\x0b\x32\x0b.CommonInfo\x12\x13\n\x04user\x18\x02 \x02(\x0b\x32\x05.User\x12\x0c\n\x04int4\x18\x04 \x02(\x05\x12\x11\n\tfansCount\x18\x06 \x02(\x05\"*\n\x05Style\x12\r\n\x05\x63olor\x18\x01 \x01(\t\x12\x12\n\nfontWeight\x18\x04 \x01(\x05\"q\n\x06Params\x12\x0c\n\x04type\x18\x01 \x02(\x05\x12\x15\n\x05style\x18\x02 \x01(\x0b\x32\x06.Style\x12\x0e\n\x06string\x18\x0b \x01(\t\x12\x18\n\x05users\x18\x15 \x01(\x0b\x32\t.UserPack\x12\x18\n\x05gifts\x18\x16 \x01(\x0b\x32\t.GiftPack\"_\n\x0b\x44isplayText\x12\x0e\n\x06method\x18\x01 \x02(\t\x12\x0e\n\x06\x66ormat\x18\x02 \x02(\t\x12\x17\n\x07\x62gStyle\x18\x03 \x01(\x0b\x32\x06.Style\x12\x17\n\x06params\x18\x04 \x02(\x0b\x32\x07.Params\"\x87\x01\n\nCommonInfo\x12\x0e\n\x06method\x18\x01 \x02(\t\x12\x0e\n\x06msg_id\x18\x02 \x02(\x05\x12\x0f\n\x07room_id\x18\x03 \x02(\x05\x12\x13\n\x0b\x63reate_time\x18\x04 \x02(\x05\x12\x10\n\x08someEnum\x18\x06 \x01(\x05\x12!\n\x0b\x64isplayText\x18\x08 \x01(\x0b\x32\x0c.DisplayText'
|
||||||
|
,
|
||||||
|
dependencies=[XiguaUser__pb2.DESCRIPTOR,XiguaGift__pb2.DESCRIPTOR,])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_MESSAGE = _descriptor.Descriptor(
|
||||||
|
name='Message',
|
||||||
|
full_name='Message',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='Message.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=56,
|
||||||
|
serialized_end=98,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_FANSCLUBMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='FansClubMessage',
|
||||||
|
full_name='FansClubMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='FansClubMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='type', full_name='FansClubMessage.type', index=1,
|
||||||
|
number=2, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='content', full_name='FansClubMessage.content', index=2,
|
||||||
|
number=3, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='FansClubMessage.user', index=3,
|
||||||
|
number=4, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=100,
|
||||||
|
serialized_end=202,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_FANSCLUBSTATSMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='FansClubStatsMessage',
|
||||||
|
full_name='FansClubStatsMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='FansClubStatsMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='title', full_name='FansClubStatsMessage.title', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='count', full_name='FansClubStatsMessage.count', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=204,
|
||||||
|
serialized_end=289,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_USERSEQMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='UserSeqMessage',
|
||||||
|
full_name='UserSeqMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='UserSeqMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='popularityText', full_name='UserSeqMessage.popularityText', index=1,
|
||||||
|
number=4, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='popularity', full_name='UserSeqMessage.popularity', index=2,
|
||||||
|
number=6, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=291,
|
||||||
|
serialized_end=384,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_DAILYRANKMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='DailyRankMessage',
|
||||||
|
full_name='DailyRankMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='DailyRankMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='ranking', full_name='DailyRankMessage.ranking', index=1,
|
||||||
|
number=10, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=386,
|
||||||
|
serialized_end=454,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_CHATMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='ChatMessage',
|
||||||
|
full_name='ChatMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='ChatMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='ChatMessage.user', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='content', full_name='ChatMessage.content', index=2,
|
||||||
|
number=3, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=456,
|
||||||
|
serialized_end=540,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_MEMBERMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='MemberMessage',
|
||||||
|
full_name='MemberMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='MemberMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='MemberMessage.user', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='popularityText', full_name='MemberMessage.popularityText', index=2,
|
||||||
|
number=14, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=542,
|
||||||
|
serialized_end=635,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_GIFTMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='GiftMessage',
|
||||||
|
full_name='GiftMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='GiftMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='giftId', full_name='GiftMessage.giftId', index=1,
|
||||||
|
number=2, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='content4', full_name='GiftMessage.content4', index=2,
|
||||||
|
number=4, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='repeated', full_name='GiftMessage.repeated', index=3,
|
||||||
|
number=5, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='combo', full_name='GiftMessage.combo', index=4,
|
||||||
|
number=6, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='GiftMessage.user', index=5,
|
||||||
|
number=7, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='isFinished', full_name='GiftMessage.isFinished', index=6,
|
||||||
|
number=9, type=8, cpp_type=7, label=1,
|
||||||
|
has_default_value=True, default_value=False,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=638,
|
||||||
|
serialized_end=799,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_SOCIALMESSAGE = _descriptor.Descriptor(
|
||||||
|
name='SocialMessage',
|
||||||
|
full_name='SocialMessage',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='commonInfo', full_name='SocialMessage.commonInfo', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='SocialMessage.user', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='int4', full_name='SocialMessage.int4', index=2,
|
||||||
|
number=4, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fansCount', full_name='SocialMessage.fansCount', index=3,
|
||||||
|
number=6, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=801,
|
||||||
|
serialized_end=903,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_STYLE = _descriptor.Descriptor(
|
||||||
|
name='Style',
|
||||||
|
full_name='Style',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='color', full_name='Style.color', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fontWeight', full_name='Style.fontWeight', index=1,
|
||||||
|
number=4, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=905,
|
||||||
|
serialized_end=947,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_PARAMS = _descriptor.Descriptor(
|
||||||
|
name='Params',
|
||||||
|
full_name='Params',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='type', full_name='Params.type', index=0,
|
||||||
|
number=1, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='style', full_name='Params.style', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='string', full_name='Params.string', index=2,
|
||||||
|
number=11, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='users', full_name='Params.users', index=3,
|
||||||
|
number=21, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='gifts', full_name='Params.gifts', index=4,
|
||||||
|
number=22, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=949,
|
||||||
|
serialized_end=1062,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_DISPLAYTEXT = _descriptor.Descriptor(
|
||||||
|
name='DisplayText',
|
||||||
|
full_name='DisplayText',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='method', full_name='DisplayText.method', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='format', full_name='DisplayText.format', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='bgStyle', full_name='DisplayText.bgStyle', index=2,
|
||||||
|
number=3, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='params', full_name='DisplayText.params', index=3,
|
||||||
|
number=4, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=1064,
|
||||||
|
serialized_end=1159,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_COMMONINFO = _descriptor.Descriptor(
|
||||||
|
name='CommonInfo',
|
||||||
|
full_name='CommonInfo',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='method', full_name='CommonInfo.method', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='msg_id', full_name='CommonInfo.msg_id', index=1,
|
||||||
|
number=2, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='room_id', full_name='CommonInfo.room_id', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='create_time', full_name='CommonInfo.create_time', index=3,
|
||||||
|
number=4, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='someEnum', full_name='CommonInfo.someEnum', index=4,
|
||||||
|
number=6, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='displayText', full_name='CommonInfo.displayText', index=5,
|
||||||
|
number=8, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=1162,
|
||||||
|
serialized_end=1297,
|
||||||
|
)
|
||||||
|
|
||||||
|
_MESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_FANSCLUBMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_FANSCLUBMESSAGE.fields_by_name['user'].message_type = XiguaUser__pb2._USER
|
||||||
|
_FANSCLUBSTATSMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_USERSEQMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_DAILYRANKMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_CHATMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_CHATMESSAGE.fields_by_name['user'].message_type = XiguaUser__pb2._USER
|
||||||
|
_MEMBERMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_MEMBERMESSAGE.fields_by_name['user'].message_type = XiguaUser__pb2._USER
|
||||||
|
_GIFTMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_GIFTMESSAGE.fields_by_name['user'].message_type = XiguaUser__pb2._USER
|
||||||
|
_SOCIALMESSAGE.fields_by_name['commonInfo'].message_type = _COMMONINFO
|
||||||
|
_SOCIALMESSAGE.fields_by_name['user'].message_type = XiguaUser__pb2._USER
|
||||||
|
_PARAMS.fields_by_name['style'].message_type = _STYLE
|
||||||
|
_PARAMS.fields_by_name['users'].message_type = XiguaUser__pb2._USERPACK
|
||||||
|
_PARAMS.fields_by_name['gifts'].message_type = XiguaGift__pb2._GIFTPACK
|
||||||
|
_DISPLAYTEXT.fields_by_name['bgStyle'].message_type = _STYLE
|
||||||
|
_DISPLAYTEXT.fields_by_name['params'].message_type = _PARAMS
|
||||||
|
_COMMONINFO.fields_by_name['displayText'].message_type = _DISPLAYTEXT
|
||||||
|
DESCRIPTOR.message_types_by_name['Message'] = _MESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['FansClubMessage'] = _FANSCLUBMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['FansClubStatsMessage'] = _FANSCLUBSTATSMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['UserSeqMessage'] = _USERSEQMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['DailyRankMessage'] = _DAILYRANKMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['ChatMessage'] = _CHATMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['MemberMessage'] = _MEMBERMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['GiftMessage'] = _GIFTMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['SocialMessage'] = _SOCIALMESSAGE
|
||||||
|
DESCRIPTOR.message_types_by_name['Style'] = _STYLE
|
||||||
|
DESCRIPTOR.message_types_by_name['Params'] = _PARAMS
|
||||||
|
DESCRIPTOR.message_types_by_name['DisplayText'] = _DISPLAYTEXT
|
||||||
|
DESCRIPTOR.message_types_by_name['CommonInfo'] = _COMMONINFO
|
||||||
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
|
Message = _reflection.GeneratedProtocolMessageType('Message', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _MESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Message)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(Message)
|
||||||
|
|
||||||
|
FansClubMessage = _reflection.GeneratedProtocolMessageType('FansClubMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _FANSCLUBMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:FansClubMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(FansClubMessage)
|
||||||
|
|
||||||
|
FansClubStatsMessage = _reflection.GeneratedProtocolMessageType('FansClubStatsMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _FANSCLUBSTATSMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:FansClubStatsMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(FansClubStatsMessage)
|
||||||
|
|
||||||
|
UserSeqMessage = _reflection.GeneratedProtocolMessageType('UserSeqMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USERSEQMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:UserSeqMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(UserSeqMessage)
|
||||||
|
|
||||||
|
DailyRankMessage = _reflection.GeneratedProtocolMessageType('DailyRankMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _DAILYRANKMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:DailyRankMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(DailyRankMessage)
|
||||||
|
|
||||||
|
ChatMessage = _reflection.GeneratedProtocolMessageType('ChatMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _CHATMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:ChatMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(ChatMessage)
|
||||||
|
|
||||||
|
MemberMessage = _reflection.GeneratedProtocolMessageType('MemberMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _MEMBERMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:MemberMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(MemberMessage)
|
||||||
|
|
||||||
|
GiftMessage = _reflection.GeneratedProtocolMessageType('GiftMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _GIFTMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:GiftMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(GiftMessage)
|
||||||
|
|
||||||
|
SocialMessage = _reflection.GeneratedProtocolMessageType('SocialMessage', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _SOCIALMESSAGE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:SocialMessage)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(SocialMessage)
|
||||||
|
|
||||||
|
Style = _reflection.GeneratedProtocolMessageType('Style', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _STYLE,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Style)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(Style)
|
||||||
|
|
||||||
|
Params = _reflection.GeneratedProtocolMessageType('Params', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _PARAMS,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Params)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(Params)
|
||||||
|
|
||||||
|
DisplayText = _reflection.GeneratedProtocolMessageType('DisplayText', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _DISPLAYTEXT,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:DisplayText)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(DisplayText)
|
||||||
|
|
||||||
|
CommonInfo = _reflection.GeneratedProtocolMessageType('CommonInfo', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _COMMONINFO,
|
||||||
|
'__module__' : 'XiguaMessage_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:CommonInfo)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(CommonInfo)
|
||||||
|
|
||||||
|
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
727
XiguaUser_pb2.py
Normal file
727
XiguaUser_pb2.py
Normal file
@ -0,0 +1,727 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: XiguaUser.proto
|
||||||
|
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
|
name='XiguaUser.proto',
|
||||||
|
package='',
|
||||||
|
syntax='proto2',
|
||||||
|
serialized_options=None,
|
||||||
|
serialized_pb=b'\n\x0fXiguaUser.proto\"\x1f\n\x08UserPack\x12\x13\n\x04user\x18\x01 \x02(\x0b\x32\x05.User\"\xb6\x01\n\x05\x42\x61\x64ge\x12\x0b\n\x03url\x18\x01 \x03(\t\x12\x0e\n\x06height\x18\x03 \x01(\x05\x12\r\n\x05width\x18\x04 \x01(\x05\x12\x0c\n\x04type\x18\x06 \x01(\x05\x12\x0f\n\x07\x63lickTo\x18\x07 \x01(\t\x12\'\n\x0b\x66\x61nClubText\x18\x08 \x01(\x0b\x32\x12.Badge.FanClubText\x1a\x39\n\x0b\x46\x61nClubText\x12\x0c\n\x04text\x18\x01 \x02(\t\x12\r\n\x05\x63olor\x18\x02 \x01(\t\x12\r\n\x05level\x18\x03 \x02(\x05\"y\n\x0c\x46\x61nsClubPack\x12(\n\x08\x66\x61nsClub\x18\x01 \x02(\x0b\x32\x16.FansClubPack.FansClub\x1a?\n\x08\x46\x61nsClub\x12\x0f\n\x05title\x18\x01 \x02(\t:\x00\x12\x10\n\x05level\x18\x02 \x02(\x05:\x01\x30\x12\x10\n\x08someEnum\x18\x03 \x01(\x05\"\xd8\x05\n\x04User\x12\n\n\x02id\x18\x01 \x02(\x03\x12\x10\n\x08nickname\x18\x03 \x02(\t\x12\x0e\n\x06gender\x18\x04 \x02(\x05\x12!\n\x0b\x61vatarThumb\x18\t \x02(\x0b\x32\x0c.User.Avatar\x12\"\n\x0c\x61vatarMedium\x18\n \x01(\x0b\x32\x0c.User.Avatar\x12!\n\x0b\x61vatarLarge\x18\x0b \x01(\x0b\x32\x0c.User.Avatar\x12\x15\n\x05\x62\x61\x64ge\x18\x15 \x03(\x0b\x32\x06.Badge\x12\x1c\n\x06\x66ollow\x18\x16 \x01(\x0b\x32\x0c.User.Follow\x12 \n\x08payGrade\x18\x17 \x02(\x0b\x32\x0e.User.PayGrade\x12\x1f\n\x08\x66\x61nsClub\x18\x18 \x02(\x0b\x32\r.FansClubPack\x12\x11\n\ttotalPaid\x18\" \x02(\x05\x1a!\n\x06\x41vatar\x12\x0b\n\x03url\x18\x01 \x02(\t\x12\n\n\x02id\x18\x02 \x01(\t\x1a\x33\n\x06\x46ollow\x12\x14\n\tfollowing\x18\x01 \x01(\x05:\x01\x30\x12\x13\n\x08\x66ollower\x18\x02 \x01(\x05:\x01\x30\x1a\x9c\x01\n\x08PayGrade\x12\x0f\n\x07\x63urrent\x18\x01 \x02(\x05\x12\r\n\x05level\x18\x06 \x02(\x05\x12\x18\n\x10\x63urrentLevelNeed\x18\n \x01(\x05\x12\x15\n\rnextLevelNeed\x18\x0b \x01(\x05\x12\x0f\n\x07\x63ontent\x18\r \x01(\t\x12\x15\n\x05\x62\x61\x64ge\x18\x13 \x02(\x0b\x32\x06.Badge\x12\x17\n\x0ftoNextLevelNeed\x18\x15 \x01(\x05\x1a#\n\nHonorLevel\x12\x15\n\x05\x62\x61\x64ge\x18\x13 \x02(\x0b\x32\x06.Badge\x1a\x90\x01\n\x05Noble\x12\x0f\n\x07\x63ontent\x18\x04 \x02(\t\x12)\n\x07\x62oarder\x18\x08 \x01(\x0b\x32\x18.User.Noble.NobleBoarder\x1aK\n\x0cNobleBoarder\x12\x0f\n\x07urlList\x18\x01 \x03(\t\x12\x0b\n\x03uri\x18\x02 \x02(\t\x12\x0e\n\x06height\x18\x03 \x01(\x05\x12\r\n\x05width\x18\x04 \x01(\x05'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_USERPACK = _descriptor.Descriptor(
|
||||||
|
name='UserPack',
|
||||||
|
full_name='UserPack',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='user', full_name='UserPack.user', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=19,
|
||||||
|
serialized_end=50,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_BADGE_FANCLUBTEXT = _descriptor.Descriptor(
|
||||||
|
name='FanClubText',
|
||||||
|
full_name='Badge.FanClubText',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='text', full_name='Badge.FanClubText.text', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='color', full_name='Badge.FanClubText.color', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='level', full_name='Badge.FanClubText.level', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=178,
|
||||||
|
serialized_end=235,
|
||||||
|
)
|
||||||
|
|
||||||
|
_BADGE = _descriptor.Descriptor(
|
||||||
|
name='Badge',
|
||||||
|
full_name='Badge',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='url', full_name='Badge.url', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=3,
|
||||||
|
has_default_value=False, default_value=[],
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='height', full_name='Badge.height', index=1,
|
||||||
|
number=3, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='width', full_name='Badge.width', index=2,
|
||||||
|
number=4, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='type', full_name='Badge.type', index=3,
|
||||||
|
number=6, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='clickTo', full_name='Badge.clickTo', index=4,
|
||||||
|
number=7, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fanClubText', full_name='Badge.fanClubText', index=5,
|
||||||
|
number=8, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[_BADGE_FANCLUBTEXT, ],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=53,
|
||||||
|
serialized_end=235,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_FANSCLUBPACK_FANSCLUB = _descriptor.Descriptor(
|
||||||
|
name='FansClub',
|
||||||
|
full_name='FansClubPack.FansClub',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='title', full_name='FansClubPack.FansClub.title', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=True, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='level', full_name='FansClubPack.FansClub.level', index=1,
|
||||||
|
number=2, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=True, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='someEnum', full_name='FansClubPack.FansClub.someEnum', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=295,
|
||||||
|
serialized_end=358,
|
||||||
|
)
|
||||||
|
|
||||||
|
_FANSCLUBPACK = _descriptor.Descriptor(
|
||||||
|
name='FansClubPack',
|
||||||
|
full_name='FansClubPack',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fansClub', full_name='FansClubPack.fansClub', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[_FANSCLUBPACK_FANSCLUB, ],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=237,
|
||||||
|
serialized_end=358,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_USER_AVATAR = _descriptor.Descriptor(
|
||||||
|
name='Avatar',
|
||||||
|
full_name='User.Avatar',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='url', full_name='User.Avatar.url', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='id', full_name='User.Avatar.id', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=660,
|
||||||
|
serialized_end=693,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER_FOLLOW = _descriptor.Descriptor(
|
||||||
|
name='Follow',
|
||||||
|
full_name='User.Follow',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='following', full_name='User.Follow.following', index=0,
|
||||||
|
number=1, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=True, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='follower', full_name='User.Follow.follower', index=1,
|
||||||
|
number=2, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=True, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=695,
|
||||||
|
serialized_end=746,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER_PAYGRADE = _descriptor.Descriptor(
|
||||||
|
name='PayGrade',
|
||||||
|
full_name='User.PayGrade',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='current', full_name='User.PayGrade.current', index=0,
|
||||||
|
number=1, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='level', full_name='User.PayGrade.level', index=1,
|
||||||
|
number=6, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='currentLevelNeed', full_name='User.PayGrade.currentLevelNeed', index=2,
|
||||||
|
number=10, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='nextLevelNeed', full_name='User.PayGrade.nextLevelNeed', index=3,
|
||||||
|
number=11, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='content', full_name='User.PayGrade.content', index=4,
|
||||||
|
number=13, type=9, cpp_type=9, label=1,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='badge', full_name='User.PayGrade.badge', index=5,
|
||||||
|
number=19, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='toNextLevelNeed', full_name='User.PayGrade.toNextLevelNeed', index=6,
|
||||||
|
number=21, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=749,
|
||||||
|
serialized_end=905,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER_HONORLEVEL = _descriptor.Descriptor(
|
||||||
|
name='HonorLevel',
|
||||||
|
full_name='User.HonorLevel',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='badge', full_name='User.HonorLevel.badge', index=0,
|
||||||
|
number=19, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=907,
|
||||||
|
serialized_end=942,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER_NOBLE_NOBLEBOARDER = _descriptor.Descriptor(
|
||||||
|
name='NobleBoarder',
|
||||||
|
full_name='User.Noble.NobleBoarder',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='urlList', full_name='User.Noble.NobleBoarder.urlList', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=3,
|
||||||
|
has_default_value=False, default_value=[],
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='uri', full_name='User.Noble.NobleBoarder.uri', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='height', full_name='User.Noble.NobleBoarder.height', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='width', full_name='User.Noble.NobleBoarder.width', index=3,
|
||||||
|
number=4, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=1014,
|
||||||
|
serialized_end=1089,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER_NOBLE = _descriptor.Descriptor(
|
||||||
|
name='Noble',
|
||||||
|
full_name='User.Noble',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='content', full_name='User.Noble.content', index=0,
|
||||||
|
number=4, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='boarder', full_name='User.Noble.boarder', index=1,
|
||||||
|
number=8, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[_USER_NOBLE_NOBLEBOARDER, ],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=945,
|
||||||
|
serialized_end=1089,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USER = _descriptor.Descriptor(
|
||||||
|
name='User',
|
||||||
|
full_name='User',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='id', full_name='User.id', index=0,
|
||||||
|
number=1, type=3, cpp_type=2, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='nickname', full_name='User.nickname', index=1,
|
||||||
|
number=3, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='gender', full_name='User.gender', index=2,
|
||||||
|
number=4, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='avatarThumb', full_name='User.avatarThumb', index=3,
|
||||||
|
number=9, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='avatarMedium', full_name='User.avatarMedium', index=4,
|
||||||
|
number=10, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='avatarLarge', full_name='User.avatarLarge', index=5,
|
||||||
|
number=11, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='badge', full_name='User.badge', index=6,
|
||||||
|
number=21, type=11, cpp_type=10, label=3,
|
||||||
|
has_default_value=False, default_value=[],
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='follow', full_name='User.follow', index=7,
|
||||||
|
number=22, type=11, cpp_type=10, label=1,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='payGrade', full_name='User.payGrade', index=8,
|
||||||
|
number=23, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fansClub', full_name='User.fansClub', index=9,
|
||||||
|
number=24, type=11, cpp_type=10, label=2,
|
||||||
|
has_default_value=False, default_value=None,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='totalPaid', full_name='User.totalPaid', index=10,
|
||||||
|
number=34, type=5, cpp_type=1, label=2,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[_USER_AVATAR, _USER_FOLLOW, _USER_PAYGRADE, _USER_HONORLEVEL, _USER_NOBLE, ],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=361,
|
||||||
|
serialized_end=1089,
|
||||||
|
)
|
||||||
|
|
||||||
|
_USERPACK.fields_by_name['user'].message_type = _USER
|
||||||
|
_BADGE_FANCLUBTEXT.containing_type = _BADGE
|
||||||
|
_BADGE.fields_by_name['fanClubText'].message_type = _BADGE_FANCLUBTEXT
|
||||||
|
_FANSCLUBPACK_FANSCLUB.containing_type = _FANSCLUBPACK
|
||||||
|
_FANSCLUBPACK.fields_by_name['fansClub'].message_type = _FANSCLUBPACK_FANSCLUB
|
||||||
|
_USER_AVATAR.containing_type = _USER
|
||||||
|
_USER_FOLLOW.containing_type = _USER
|
||||||
|
_USER_PAYGRADE.fields_by_name['badge'].message_type = _BADGE
|
||||||
|
_USER_PAYGRADE.containing_type = _USER
|
||||||
|
_USER_HONORLEVEL.fields_by_name['badge'].message_type = _BADGE
|
||||||
|
_USER_HONORLEVEL.containing_type = _USER
|
||||||
|
_USER_NOBLE_NOBLEBOARDER.containing_type = _USER_NOBLE
|
||||||
|
_USER_NOBLE.fields_by_name['boarder'].message_type = _USER_NOBLE_NOBLEBOARDER
|
||||||
|
_USER_NOBLE.containing_type = _USER
|
||||||
|
_USER.fields_by_name['avatarThumb'].message_type = _USER_AVATAR
|
||||||
|
_USER.fields_by_name['avatarMedium'].message_type = _USER_AVATAR
|
||||||
|
_USER.fields_by_name['avatarLarge'].message_type = _USER_AVATAR
|
||||||
|
_USER.fields_by_name['badge'].message_type = _BADGE
|
||||||
|
_USER.fields_by_name['follow'].message_type = _USER_FOLLOW
|
||||||
|
_USER.fields_by_name['payGrade'].message_type = _USER_PAYGRADE
|
||||||
|
_USER.fields_by_name['fansClub'].message_type = _FANSCLUBPACK
|
||||||
|
DESCRIPTOR.message_types_by_name['UserPack'] = _USERPACK
|
||||||
|
DESCRIPTOR.message_types_by_name['Badge'] = _BADGE
|
||||||
|
DESCRIPTOR.message_types_by_name['FansClubPack'] = _FANSCLUBPACK
|
||||||
|
DESCRIPTOR.message_types_by_name['User'] = _USER
|
||||||
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
|
UserPack = _reflection.GeneratedProtocolMessageType('UserPack', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USERPACK,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:UserPack)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(UserPack)
|
||||||
|
|
||||||
|
Badge = _reflection.GeneratedProtocolMessageType('Badge', (_message.Message,), {
|
||||||
|
|
||||||
|
'FanClubText' : _reflection.GeneratedProtocolMessageType('FanClubText', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _BADGE_FANCLUBTEXT,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Badge.FanClubText)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _BADGE,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:Badge)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(Badge)
|
||||||
|
_sym_db.RegisterMessage(Badge.FanClubText)
|
||||||
|
|
||||||
|
FansClubPack = _reflection.GeneratedProtocolMessageType('FansClubPack', (_message.Message,), {
|
||||||
|
|
||||||
|
'FansClub' : _reflection.GeneratedProtocolMessageType('FansClub', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _FANSCLUBPACK_FANSCLUB,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:FansClubPack.FansClub)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _FANSCLUBPACK,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:FansClubPack)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(FansClubPack)
|
||||||
|
_sym_db.RegisterMessage(FansClubPack.FansClub)
|
||||||
|
|
||||||
|
User = _reflection.GeneratedProtocolMessageType('User', (_message.Message,), {
|
||||||
|
|
||||||
|
'Avatar' : _reflection.GeneratedProtocolMessageType('Avatar', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USER_AVATAR,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.Avatar)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
|
||||||
|
'Follow' : _reflection.GeneratedProtocolMessageType('Follow', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USER_FOLLOW,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.Follow)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
|
||||||
|
'PayGrade' : _reflection.GeneratedProtocolMessageType('PayGrade', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USER_PAYGRADE,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.PayGrade)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
|
||||||
|
'HonorLevel' : _reflection.GeneratedProtocolMessageType('HonorLevel', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USER_HONORLEVEL,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.HonorLevel)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
|
||||||
|
'Noble' : _reflection.GeneratedProtocolMessageType('Noble', (_message.Message,), {
|
||||||
|
|
||||||
|
'NobleBoarder' : _reflection.GeneratedProtocolMessageType('NobleBoarder', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _USER_NOBLE_NOBLEBOARDER,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.Noble.NobleBoarder)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _USER_NOBLE,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User.Noble)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _USER,
|
||||||
|
'__module__' : 'XiguaUser_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:User)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(User)
|
||||||
|
_sym_db.RegisterMessage(User.Avatar)
|
||||||
|
_sym_db.RegisterMessage(User.Follow)
|
||||||
|
_sym_db.RegisterMessage(User.PayGrade)
|
||||||
|
_sym_db.RegisterMessage(User.HonorLevel)
|
||||||
|
_sym_db.RegisterMessage(User.Noble)
|
||||||
|
_sym_db.RegisterMessage(User.Noble.NobleBoarder)
|
||||||
|
|
||||||
|
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
143
Xigua_pb2.py
Normal file
143
Xigua_pb2.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: Xigua.proto
|
||||||
|
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
|
name='Xigua.proto',
|
||||||
|
package='',
|
||||||
|
syntax='proto2',
|
||||||
|
serialized_options=None,
|
||||||
|
serialized_pb=b'\n\x0bXigua.proto\"\x9a\x01\n\tXiguaLive\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.XiguaLive.Data\x12\x0e\n\x06\x63ursor\x18\x02 \x02(\t\x12\x16\n\x0e\x66\x65tch_interval\x18\x03 \x01(\x05\x12\x0b\n\x03now\x18\x04 \x01(\x05\x12\x14\n\x0cinternal_ext\x18\x05 \x02(\t\x1a#\n\x04\x44\x61ta\x12\x0e\n\x06method\x18\x01 \x02(\t\x12\x0b\n\x03raw\x18\x02 \x02(\x0c'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_XIGUALIVE_DATA = _descriptor.Descriptor(
|
||||||
|
name='Data',
|
||||||
|
full_name='XiguaLive.Data',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='method', full_name='XiguaLive.Data.method', index=0,
|
||||||
|
number=1, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='raw', full_name='XiguaLive.Data.raw', index=1,
|
||||||
|
number=2, type=12, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"",
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=135,
|
||||||
|
serialized_end=170,
|
||||||
|
)
|
||||||
|
|
||||||
|
_XIGUALIVE = _descriptor.Descriptor(
|
||||||
|
name='XiguaLive',
|
||||||
|
full_name='XiguaLive',
|
||||||
|
filename=None,
|
||||||
|
file=DESCRIPTOR,
|
||||||
|
containing_type=None,
|
||||||
|
fields=[
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='data', full_name='XiguaLive.data', index=0,
|
||||||
|
number=1, type=11, cpp_type=10, label=3,
|
||||||
|
has_default_value=False, default_value=[],
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='cursor', full_name='XiguaLive.cursor', index=1,
|
||||||
|
number=2, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='fetch_interval', full_name='XiguaLive.fetch_interval', index=2,
|
||||||
|
number=3, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='now', full_name='XiguaLive.now', index=3,
|
||||||
|
number=4, type=5, cpp_type=1, label=1,
|
||||||
|
has_default_value=False, default_value=0,
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='internal_ext', full_name='XiguaLive.internal_ext', index=4,
|
||||||
|
number=5, type=9, cpp_type=9, label=2,
|
||||||
|
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
serialized_options=None, file=DESCRIPTOR),
|
||||||
|
],
|
||||||
|
extensions=[
|
||||||
|
],
|
||||||
|
nested_types=[_XIGUALIVE_DATA, ],
|
||||||
|
enum_types=[
|
||||||
|
],
|
||||||
|
serialized_options=None,
|
||||||
|
is_extendable=False,
|
||||||
|
syntax='proto2',
|
||||||
|
extension_ranges=[],
|
||||||
|
oneofs=[
|
||||||
|
],
|
||||||
|
serialized_start=16,
|
||||||
|
serialized_end=170,
|
||||||
|
)
|
||||||
|
|
||||||
|
_XIGUALIVE_DATA.containing_type = _XIGUALIVE
|
||||||
|
_XIGUALIVE.fields_by_name['data'].message_type = _XIGUALIVE_DATA
|
||||||
|
DESCRIPTOR.message_types_by_name['XiguaLive'] = _XIGUALIVE
|
||||||
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
|
XiguaLive = _reflection.GeneratedProtocolMessageType('XiguaLive', (_message.Message,), {
|
||||||
|
|
||||||
|
'Data' : _reflection.GeneratedProtocolMessageType('Data', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _XIGUALIVE_DATA,
|
||||||
|
'__module__' : 'Xigua_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:XiguaLive.Data)
|
||||||
|
})
|
||||||
|
,
|
||||||
|
'DESCRIPTOR' : _XIGUALIVE,
|
||||||
|
'__module__' : 'Xigua_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:XiguaLive)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(XiguaLive)
|
||||||
|
_sym_db.RegisterMessage(XiguaLive.Data)
|
||||||
|
|
||||||
|
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
0
access_token
Normal file
0
access_token
Normal file
572
api.py
572
api.py
@ -1,180 +1,520 @@
|
|||||||
|
# coding=utf-8
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from MemberMsg import MemberMsg
|
from Struct.MemberMsg import MemberMsg
|
||||||
from User import User
|
from Struct.User import User
|
||||||
from Gift import Gift
|
from Struct.Gift import Gift
|
||||||
from Chat import Chat
|
from Struct.Chat import Chat
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from Xigua_pb2 import XiguaLive
|
||||||
|
from XiguaMessage_pb2 import FansClubMessage, SocialMessage
|
||||||
|
|
||||||
s = requests.Session()
|
DEBUG = False
|
||||||
|
# 自己抓的自己设备的参数,建议开发者自己抓一个长期使用
|
||||||
DEBUG: bool = False
|
# 如果有大佬破解初次激活设备时的数据也行,可以自己生成一堆用
|
||||||
|
CUSTOM_INFO = {
|
||||||
|
'iid': "3993882704224472",
|
||||||
|
'device_id': "71008241150",
|
||||||
|
'cdid': "f93b3708-3fec-498f-9080-723a5679f4c0",
|
||||||
|
'openudid': "4aeb1e2b627697be",
|
||||||
|
# 'aid': "32", # 是一个不变的值
|
||||||
|
'channel': "xiaomi",
|
||||||
|
'device_brand': "Xiaomi",
|
||||||
|
'device_type': "MI+9",
|
||||||
|
'os_api': "29",
|
||||||
|
'os_version': "10",
|
||||||
|
'abi': "armeabi-v7a",
|
||||||
|
'dpi': "480",
|
||||||
|
'resolution': "1080*2217",
|
||||||
|
'rom_version': "miui_V12_V12.0.6.0.QFACNXM",
|
||||||
|
}
|
||||||
|
VERSION_INFO = {
|
||||||
|
'app_name': "video_article",
|
||||||
|
'version_code': "966",
|
||||||
|
'version_code_full': "96615",
|
||||||
|
'version_name': "9.6.6",
|
||||||
|
'ab_version': "668851,2678488,668858,2678385,668859,2678471,668856,2678470,668855,2678439,668854,994679,"
|
||||||
|
"2678460,2713070,2738381,2744004,668853,2678466,668852,2678435,2625016",
|
||||||
|
'manifest_version_code': "566",
|
||||||
|
'tma_jssdk_version': "2010000",
|
||||||
|
'oaid': "693ea85657ef38ca",
|
||||||
|
}
|
||||||
|
COMMON_GET_PARAM = (
|
||||||
|
"&iid={iid}&device_id={device_id}&ac=wifi&channel={channel}&aid=32&app_name={app_name}&version_code={version_code}&"
|
||||||
|
"version_name={version_name}&device_platform=android&ab_version={ab_version}&ssmix=a&device_type={device_type}&"
|
||||||
|
"device_brand={device_brand}&language=zh&os_api={os_api}&os_version={os_version}&openudid={openudid}&"
|
||||||
|
"manifest_version_code={manifest_version_code}&resolution={resolution}&dpi={dpi}&"
|
||||||
|
"update_version_code={version_code_full}&_rticket={{TIMESTAMP:.0f}}&"
|
||||||
|
"cdid_ts={{TIMESTAMP:.0f}}&host_abi={abi}&tma_jssdk_version={tma_jssdk_version}&"
|
||||||
|
"rom_version={rom_version}&cdid={cdid}&oaid={oaid}").format_map({**VERSION_INFO, **CUSTOM_INFO})
|
||||||
|
WEBCAST_GET_PARAMS = "webcast_sdk_version=1990&webcast_language=zh&webcast_locale=zh_CN&webcast_gps_access=1"
|
||||||
|
ROOM_ENTER_POST_PARAMS = (
|
||||||
|
"room_id={roomId}&hold_living_room=1&is_login=0&enter_from_uid_by_shared=0&video_id=0&"
|
||||||
|
"scenario=0&enter_type=click&enter_source=click_pgc_WITHIN_pgc-head_portrait&live_room_mode=0")
|
||||||
|
SEARCH_USER_API = (
|
||||||
|
"https://search5-search-lq.ixigua.com/video/app/search/live/?format=json&keyword_type=search_subtab_switch"
|
||||||
|
"&fss=search_subtab_switch&target_channel=video_search&keyword_type=search_subtab_switch&offset=0&count=10"
|
||||||
|
"&search_sug=1&forum=1&is_native_req=0&m_tab=video&pd=user&tab=user&_s_tma=SEARCH_STANDARD.list.fe_get_data"
|
||||||
|
'&_s_page_sub_route=/&_s_ec={{"filterDataType":[],"reserveFilterBar":true}}&__use_xigua_native_bridge_fetch__=1'
|
||||||
|
'&ab_param={{"is_show_filter_feature": 1, "is_hit_new_ui": 1}}'
|
||||||
|
"&search_start_time={TIMESTAMP:.0f}&from=live&en_qc=1&pd=xigua_live&ssmix=a{COMMON}&keyword={keyword}")
|
||||||
|
USER_INFO_API = "https://ib-lq.snssdk.com/video/app/user/userhome/v8/?to_user_id={userId}{COMMON}"
|
||||||
|
ROOM_INFO_API = "https://webcast5-normal-c-lq.ixigua.com/webcast/room/enter/?{WEBCAST}{COMMON}"
|
||||||
|
DANMAKU_GET_API = "https://webcast5-normal-c-lq.ixigua.com/webcast/im/fetch/?{WEBCAST}{COMMON}"
|
||||||
|
GIFT_DATA_API = ("https://webcast5-normal-c-hl.ixigua.com/webcast/gift/list/?room_id={roomId}&to_room_id={roomId}&"
|
||||||
|
"gift_scene=1&fetch_giftlist_from=2¤t_network_quality_info={{}}&"
|
||||||
|
"{WEBCAST}{COMMON}")
|
||||||
|
COMMON_HEADERS = {
|
||||||
|
"x-vc-bdturing-sdk-version": "2.0.1",
|
||||||
|
"sdk-version": '2',
|
||||||
|
"passport-sdk-version": "21",
|
||||||
|
"User-Agent": "Dalvik/2.1.0 (Linux; U; Android 10; MI 9 MIUI/V12.0.6.0.QFACNXM) VideoArticle/9.6.6 "
|
||||||
|
"cronet/TTNetVersion:4b936afe 2021-01-13 QuicVersion:47946d2a 2020-10-14",
|
||||||
|
"X-SS-STUB": "74103A7F40FDC66E0675705DCA2C3A77",
|
||||||
|
"X-SS-DP": "32",
|
||||||
|
"Accept-Encoding": "gzip, deflate"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class XiGuaLiveApi:
|
class XiGuaLiveApi:
|
||||||
isLive: bool = False
|
|
||||||
isValidRoom: bool = False
|
|
||||||
_rawRoomInfo = {}
|
|
||||||
roomID: int = 0
|
|
||||||
roomTitle: str = ""
|
|
||||||
roomLiver: User = None
|
|
||||||
roomPopularity: int = 0
|
|
||||||
roomMember: int = 0
|
|
||||||
_cursor = ""
|
|
||||||
|
|
||||||
def __init__(self, room: int):
|
def __init__(self, name=None):
|
||||||
self.room = room
|
"""
|
||||||
|
Api类
|
||||||
|
Init Function
|
||||||
|
:param name: class:str|User: 主播名
|
||||||
|
"""
|
||||||
|
if name is None:
|
||||||
|
name = "永恒de草薙"
|
||||||
|
self.broadcaster = None
|
||||||
|
self.isValidUser = False
|
||||||
|
self.name = str(name)
|
||||||
|
if type(name) == User:
|
||||||
|
self.broadcaster = name
|
||||||
|
self.name = name.name
|
||||||
|
elif str(name).isdigit():
|
||||||
|
self.broadcaster = User()
|
||||||
|
self.isValidUser = True
|
||||||
|
self.broadcaster.ID = int(name)
|
||||||
|
else:
|
||||||
|
self.name = str(name)
|
||||||
|
self.isLive = False
|
||||||
|
self._rawRoomInfo = {}
|
||||||
|
self.roomID = 0
|
||||||
|
self.roomPopularity = 0
|
||||||
|
self.s = requests.session()
|
||||||
|
self.s.headers.update(COMMON_HEADERS)
|
||||||
|
self._updRoomAt = datetime.fromtimestamp(0)
|
||||||
self.updRoomInfo()
|
self.updRoomInfo()
|
||||||
Gift.update(self.roomID)
|
self._ext = ""
|
||||||
self._enterRoom()
|
self._cursor = "0"
|
||||||
|
|
||||||
def _updateRoomInfo(self, json):
|
def _updateRoomPopularity(self, _data):
|
||||||
if "Msg" in json:
|
"""
|
||||||
if "member_count" in json["Msg"]:
|
更新房间人气的方法
|
||||||
self.roomMember = json["Msg"]["member_count"]
|
Update Room Popularity
|
||||||
if "popularity" in json["Msg"]:
|
:param _data: Received Message
|
||||||
self.roomPopularity = json["Msg"]["popularity"]
|
"""
|
||||||
elif "data" in json:
|
if "extra" in _data:
|
||||||
if "popularity" in json["data"]:
|
if "member_count" in _data["extra"] and _data["extra"]["member_count"] > 0:
|
||||||
self.roomPopularity = json["data"]["popularity"]
|
self.roomPopularity = _data["extra"]["member_count"]
|
||||||
|
if "data" in _data:
|
||||||
|
if "popularity" in _data["data"]:
|
||||||
|
self.roomPopularity = _data["data"]["popularity"]
|
||||||
|
|
||||||
def apiChangedError(self, msg: str, *args):
|
def getJson(self, url, **kwargs):
|
||||||
|
if "timeout" not in kwargs:
|
||||||
|
kwargs["timeout"] = 10
|
||||||
|
try:
|
||||||
|
p = self.s.get(url, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
print("网络请求失败")
|
||||||
|
if DEBUG:
|
||||||
|
print("GET")
|
||||||
|
print("URL", url)
|
||||||
|
print("ERR ", e.__str__())
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return p.json()
|
||||||
|
except Exception as e:
|
||||||
|
print("解析请求失败")
|
||||||
|
if DEBUG:
|
||||||
|
print("GET JSON")
|
||||||
|
print("URL", url)
|
||||||
|
print("CNT", p.text)
|
||||||
|
print("ERR ", e.__str__())
|
||||||
|
return None
|
||||||
|
|
||||||
|
def postJson(self, url, data, **kwargs):
|
||||||
|
if "timeout" not in kwargs:
|
||||||
|
kwargs["timeout"] = 10
|
||||||
|
try:
|
||||||
|
p = self.s.post(url, data=data, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
print("网络请求失败")
|
||||||
|
if DEBUG:
|
||||||
|
print("POST")
|
||||||
|
print("URL", url)
|
||||||
|
print("DATA", data)
|
||||||
|
print("ERR ", e.__str__())
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return p.json()
|
||||||
|
except Exception as e:
|
||||||
|
print("解析请求失败")
|
||||||
|
if DEBUG:
|
||||||
|
print("POST JSON")
|
||||||
|
print("URL", url)
|
||||||
|
print("DATA", data)
|
||||||
|
print("CNT", p.text)
|
||||||
|
print("HDR", p.headers)
|
||||||
|
print("ERR ", e.__str__())
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def apiChangedError(msg: str, *args):
|
||||||
|
"""
|
||||||
|
API发生更改时的提示
|
||||||
|
Warning while Detected Api has Changed
|
||||||
|
:param msg: 提示信息
|
||||||
|
:param args: DEBUG模式下,显示更多信息
|
||||||
|
"""
|
||||||
print(msg)
|
print(msg)
|
||||||
|
if DEBUG:
|
||||||
print(*args)
|
print(*args)
|
||||||
|
|
||||||
def onPresent(self, gift: Gift):
|
def onPresent(self, gift: Gift):
|
||||||
print("礼物连击 : ", gift)
|
"""
|
||||||
|
礼物连击中的消息
|
||||||
|
Message On Sending Presents
|
||||||
|
:param gift: Struct of Gift Message
|
||||||
|
"""
|
||||||
|
print("礼物连击 :", gift)
|
||||||
|
|
||||||
def onPresentEnd(self, gift: Gift):
|
def onPresentEnd(self, gift: Gift):
|
||||||
|
"""
|
||||||
|
礼物送完了的提示信息
|
||||||
|
Message On Finished Send Present
|
||||||
|
:param gift: Struct of Gift Message
|
||||||
|
"""
|
||||||
print("感谢", gift)
|
print("感谢", gift)
|
||||||
|
|
||||||
def onAd(self, i):
|
def onAd(self, i):
|
||||||
|
"""
|
||||||
|
全局广播
|
||||||
|
All Channel Broadcasting Message( Just An Ad )
|
||||||
|
:param i: JSON DATA if you wanna using it
|
||||||
|
"""
|
||||||
# print(i)
|
# print(i)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def onChat(self, chat: Chat):
|
def onChat(self, chat: Chat):
|
||||||
|
"""
|
||||||
|
聊天信息
|
||||||
|
On Chatting
|
||||||
|
:param chat: Struct of Chat Message
|
||||||
|
"""
|
||||||
|
if not chat.isFiltered:
|
||||||
print(chat)
|
print(chat)
|
||||||
|
|
||||||
def onEnter(self, msg: MemberMsg):
|
def onEnter(self, msg: MemberMsg):
|
||||||
print("提示 : ", msg)
|
"""
|
||||||
|
进入房间消息
|
||||||
|
On Entering Room
|
||||||
|
:param msg: Struct of Member Message
|
||||||
|
"""
|
||||||
|
print("提示 :", msg)
|
||||||
|
|
||||||
def onSubscribe(self, user: User):
|
def onSubscribe(self, user: User):
|
||||||
print("消息 : ", user, "关注了主播")
|
"""
|
||||||
|
关注主播时的消息
|
||||||
|
On Subscribe
|
||||||
|
:param user: Struct of User Message
|
||||||
|
"""
|
||||||
|
print("消息 :", user, "关注了主播")
|
||||||
|
|
||||||
def onJoin(self, user: User):
|
def onJoin(self, user: User):
|
||||||
print("感谢", user, "加入了粉丝团")
|
"""
|
||||||
|
加入粉丝团消息
|
||||||
|
:param user:
|
||||||
|
"""
|
||||||
|
print("欢迎", user, "加入了粉丝团")
|
||||||
|
|
||||||
def onMessage(self, msg: str):
|
def onMessage(self, msg: str):
|
||||||
print("消息 : ", msg)
|
"""
|
||||||
|
系统消息
|
||||||
|
:param msg:
|
||||||
|
"""
|
||||||
|
print("消息 :", msg)
|
||||||
|
|
||||||
def onLike(self, user: User):
|
def onLike(self, user: User):
|
||||||
|
"""
|
||||||
|
点击喜欢的消息
|
||||||
|
On Like
|
||||||
|
:param user:
|
||||||
|
"""
|
||||||
print("用户", user, "点了喜欢")
|
print("用户", user, "点了喜欢")
|
||||||
|
|
||||||
def onLeave(self, json: any):
|
def onLeave(self, json: any):
|
||||||
print("消息 : ", "主播离开一小会")
|
"""
|
||||||
|
下播消息
|
||||||
|
On Liver Leave
|
||||||
|
:param json:
|
||||||
|
"""
|
||||||
|
print("消息 :", "主播离开了")
|
||||||
|
self.updRoomInfo()
|
||||||
|
|
||||||
def _enterRoom(self):
|
def _checkUsernameIsMatched(self, compare=None):
|
||||||
if not self.isValidRoom:
|
"""
|
||||||
return
|
验证主播名字是自己想要的那个
|
||||||
p = s.post("https://live.ixigua.com/api/room/enter/{roomID}".format(roomID=self.roomID))
|
Check name matched
|
||||||
if DEBUG:
|
:return: bool: 是否匹配
|
||||||
print(p.text)
|
"""
|
||||||
|
if compare is None:
|
||||||
|
compare = self.broadcaster
|
||||||
|
if self.name is None or compare is None:
|
||||||
|
return False
|
||||||
|
return self.name == compare.__str__() or compare.__repr__() in self.name or self.name in compare.__repr__()
|
||||||
|
|
||||||
def updRoomInfo(self):
|
def _forceSearchUser(self):
|
||||||
p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=self.room))
|
"""
|
||||||
if DEBUG:
|
搜索主播名
|
||||||
print(p.text)
|
:return:
|
||||||
d = p.json()
|
"""
|
||||||
if "data" not in d or "title" not in d["data"] or "id" not in d["data"]:
|
_formatData = {"TIMESTAMP": time.time() * 1000, "keyword": self.name}
|
||||||
self.apiChangedError("无法获取RoomID,请与我联系")
|
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||||
return
|
_formatData['COMMON'] = _COMMON
|
||||||
self.isValidRoom = True
|
_url = SEARCH_USER_API.format_map(_formatData)
|
||||||
self._rawRoomInfo = d["data"]
|
d = self.getJson(_url)
|
||||||
self.roomLiver = User(d)
|
if d is None:
|
||||||
self.roomTitle = d["data"]["title"]
|
print("搜索接口请求失败")
|
||||||
self.roomID = d["data"]["id"]
|
return False
|
||||||
self._updateRoomInfo(d)
|
self.broadcaster = None
|
||||||
if "status" in d["data"] and d["data"]["status"] == 2:
|
self.isValidUser = False
|
||||||
self.isLive = True
|
self.isLive = False
|
||||||
|
if "data" in d and d["data"] is not None:
|
||||||
|
for i in d["data"]:
|
||||||
|
if self.broadcaster is not None:
|
||||||
|
break
|
||||||
|
if i["card_type"] != 3:
|
||||||
|
continue
|
||||||
|
if "search_data" not in i or len(i["search_data"]) == 0:
|
||||||
|
break
|
||||||
|
for _j in i["search_data"]:
|
||||||
|
if "room" in _j:
|
||||||
|
_user = User(_j["room"])
|
||||||
|
self.roomID = _j["room"]["room_id"]
|
||||||
|
self.isLive = _j["room"]["is_living"]
|
||||||
|
if self._checkUsernameIsMatched(_user):
|
||||||
|
self.isValidUser = True
|
||||||
|
self.broadcaster = _user
|
||||||
|
break
|
||||||
|
self._updRoomAt = datetime.now()
|
||||||
|
return self._updateUserInfo()
|
||||||
|
|
||||||
|
def _updateUserInfo(self):
|
||||||
|
"""
|
||||||
|
获取用户信息
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.broadcaster is None:
|
||||||
|
self.isValidUser = False
|
||||||
|
return False
|
||||||
|
self.isLive = False
|
||||||
|
_formatData = {"TIMESTAMP": time.time() * 1000, "userId": self.broadcaster.ID}
|
||||||
|
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||||
|
_formatData['COMMON'] = _COMMON
|
||||||
|
_url = USER_INFO_API.format_map(_formatData)
|
||||||
|
d = self.getJson(_url)
|
||||||
|
if d is None:
|
||||||
|
print("获取用户信息失败")
|
||||||
|
return False
|
||||||
|
self.isValidUser = d["status"] == 0
|
||||||
|
_d = d.get('data', {})
|
||||||
|
if "user_home_info" not in _d and _d['user_home_info']['user_info'] is None:
|
||||||
|
self.apiChangedError("Api发生改变,请及时联系我", d)
|
||||||
|
return False
|
||||||
|
self._updRoomAt = datetime.now()
|
||||||
|
self.broadcaster = User(_d['user_home_info'])
|
||||||
|
if not self._checkUsernameIsMatched():
|
||||||
|
self.isLive = False
|
||||||
|
return False
|
||||||
|
self.isLive = 'user_live_info_list' in _d
|
||||||
|
if self.isLive and len(_d['user_live_info_list']) != 0:
|
||||||
|
# 既然有长度,默认个0应该没事
|
||||||
|
self._rawRoomInfo = _d['user_live_info_list'][0]['live_info']
|
||||||
else:
|
else:
|
||||||
self.isLive = False
|
self.isLive = False
|
||||||
|
if self.isLive:
|
||||||
|
self.roomID = self._rawRoomInfo['room_id']
|
||||||
|
return self._getRoomInfo(True)
|
||||||
|
return self.isLive
|
||||||
|
|
||||||
|
def _getRoomInfo(self, force=False):
|
||||||
|
if self.roomID == 0 or not self.roomID:
|
||||||
|
self.isLive = False
|
||||||
|
return False
|
||||||
|
if (self._updRoomAt + timedelta(minutes=3) > datetime.now()) and not force:
|
||||||
|
return self.isLive
|
||||||
|
_formatData = {"TIMESTAMP": time.time() * 1000}
|
||||||
|
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||||
|
_formatData['COMMON'] = _COMMON
|
||||||
|
_formatData['WEBCAST'] = WEBCAST_GET_PARAMS
|
||||||
|
_url = ROOM_INFO_API.format_map(_formatData)
|
||||||
|
_postData = ROOM_ENTER_POST_PARAMS.format_map({'roomId': self.roomID})
|
||||||
|
_headers = {"response-format": "json",
|
||||||
|
'Connection': "keep-alive",
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'Content-Length': str(len(_postData)),
|
||||||
|
**COMMON_HEADERS,
|
||||||
|
}
|
||||||
|
d = self.postJson(_url, _postData, headers=_headers)
|
||||||
|
self.isLive = False
|
||||||
|
if d is None:
|
||||||
|
print("获取房间信息接口请求失败")
|
||||||
|
return False
|
||||||
|
if d["status_code"] != 0:
|
||||||
|
print("接口提示:【{}】".format(d["data"]["message"]))
|
||||||
|
return False
|
||||||
|
self._rawRoomInfo = d["data"]
|
||||||
|
self.isLive = self._rawRoomInfo["status"] == 2
|
||||||
|
self._updRoomAt = datetime.now()
|
||||||
|
self._updateRoomPopularity(d)
|
||||||
|
return self.isLive
|
||||||
|
|
||||||
|
def updRoomInfo(self, force=False):
|
||||||
|
"""
|
||||||
|
更新房间信息
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not force and (self._updRoomAt + timedelta(minutes=2) > datetime.now()):
|
||||||
|
return self.isLive
|
||||||
|
if not self.isValidUser:
|
||||||
|
return self._forceSearchUser()
|
||||||
|
elif not self.isLive:
|
||||||
|
return self._updateUserInfo()
|
||||||
|
else:
|
||||||
|
return self._getRoomInfo(force)
|
||||||
|
|
||||||
|
def updGiftInfo(self):
|
||||||
|
self.updRoomInfo()
|
||||||
|
_formatData = {"TIMESTAMP": time.time() * 1000, "roomId": self.roomID}
|
||||||
|
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||||
|
_formatData['COMMON'] = _COMMON
|
||||||
|
_formatData['WEBCAST'] = WEBCAST_GET_PARAMS
|
||||||
|
_url = GIFT_DATA_API.format_map(_formatData)
|
||||||
|
d = self.getJson(_url)
|
||||||
|
if d is None or d["status_code"] != 0:
|
||||||
|
return "异常"
|
||||||
|
elif 'pages' in d["data"]:
|
||||||
|
for _page in d["data"]['pages']:
|
||||||
|
if 'gifts' in _page:
|
||||||
|
for _gift in _page['gifts']:
|
||||||
|
Gift.addGift(_gift)
|
||||||
|
return len(Gift.giftList)
|
||||||
|
|
||||||
def getDanmaku(self):
|
def getDanmaku(self):
|
||||||
if not self.isValidRoom:
|
"""
|
||||||
return
|
获取弹幕
|
||||||
p = s.get("https://live.ixigua.com/api/msg/list/{roomID}?AnchorID={room}&Cursor={cursor}".format(
|
"""
|
||||||
roomID=self.roomID,
|
|
||||||
room=self.room,
|
|
||||||
cursor=self._cursor
|
|
||||||
))
|
|
||||||
d = p.json()
|
|
||||||
if "data" not in d or "Extra" not in d["data"] or "Cursor" not in d["data"]["Extra"]:
|
|
||||||
if DEBUG:
|
|
||||||
print(d)
|
|
||||||
self.apiChangedError("数据结构改变,请与我联系")
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
self._cursor = d["data"]["Extra"]["Cursor"]
|
|
||||||
if DEBUG:
|
|
||||||
print("Cursor", self._cursor)
|
|
||||||
if "LiveMsgs" not in d["data"]:
|
|
||||||
self.updRoomInfo()
|
self.updRoomInfo()
|
||||||
|
if not self.isLive:
|
||||||
return
|
return
|
||||||
for i in d['data']['LiveMsgs']:
|
_formatData = {"TIMESTAMP": time.time() * 1000, "roomId": self.roomID}
|
||||||
if DEBUG:
|
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||||
print(i)
|
_formatData['COMMON'] = _COMMON
|
||||||
if "Method" not in i:
|
_formatData['WEBCAST'] = WEBCAST_GET_PARAMS
|
||||||
continue
|
_url = DANMAKU_GET_API.format_map(_formatData)
|
||||||
if i['Method'] == "VideoLivePresentMessage":
|
p = self.s.post(_url, data="room_id={roomId}&fetch_rule=0&cursor={cursor}&"
|
||||||
self.onPresent(Gift(i))
|
"resp_content_type=protobuf&live_id=3&user_id=0&identity=audience&"
|
||||||
elif i['Method'] == "VideoLivePresentEndTipMessage":
|
"last_rtt=85&internal_ext={ext}"
|
||||||
self.onPresentEnd(Gift(i))
|
.format_map({"roomId":self.roomID, "cursor": self._cursor, "ext": self._ext}),
|
||||||
elif i['Method'] == "VideoLiveRoomAdMessage":
|
headers={"Content-Type": "application/x-www-form-urlencoded"})
|
||||||
self.onAd(i)
|
if p.status_code != 200:
|
||||||
elif i['Method'] == "VideoLiveChatMessage":
|
return
|
||||||
self.onChat(Chat(i))
|
data = XiguaLive()
|
||||||
elif i['Method'] == "VideoLiveMemberMessage":
|
data.ParseFromString(p.content)
|
||||||
self._updateRoomInfo(i)
|
self._cursor = data.cursor
|
||||||
self.onEnter(MemberMsg(i))
|
self._ext = data.internal_ext
|
||||||
elif i['Method'] == "VideoLiveSocialMessage":
|
for _each in data.data:
|
||||||
self.onSubscribe(User(i))
|
if _each.method == "WebcastGiftMessage":
|
||||||
elif i['Method'] == "VideoLiveJoinDiscipulusMessage":
|
_gift = Gift(_each.raw)
|
||||||
self.onJoin(User(i))
|
if _gift.isAnimate() or _gift.isFinished:
|
||||||
elif i['Method'] == "VideoLiveControlMessage":
|
self.onPresentEnd(_gift)
|
||||||
print("消息:", "主播离开一小会")
|
else:
|
||||||
elif i['Method'] == "VideoLiveDiggMessage":
|
self.onPresent(_gift)
|
||||||
self.onLike(User(i))
|
elif _each.method == "WebcastChatMessage":
|
||||||
|
_chat = Chat(_each.raw)
|
||||||
|
self.onChat(_chat)
|
||||||
|
elif _each.method == "WebcastControlMessage":
|
||||||
|
# 下播的时候会有个这个
|
||||||
|
self.onLeave(None)
|
||||||
|
elif _each.method == "WebcastSocialMessage":
|
||||||
|
_socialMessage = SocialMessage()
|
||||||
|
_socialMessage.ParseFromString(_each.raw)
|
||||||
|
_user = User(_socialMessage.user)
|
||||||
|
self.onSubscribe(_user)
|
||||||
|
elif _each.method == "WebcastFansclubMessage":
|
||||||
|
_fansClubMessage = FansClubMessage()
|
||||||
|
_fansClubMessage.ParseFromString(_each.raw)
|
||||||
|
# 升级是1,加入是2
|
||||||
|
if _fansClubMessage.type == 2:
|
||||||
|
_user = User(_fansClubMessage.user)
|
||||||
|
self.onJoin(_user)
|
||||||
|
else:
|
||||||
|
self.onMessage(_fansClubMessage.content)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def updateAt(self):
|
||||||
|
return self._updRoomAt
|
||||||
|
|
||||||
|
|
||||||
|
def public_hello():
|
||||||
|
print("西瓜直播弹幕助手 by JerryYan")
|
||||||
|
print("接口版本:{version_name}({version_code_full})".format_map(VERSION_INFO))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
room = 97621754276 # 永恒
|
name = "永恒de草薙"
|
||||||
# room = 75366565294
|
if len(sys.argv) > 2:
|
||||||
# room = 83940182312 #Dae
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
if sys.argv[-1] == "d":
|
if sys.argv[-1] == "d":
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
try:
|
name = sys.argv[1]
|
||||||
room = int(sys.argv[1])
|
public_hello()
|
||||||
except ValueError:
|
print("搜索【", name, "】", end="\t", flush=True)
|
||||||
pass
|
api = XiGuaLiveApi(name)
|
||||||
print("西瓜直播弹幕助手 by JerryYan")
|
if not api.isValidUser:
|
||||||
api = XiGuaLiveApi(room)
|
input("用户不存在")
|
||||||
print("进入", api.roomLiver, "的直播间")
|
|
||||||
if not api.isValidRoom:
|
|
||||||
input("房间不存在")
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
print("OK")
|
||||||
|
print(api.broadcaster.__repr__())
|
||||||
|
print("更新房间信息,请稍后", end="\t", flush=True)
|
||||||
|
if api.updRoomInfo(True):
|
||||||
|
print("OK")
|
||||||
|
else:
|
||||||
|
print("FAIL")
|
||||||
|
print("更新房间礼物信息", end="\t", flush=True)
|
||||||
|
__res = api.updGiftInfo()
|
||||||
|
if __res < 0:
|
||||||
|
print("FAIL")
|
||||||
|
else:
|
||||||
|
print('OK\n礼物种数:', __res)
|
||||||
print("=" * 30)
|
print("=" * 30)
|
||||||
while True:
|
while True:
|
||||||
if api.isLive:
|
if api.isLive:
|
||||||
try:
|
try:
|
||||||
api.getDanmaku()
|
api.getDanmaku()
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
except requests.exceptions.BaseHTTPError:
|
||||||
|
print("网络错误,请确认网络")
|
||||||
|
time.sleep(5)
|
||||||
|
# except Exception as e:
|
||||||
|
# print(e)
|
||||||
else:
|
else:
|
||||||
print("主播未开播,等待1分钟后重试")
|
print("主播未开播,等待1分钟后重试")
|
||||||
time.sleep(60)
|
time.sleep(60)
|
||||||
api.updRoomInfo()
|
api.updRoomInfo(True)
|
||||||
|
393
bilibili.py
393
bilibili.py
@ -1,159 +1,19 @@
|
|||||||
# coding=utf-8
|
from bilibiliuploader import core, VideoPart
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import rsa
|
|
||||||
import math
|
|
||||||
import base64
|
|
||||||
import hashlib
|
|
||||||
import requests
|
|
||||||
from urllib import parse
|
|
||||||
|
|
||||||
|
|
||||||
class VideoPart:
|
|
||||||
def __init__(self, path, title='', desc=''):
|
|
||||||
self.path = path
|
|
||||||
self.title = title
|
|
||||||
self.desc = desc
|
|
||||||
|
|
||||||
class Bilibili:
|
class Bilibili:
|
||||||
def __init__(self, cookie=None):
|
def __init__(self):
|
||||||
self.videos = []
|
self.access_token = ""
|
||||||
self.session = requests.session()
|
self.session_id = ""
|
||||||
if cookie:
|
self.user_id = ""
|
||||||
self.session.headers["cookie"] = cookie
|
self.parts = []
|
||||||
self.csrf = re.search('bili_jct=(.*?);', cookie).group(1)
|
|
||||||
self.mid = re.search('DedeUserID=(.*?);', cookie).group(1)
|
|
||||||
self.session.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
|
|
||||||
self.session.headers['Referer'] = 'https://space.bilibili.com/{mid}/#!/'.format(mid=self.mid)
|
|
||||||
# session.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
|
|
||||||
# session.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
||||||
|
|
||||||
def login(self, user, pwd):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:param user: username
|
|
||||||
:type user: str
|
|
||||||
:param pwd: password
|
|
||||||
:type pwd: str
|
|
||||||
:return: if success return True
|
|
||||||
else return msg json
|
|
||||||
"""
|
|
||||||
APPKEY = '1d8b6e7d45233436'
|
|
||||||
ACTIONKEY = 'appkey'
|
|
||||||
BUILD = 520001
|
|
||||||
DEVICE = 'android'
|
|
||||||
MOBI_APP = 'android'
|
|
||||||
PLATFORM = 'android'
|
|
||||||
APPSECRET = '560c52ccd288fed045859ed18bffd973'
|
|
||||||
|
|
||||||
def md5(s):
|
|
||||||
h = hashlib.md5()
|
|
||||||
h.update(s.encode('utf-8'))
|
|
||||||
return h.hexdigest()
|
|
||||||
|
|
||||||
def sign(s):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:return: return sign
|
|
||||||
"""
|
|
||||||
return md5(s + APPSECRET)
|
|
||||||
|
|
||||||
def signed_body(body):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:return: body which be added sign
|
|
||||||
"""
|
|
||||||
if isinstance(body, str):
|
|
||||||
return body + '&sign=' + sign(body)
|
|
||||||
elif isinstance(body, dict):
|
|
||||||
ls = []
|
|
||||||
for k, v in body.items():
|
|
||||||
ls.append(k + '=' + v)
|
|
||||||
body['sign'] = sign('&'.join(ls))
|
|
||||||
return body
|
|
||||||
|
|
||||||
def getkey():
|
|
||||||
"""
|
|
||||||
|
|
||||||
:return: hash, key
|
|
||||||
"""
|
|
||||||
r = self.session.post(
|
|
||||||
'https://passport.bilibili.com/api/oauth2/getKey',
|
|
||||||
signed_body({'appkey': APPKEY}),
|
|
||||||
)
|
|
||||||
# {"ts":1544152439,"code":0,"data":{"hash":"99c7573759582e0b","key":"-----BEGIN PUBLIC----- -----END PUBLIC KEY-----\n"}}
|
|
||||||
json = r.json()
|
|
||||||
data = json['data']
|
|
||||||
return data['hash'], data['key']
|
|
||||||
|
|
||||||
def cnn_captcha(img):
|
|
||||||
url = "http://47.95.255.188:5000/code"
|
|
||||||
data = {"image": img}
|
|
||||||
r = requests.post(url, data=data)
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
self.session.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
||||||
h, k = getkey()
|
|
||||||
pwd = base64.b64encode(
|
|
||||||
rsa.encrypt(
|
|
||||||
(h + pwd).encode('utf-8'),
|
|
||||||
rsa.PublicKey.load_pkcs1_openssl_pem(k.encode())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
user = parse.quote_plus(user)
|
|
||||||
pwd = parse.quote_plus(pwd)
|
|
||||||
|
|
||||||
r = self.session.post(
|
|
||||||
'https://passport.bilibili.com/api/v2/oauth2/login',
|
|
||||||
signed_body('appkey={appkey}&password={password}&username={username}'
|
|
||||||
.format(appkey=APPKEY, username=user, password=pwd))
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
json = r.json()
|
|
||||||
except:
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
if json['code'] == -105:
|
|
||||||
# need captcha
|
|
||||||
self.session.headers['cookie'] = 'sid=xxxxxxxx'
|
|
||||||
r = self.session.get('https://passport.bilibili.com/captcha')
|
|
||||||
captcha = cnn_captcha(base64.b64encode(r.content))
|
|
||||||
r = self.session.post(
|
|
||||||
'https://passport.bilibili.com/api/v2/oauth2/login',
|
|
||||||
signed_body('actionKey={actionKey}&appkey={appkey}&build={build}&captcha={captcha}&device={device}'
|
|
||||||
'&mobi_app={mobi_app}&password={password}&platform={platform}&username={username}'
|
|
||||||
.format(actionKey=ACTIONKEY,
|
|
||||||
appkey=APPKEY,
|
|
||||||
build=BUILD,
|
|
||||||
captcha=captcha,
|
|
||||||
device=DEVICE,
|
|
||||||
mobi_app=MOBI_APP,
|
|
||||||
password=pwd,
|
|
||||||
platform=PLATFORM,
|
|
||||||
username=user)),
|
|
||||||
)
|
|
||||||
json = r.json()
|
|
||||||
|
|
||||||
|
|
||||||
if json['code'] is not 0:
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
ls = []
|
|
||||||
for item in json['data']['cookie_info']['cookies']:
|
|
||||||
ls.append(item['name'] + '=' + item['value'])
|
|
||||||
cookie = '; '.join(ls)
|
|
||||||
self.session.headers["cookie"] = cookie
|
|
||||||
|
|
||||||
self.csrf = re.search('bili_jct=(.*?);', cookie).group(1)
|
|
||||||
self.mid = re.search('DedeUserID=(.*?);', cookie).group(1)
|
|
||||||
self.session.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
|
|
||||||
self.session.headers['Referer'] = 'https://space.bilibili.com/{mid}/#!/'.format(mid=self.mid)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
from Common import appendOperation
|
||||||
|
with open("access_token", "r") as f:
|
||||||
|
self.access_token = f.read(64).strip()
|
||||||
|
self.session_id, self.user_id, expires = core.login_by_access_token(self.access_token)
|
||||||
|
appendOperation("B站登录,UID【{}】,过期时间【{}】".format(self.user_id, expires))
|
||||||
|
|
||||||
def upload(self,
|
def upload(self,
|
||||||
parts,
|
parts,
|
||||||
@ -186,12 +46,41 @@ class Bilibili:
|
|||||||
:type no_reprint: int
|
:type no_reprint: int
|
||||||
"""
|
"""
|
||||||
self.preUpload(parts)
|
self.preUpload(parts)
|
||||||
self.finishUpload(title,tid,tag,desc,source,cover,no_reprint)
|
self.finishUpload(title, tid, tag, desc, source, cover, no_reprint)
|
||||||
|
self.clear()
|
||||||
|
|
||||||
def preUpload(self,parts):
|
def preUpload(self, parts, max_retry=5):
|
||||||
"""
|
"""
|
||||||
|
:param max_retry:
|
||||||
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
|
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
|
||||||
:type parts: VideoPart or list<VideoPart>
|
:type parts: VideoPart or list<VideoPart>
|
||||||
|
"""
|
||||||
|
from Common import appendUploadStatus, modifyLastUploadStatus, appendError
|
||||||
|
if not isinstance(parts, list):
|
||||||
|
parts = [parts]
|
||||||
|
|
||||||
|
def log_status(video_part: VideoPart, chunks_index: int, chunks_num: int):
|
||||||
|
modifyLastUploadStatus("Uploading >{}< @ {:.2f}%".format(video_part.path, 100.0 * chunks_index / chunks_num))
|
||||||
|
for part in parts:
|
||||||
|
appendUploadStatus("Start Uploading >{}<".format(part.path))
|
||||||
|
status = core.upload_video_part(self.access_token, self.session_id, self.user_id, part, max_retry, cb=log_status)
|
||||||
|
if status:
|
||||||
|
# 上传完毕
|
||||||
|
modifyLastUploadStatus("Upload >{}< Finished;【{}】".format(part.path, part.server_file_name))
|
||||||
|
self.parts.append(part)
|
||||||
|
else:
|
||||||
|
modifyLastUploadStatus("Upload >{}< Failed".format(part.path))
|
||||||
|
|
||||||
|
def finishUpload(self,
|
||||||
|
title,
|
||||||
|
tid,
|
||||||
|
tag,
|
||||||
|
desc,
|
||||||
|
source='',
|
||||||
|
cover='',
|
||||||
|
no_reprint=1,
|
||||||
|
):
|
||||||
|
"""
|
||||||
:param title: video's title
|
:param title: video's title
|
||||||
:type title: str
|
:type title: str
|
||||||
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
|
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
|
||||||
@ -207,186 +96,26 @@ class Bilibili:
|
|||||||
:type cover: str
|
:type cover: str
|
||||||
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
|
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
|
||||||
:type no_reprint: int
|
:type no_reprint: int
|
||||||
|
:param copyright: (optional) 0=转载的, 1=自制的(default)
|
||||||
|
:type copyright: int
|
||||||
"""
|
"""
|
||||||
|
from Common import appendUploadStatus, modifyLastUploadStatus, appendError
|
||||||
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
|
if len(self.parts) == 0:
|
||||||
if not isinstance(parts, list):
|
return
|
||||||
parts = [parts]
|
appendUploadStatus("[{}]投稿中,请稍后".format(title))
|
||||||
|
|
||||||
videos = []
|
|
||||||
for part in parts:
|
|
||||||
filepath = part.path
|
|
||||||
filename = os.path.basename(filepath)
|
|
||||||
filesize = os.path.getsize(filepath)
|
|
||||||
r = self.session.get('https://member.bilibili.com/preupload?'
|
|
||||||
'os=upos&upcdn=ws&name={name}&size={size}&r=upos&profile=ugcupos%2Fyb&ssl=0'
|
|
||||||
.format(name=filename, size=filesize))
|
|
||||||
"""return example
|
|
||||||
{
|
|
||||||
"upos_uri": "upos://ugc/i181012ws18x52mti3gg0h33chn3tyhp.mp4",
|
|
||||||
"biz_id": 58993125,
|
|
||||||
"endpoint": "//upos-hz-upcdnws.acgvideo.com",
|
|
||||||
"endpoints": [
|
|
||||||
"//upos-hz-upcdnws.acgvideo.com",
|
|
||||||
"//upos-hz-upcdntx.acgvideo.com"
|
|
||||||
],
|
|
||||||
"chunk_retry_delay": 3,
|
|
||||||
"chunk_retry": 200,
|
|
||||||
"chunk_size": 4194304,
|
|
||||||
"threads": 2,
|
|
||||||
"timeout": 900,
|
|
||||||
"auth": "os=upos&cdn=upcdnws&uid=&net_state=4&device=&build=&os_version=&ak=×tamp=&sign=",
|
|
||||||
"OK": 1
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
json = r.json()
|
|
||||||
upos_uri = json['upos_uri']
|
|
||||||
endpoint = json['endpoint']
|
|
||||||
auth = json['auth']
|
|
||||||
biz_id = json['biz_id']
|
|
||||||
chunk_size = json['chunk_size']
|
|
||||||
self.session.headers['X-Upos-Auth'] = auth # add auth header
|
|
||||||
r = self.session.post(
|
|
||||||
'https:{}/{}?uploads&output=json'.format(endpoint, upos_uri.replace('upos://', '')))
|
|
||||||
# {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"}
|
|
||||||
json = r.json()
|
|
||||||
upload_id = json['upload_id']
|
|
||||||
|
|
||||||
with open(filepath, 'rb') as f:
|
|
||||||
chunks_num = math.ceil(filesize / chunk_size)
|
|
||||||
chunks_index = -1
|
|
||||||
while True:
|
|
||||||
chunks_data = f.read(chunk_size)
|
|
||||||
if not chunks_data:
|
|
||||||
break
|
|
||||||
chunks_index += 1 # start with 0
|
|
||||||
r = self.session.put('https:{endpoint}/{upos_uri}?'
|
|
||||||
'partNumber={part_number}&uploadId={upload_id}&chunk={chunk}&chunks={chunks}&size={size}&start={start}&end={end}&total={total}'
|
|
||||||
.format(endpoint=endpoint,
|
|
||||||
upos_uri=upos_uri.replace('upos://', ''),
|
|
||||||
part_number=chunks_index + 1, # starts with 1
|
|
||||||
upload_id=upload_id,
|
|
||||||
chunk=chunks_index,
|
|
||||||
chunks=chunks_num,
|
|
||||||
size=len(chunks_data),
|
|
||||||
start=chunks_index * chunk_size,
|
|
||||||
end=chunks_index * chunk_size + len(chunks_data),
|
|
||||||
total=filesize,
|
|
||||||
),
|
|
||||||
chunks_data,
|
|
||||||
)
|
|
||||||
print('{} : UPLOAD {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), chunks_index,
|
|
||||||
chunks_num), r.text)
|
|
||||||
|
|
||||||
# NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769
|
|
||||||
self.session.post('https:{endpoint}/{upos_uri}?'
|
|
||||||
'output=json&name={name}&profile=ugcupos%2Fyb&uploadId={upload_id}&biz_id={biz_id}'
|
|
||||||
.format(endpoint=endpoint,
|
|
||||||
upos_uri=upos_uri.replace('upos://', ''),
|
|
||||||
name=filename,
|
|
||||||
upload_id=upload_id,
|
|
||||||
biz_id=biz_id,
|
|
||||||
),
|
|
||||||
{"parts": [{"partNumber": i, "eTag": "etag"} for i in range(1, chunks_num + 1)]},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0],
|
|
||||||
'title': part.title,
|
|
||||||
'desc': part.desc})
|
|
||||||
|
|
||||||
def finishUpload(self,
|
|
||||||
title,
|
|
||||||
tid,
|
|
||||||
tag,
|
|
||||||
desc,
|
|
||||||
source='',
|
|
||||||
cover='',
|
|
||||||
no_reprint=1,
|
|
||||||
):
|
|
||||||
copyright = 2 if source else 1
|
copyright = 2 if source else 1
|
||||||
r = self.session.post('https://member.bilibili.com/x/vu/web/add?csrf=' + self.csrf,
|
try:
|
||||||
json={
|
avid, bvid = core.upload(self.access_token, self.session_id, self.user_id, self.parts, copyright,
|
||||||
"copyright" : copyright,
|
title=title, tid=tid, tag=','.join(tag), desc=desc, source=source, cover=cover, no_reprint=no_reprint)
|
||||||
"source" : source,
|
modifyLastUploadStatus("[{}]投稿成功;AVID【{}】,BVID【{}】".format(title, avid, bvid))
|
||||||
"title" : title,
|
self.clear()
|
||||||
"tid" : tid,
|
except Exception as e:
|
||||||
"tag" : ','.join(tag),
|
modifyLastUploadStatus("[{}]投稿失败".format(title))
|
||||||
"no_reprint": no_reprint,
|
appendError(e)
|
||||||
"desc" : desc,
|
|
||||||
"cover" : cover,
|
|
||||||
"mission_id": 0,
|
|
||||||
"order_id" : 0,
|
|
||||||
"videos" : self.videos}
|
|
||||||
)
|
|
||||||
print(r.text)
|
|
||||||
for _p in self.videos:
|
|
||||||
os.remove(_p.path)
|
|
||||||
|
|
||||||
|
|
||||||
|
def reloadFromPrevious(self):
|
||||||
|
...
|
||||||
|
|
||||||
def addChannel(self, name, intro=''):
|
def clear(self):
|
||||||
"""
|
self.parts = []
|
||||||
|
|
||||||
:param name: channel's name
|
|
||||||
:type name: str
|
|
||||||
:param intro: channel's introduction
|
|
||||||
:type intro: str
|
|
||||||
"""
|
|
||||||
r = self.session.post(
|
|
||||||
url='https://space.bilibili.com/ajax/channel/addChannel',
|
|
||||||
data={
|
|
||||||
'name' : name,
|
|
||||||
'intro': intro,
|
|
||||||
'aids' : '',
|
|
||||||
'csrf' : self.csrf,
|
|
||||||
},
|
|
||||||
# name=123&intro=123&aids=&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497077610768
|
|
||||||
|
|
||||||
)
|
|
||||||
# return
|
|
||||||
# {"status":true,"data":{"cid":"15812"}}
|
|
||||||
print(r.json())
|
|
||||||
|
|
||||||
def channel_addVideo(self, cid, aids):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:param cid: channel's id
|
|
||||||
:type cid: int
|
|
||||||
:param aids: videos' id
|
|
||||||
:type aids: list<int>
|
|
||||||
"""
|
|
||||||
|
|
||||||
r = self.session.post(
|
|
||||||
url='https://space.bilibili.com/ajax/channel/addVideo',
|
|
||||||
data={
|
|
||||||
'aids': '%2C'.join(aids),
|
|
||||||
'cid' : cid,
|
|
||||||
'csrf': self.csrf
|
|
||||||
}
|
|
||||||
# aids=9953555%2C9872953&cid=15814&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497079332679
|
|
||||||
)
|
|
||||||
print(r.json())
|
|
||||||
|
|
||||||
def cover_up(self, img):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:param img: img path or stream
|
|
||||||
:type img: str or BufferedReader
|
|
||||||
:return: img URL
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(img, str):
|
|
||||||
f = open(img, 'rb')
|
|
||||||
else:
|
|
||||||
f = img
|
|
||||||
r = self.session.post(
|
|
||||||
url='https://member.bilibili.com/x/vu/web/cover/up',
|
|
||||||
data={
|
|
||||||
'cover': b'data:image/jpeg;base64,' + (base64.b64encode(f.read())),
|
|
||||||
'csrf': self.csrf,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
# print(r.text)
|
|
||||||
# {"code":0,"data":{"url":"http://i0.hdslb.com/bfs/archive/67db4a6eae398c309244e74f6e85ae8d813bd7c9.jpg"},"message":"","ttl":1}
|
|
||||||
return r.json()['data']['url']
|
|
||||||
|
|
4
bilibiliuploader/README.md
Normal file
4
bilibiliuploader/README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
修改自
|
||||||
|
https://github.com/FortuneDayssss/BilibiliUploader/
|
||||||
|
|
||||||
|
LICENSE:GPL
|
4
bilibiliuploader/__init__.py
Normal file
4
bilibiliuploader/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .bilibiliuploader import BilibiliUploader
|
||||||
|
from .core import VideoPart
|
||||||
|
|
||||||
|
__version__ = '0.0.6'
|
118
bilibiliuploader/bilibiliuploader.py
Normal file
118
bilibiliuploader/bilibiliuploader.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import bilibiliuploader.core as core
|
||||||
|
from bilibiliuploader.util import cipher
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class BilibiliUploader():
|
||||||
|
def __init__(self):
|
||||||
|
self.access_token = None
|
||||||
|
self.refresh_token = None
|
||||||
|
self.sid = None
|
||||||
|
self.mid = None
|
||||||
|
|
||||||
|
def login(self, username, password):
|
||||||
|
code, self.access_token, self.refresh_token, self.sid, self.mid, _ = core.login(username, password)
|
||||||
|
if code != 0: # success
|
||||||
|
print("login fail, error code = {}".format(code))
|
||||||
|
|
||||||
|
def login_by_access_token(self, access_token, refresh_token=None):
|
||||||
|
self.access_token = access_token
|
||||||
|
self.refresh_token = refresh_token
|
||||||
|
self.sid, self.mid, _ = core.login_by_access_token(access_token)
|
||||||
|
|
||||||
|
def login_by_access_token_file(self, file_name):
|
||||||
|
with open(file_name, "r") as f:
|
||||||
|
login_data = json.loads(f.read())
|
||||||
|
self.access_token = login_data["access_token"]
|
||||||
|
self.refresh_token = login_data["refresh_token"]
|
||||||
|
self.sid, self.mid, _ = core.login_by_access_token(self.access_token)
|
||||||
|
|
||||||
|
def save_login_data(self, file_name=None):
|
||||||
|
login_data = json.dumps(
|
||||||
|
{
|
||||||
|
"access_token": self.access_token,
|
||||||
|
"refresh_token": self.refresh_token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with open(file_name, "w+") as f:
|
||||||
|
f.write(login_data)
|
||||||
|
finally:
|
||||||
|
return login_data
|
||||||
|
|
||||||
|
|
||||||
|
def upload(self,
|
||||||
|
parts,
|
||||||
|
copyright: int,
|
||||||
|
title: str,
|
||||||
|
tid: int,
|
||||||
|
tag: str,
|
||||||
|
desc: str,
|
||||||
|
source: str = '',
|
||||||
|
cover: str = '',
|
||||||
|
no_reprint: int = 0,
|
||||||
|
open_elec: int = 1,
|
||||||
|
max_retry: int = 5,
|
||||||
|
thread_pool_workers: int = 1):
|
||||||
|
return core.upload(self.access_token,
|
||||||
|
self.sid,
|
||||||
|
self.mid,
|
||||||
|
parts,
|
||||||
|
copyright,
|
||||||
|
title,
|
||||||
|
tid,
|
||||||
|
tag,
|
||||||
|
desc,
|
||||||
|
source,
|
||||||
|
cover,
|
||||||
|
no_reprint,
|
||||||
|
open_elec,
|
||||||
|
max_retry,
|
||||||
|
thread_pool_workers)
|
||||||
|
|
||||||
|
def edit(self,
|
||||||
|
avid=None,
|
||||||
|
bvid=None,
|
||||||
|
parts=None,
|
||||||
|
insert_index=None,
|
||||||
|
copyright=None,
|
||||||
|
title=None,
|
||||||
|
tid=None,
|
||||||
|
tag=None,
|
||||||
|
desc=None,
|
||||||
|
source=None,
|
||||||
|
cover=None,
|
||||||
|
no_reprint=None,
|
||||||
|
open_elec=None,
|
||||||
|
max_retry: int = 5,
|
||||||
|
thread_pool_workers: int = 1):
|
||||||
|
|
||||||
|
if not avid and not bvid:
|
||||||
|
print("please provide avid or bvid")
|
||||||
|
return None, None
|
||||||
|
if not avid:
|
||||||
|
avid = cipher.bv2av(bvid)
|
||||||
|
if not isinstance(parts, list):
|
||||||
|
parts = [parts]
|
||||||
|
if type(avid) is str:
|
||||||
|
avid = int(avid)
|
||||||
|
core.edit_videos(
|
||||||
|
self.access_token,
|
||||||
|
self.sid,
|
||||||
|
self.mid,
|
||||||
|
avid,
|
||||||
|
bvid,
|
||||||
|
parts,
|
||||||
|
insert_index,
|
||||||
|
copyright,
|
||||||
|
title,
|
||||||
|
tid,
|
||||||
|
tag,
|
||||||
|
desc,
|
||||||
|
source,
|
||||||
|
cover,
|
||||||
|
no_reprint,
|
||||||
|
open_elec,
|
||||||
|
max_retry,
|
||||||
|
thread_pool_workers
|
||||||
|
)
|
790
bilibiliuploader/core.py
Normal file
790
bilibiliuploader/core.py
Normal file
@ -0,0 +1,790 @@
|
|||||||
|
import requests
|
||||||
|
from datetime import datetime
|
||||||
|
from bilibiliuploader.util import cipher as cipher
|
||||||
|
from urllib import parse
|
||||||
|
import os
|
||||||
|
import math
|
||||||
|
import hashlib
|
||||||
|
from bilibiliuploader.util.retry import Retry
|
||||||
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# From PC ugc_assisstant
|
||||||
|
# APPKEY = 'aae92bc66f3edfab'
|
||||||
|
# APPSECRET = 'af125a0d5279fd576c1b4418a3e8276d'
|
||||||
|
APPKEY = '1d8b6e7d45233436'
|
||||||
|
APPSECRET = '560c52ccd288fed045859ed18bffd973'
|
||||||
|
LOGIN_APPKEY = '783bbb7264451d82'
|
||||||
|
|
||||||
|
# upload chunk size = 2MB
|
||||||
|
CHUNK_SIZE = 2 * 1024 * 1024
|
||||||
|
|
||||||
|
# captcha
|
||||||
|
CAPTCHA_RECOGNIZE_URL = "NOT SUPPORT"
|
||||||
|
|
||||||
|
|
||||||
|
class VideoPart:
|
||||||
|
"""
|
||||||
|
Video Part of a post.
|
||||||
|
每个对象代表一个分P
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
path: file path in local file system.
|
||||||
|
title: title of the video part.
|
||||||
|
desc: description of the video part.
|
||||||
|
server_file_name: file name in bilibili server. generated by pre-upload API.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, path, title='', desc='', server_file_name=None):
|
||||||
|
self.path = path
|
||||||
|
self.title = title
|
||||||
|
self.desc = desc
|
||||||
|
self.server_file_name = server_file_name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<{clazz}, path: {path}, title: {title}, desc: {desc}, server_file_name:{server_file_name}>' \
|
||||||
|
.format(clazz=self.__class__.__name__,
|
||||||
|
path=self.path,
|
||||||
|
title=self.title,
|
||||||
|
desc=self.desc,
|
||||||
|
server_file_name=self.server_file_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_key_old(sid=None, jsessionid=None):
|
||||||
|
"""
|
||||||
|
get public key, hash and session id for login.
|
||||||
|
Args:
|
||||||
|
sid: session id. only for captcha login.
|
||||||
|
jsessionid: j-session id. only for captcha login.
|
||||||
|
Returns:
|
||||||
|
hash: salt for password encryption.
|
||||||
|
pubkey: rsa public key for password encryption.
|
||||||
|
sid: session id.
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'Accept': "application/json, text/javascript, */*; q=0.01"
|
||||||
|
}
|
||||||
|
post_data = {
|
||||||
|
'appkey': APPKEY,
|
||||||
|
'platform': "pc",
|
||||||
|
'ts': str(int(datetime.now().timestamp()))
|
||||||
|
}
|
||||||
|
post_data['sign'] = cipher.sign_dict(post_data, APPSECRET)
|
||||||
|
cookie = {}
|
||||||
|
if sid:
|
||||||
|
cookie['sid'] = sid
|
||||||
|
if jsessionid:
|
||||||
|
cookie['JSESSIONID'] = jsessionid
|
||||||
|
r = requests.post(
|
||||||
|
# "https://passport.bilibili.com/api/oauth2/getKey",
|
||||||
|
"https://passport.bilibili.com/x/passport-login/web/key",
|
||||||
|
headers=headers,
|
||||||
|
data=post_data,
|
||||||
|
cookies=cookie
|
||||||
|
)
|
||||||
|
print(r.content.decode())
|
||||||
|
r_data = r.json()['data']
|
||||||
|
if sid:
|
||||||
|
return r_data['hash'], r_data['key'], sid
|
||||||
|
return r_data['hash'], r_data['key'], r.cookies['sid']
|
||||||
|
|
||||||
|
|
||||||
|
def get_key():
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'Accept': "application/json, text/javascript, */*; q=0.01"
|
||||||
|
}
|
||||||
|
params_data = {
|
||||||
|
'appkey': LOGIN_APPKEY,
|
||||||
|
# 'ts': str(int(datetime.now().timestamp()))
|
||||||
|
}
|
||||||
|
params_data['sign'] = cipher.login_sign_dict_bin(params_data)
|
||||||
|
r = requests.get(
|
||||||
|
"https://passport.bilibili.com/x/passport-login/web/key",
|
||||||
|
headers=headers,
|
||||||
|
params=params_data
|
||||||
|
)
|
||||||
|
r_data = r.json()['data']
|
||||||
|
return r_data['hash'], r_data['key'], ''
|
||||||
|
|
||||||
|
|
||||||
|
def get_capcha(sid):
|
||||||
|
headers = {
|
||||||
|
'User-Agent': '',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
}
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'appkey': APPKEY,
|
||||||
|
'platform': 'pc',
|
||||||
|
'ts': str(int(datetime.now().timestamp()))
|
||||||
|
}
|
||||||
|
params['sign'] = cipher.sign_dict(params, APPSECRET)
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
"https://passport.bilibili.com/captcha",
|
||||||
|
headers=headers,
|
||||||
|
params=params,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
print(r.status_code)
|
||||||
|
|
||||||
|
capcha_data = r.content
|
||||||
|
|
||||||
|
return r.cookies['JSESSIONID'], capcha_data
|
||||||
|
|
||||||
|
|
||||||
|
def recognize_captcha(img: bytes):
|
||||||
|
img_base64 = str(base64.b64encode(img), encoding='utf-8')
|
||||||
|
r = requests.post(
|
||||||
|
url=CAPTCHA_RECOGNIZE_URL,
|
||||||
|
data={'image': img_base64}
|
||||||
|
)
|
||||||
|
return r.content.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def login(username, password):
|
||||||
|
"""
|
||||||
|
bilibili login.
|
||||||
|
Args:
|
||||||
|
username: plain text username for bilibili.
|
||||||
|
password: plain text password for bilibili.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
code: login response code (0: success, -105: captcha error, ...).
|
||||||
|
access_token: token for further operation.
|
||||||
|
refresh_token: token for refresh access_token.
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
expires_in: access token expire time (30 days)
|
||||||
|
"""
|
||||||
|
hash, pubkey, sid = get_key()
|
||||||
|
|
||||||
|
encrypted_password = cipher.encrypt_login_password(password, hash, pubkey)
|
||||||
|
url_encoded_username = parse.quote_plus(username)
|
||||||
|
url_encoded_password = parse.quote_plus(encrypted_password)
|
||||||
|
|
||||||
|
post_data = {
|
||||||
|
'appkey': LOGIN_APPKEY,
|
||||||
|
'password': url_encoded_password,
|
||||||
|
'ts': str(int(datetime.now().timestamp())),
|
||||||
|
'username': url_encoded_username
|
||||||
|
}
|
||||||
|
|
||||||
|
post_data['sign'] = cipher.login_sign_dict_bin(post_data)
|
||||||
|
# avoid multiple url parse
|
||||||
|
post_data['username'] = username
|
||||||
|
post_data['password'] = encrypted_password
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'User-Agent': '',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
# "https://passport.bilibili.com/api/v3/oauth2/login",
|
||||||
|
"https://passport.bilibili.com/x/passport-login/oauth2/login",
|
||||||
|
headers=headers,
|
||||||
|
data=post_data,
|
||||||
|
)
|
||||||
|
response = r.json()
|
||||||
|
response_code = response['code']
|
||||||
|
if response_code == 0:
|
||||||
|
login_data = response['data']['token_info']
|
||||||
|
return response_code, login_data['access_token'], login_data['refresh_token'], sid, login_data['mid'], \
|
||||||
|
login_data["expires_in"]
|
||||||
|
elif response_code == -105: # captcha error, retry=5
|
||||||
|
retry_cnt = 5
|
||||||
|
while response_code == -105 and retry_cnt > 0:
|
||||||
|
response_code, access_token, refresh_token, sid, mid, expire_in = login_captcha(username, password, sid)
|
||||||
|
if response_code == 0:
|
||||||
|
return response_code, access_token, refresh_token, sid, mid, expire_in
|
||||||
|
retry_cnt -= 1
|
||||||
|
|
||||||
|
# other error code
|
||||||
|
return response_code, None, None, sid, None, None
|
||||||
|
|
||||||
|
|
||||||
|
def login_captcha(username, password, sid):
|
||||||
|
"""
|
||||||
|
bilibili login with captcha.
|
||||||
|
depend on captcha recognize service, please do not use this as first choice.
|
||||||
|
Args:
|
||||||
|
username: plain text username for bilibili.
|
||||||
|
password: plain text password for bilibili.
|
||||||
|
sid: session id
|
||||||
|
Returns:
|
||||||
|
code: login response code (0: success, -105: captcha error, ...).
|
||||||
|
access_token: token for further operation.
|
||||||
|
refresh_token: token for refresh access_token.
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
expires_in: access token expire time (30 days)
|
||||||
|
"""
|
||||||
|
|
||||||
|
jsessionid, captcha_img = get_capcha(sid)
|
||||||
|
captcha_str = recognize_captcha(captcha_img)
|
||||||
|
|
||||||
|
hash, pubkey, sid = get_key(sid, jsessionid)
|
||||||
|
|
||||||
|
encrypted_password = cipher.encrypt_login_password(password, hash, pubkey)
|
||||||
|
url_encoded_username = parse.quote_plus(username)
|
||||||
|
url_encoded_password = parse.quote_plus(encrypted_password)
|
||||||
|
|
||||||
|
post_data = {
|
||||||
|
'appkey': APPKEY,
|
||||||
|
'captcha': captcha_str,
|
||||||
|
'password': url_encoded_password,
|
||||||
|
'platform': "pc",
|
||||||
|
'ts': str(int(datetime.now().timestamp())),
|
||||||
|
'username': url_encoded_username
|
||||||
|
}
|
||||||
|
|
||||||
|
post_data['sign'] = cipher.sign_dict(post_data, APPSECRET)
|
||||||
|
# avoid multiple url parse
|
||||||
|
post_data['username'] = username
|
||||||
|
post_data['password'] = encrypted_password
|
||||||
|
post_data['captcha'] = captcha_str
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'User-Agent': '',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
"https://passport.bilibili.com/api/oauth2/login",
|
||||||
|
headers=headers,
|
||||||
|
data=post_data,
|
||||||
|
cookies={
|
||||||
|
'JSESSIONID': jsessionid,
|
||||||
|
'sid': sid
|
||||||
|
}
|
||||||
|
)
|
||||||
|
response = r.json()
|
||||||
|
if response['code'] == 0:
|
||||||
|
login_data = response['data']
|
||||||
|
return response['code'], login_data['access_token'], login_data['refresh_token'], sid, login_data['mid'], \
|
||||||
|
login_data["expires_in"]
|
||||||
|
else:
|
||||||
|
return response['code'], None, None, sid, None, None
|
||||||
|
|
||||||
|
|
||||||
|
def login_by_access_token(access_token):
|
||||||
|
"""
|
||||||
|
bilibili access token login.
|
||||||
|
Args:
|
||||||
|
access_token: Bilibili access token got by previous username/password login.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
expires_in: access token expire time
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
'Host': 'passport.bilibili.com',
|
||||||
|
'User-Agent': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
login_params = {
|
||||||
|
'appkey': APPKEY,
|
||||||
|
'access_token': access_token,
|
||||||
|
'platform': "pc",
|
||||||
|
'ts': str(int(datetime.now().timestamp())),
|
||||||
|
}
|
||||||
|
login_params['sign'] = cipher.sign_dict(login_params, APPSECRET)
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
url="https://passport.bilibili.com/api/oauth2/info",
|
||||||
|
headers=headers,
|
||||||
|
params=login_params
|
||||||
|
)
|
||||||
|
|
||||||
|
login_data = r.json()['data']
|
||||||
|
|
||||||
|
return r.cookies['sid'], login_data['mid'], login_data["expires_in"]
|
||||||
|
|
||||||
|
|
||||||
|
def upload_cover(access_token, sid, cover_file_path):
|
||||||
|
with open(cover_file_path, "rb") as f:
|
||||||
|
cover_pic = f.read()
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Host': 'member.bilibili.com',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
'User-Agent': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"access_key": access_token,
|
||||||
|
}
|
||||||
|
|
||||||
|
params["sign"] = cipher.sign_dict(params, APPSECRET)
|
||||||
|
|
||||||
|
files = {
|
||||||
|
'file': ("cover.png", cover_pic, "Content-Type: image/png"),
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
"http://member.bilibili.com/x/vu/client/cover/up",
|
||||||
|
headers=headers,
|
||||||
|
params=params,
|
||||||
|
files=files,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
},
|
||||||
|
verify=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
return r.json()["data"]["url"]
|
||||||
|
|
||||||
|
|
||||||
|
def upload_chunk(upload_url, server_file_name, local_file_name, chunk_data, chunk_size, chunk_id, chunk_total_num):
|
||||||
|
"""
|
||||||
|
upload video chunk.
|
||||||
|
Args:
|
||||||
|
upload_url: upload url by pre_upload api.
|
||||||
|
server_file_name: file name on server by pre_upload api.
|
||||||
|
local_file_name: video file name in local fs.
|
||||||
|
chunk_data: binary data of video chunk.
|
||||||
|
chunk_size: default of ugc_assisstant is 2M.
|
||||||
|
chunk_id: chunk number.
|
||||||
|
chunk_total_num: total chunk number.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True: upload chunk success.
|
||||||
|
False: upload chunk fail.
|
||||||
|
"""
|
||||||
|
print("chunk{}/{}".format(chunk_id, chunk_total_num))
|
||||||
|
print("filename: {}".format(local_file_name))
|
||||||
|
files = {
|
||||||
|
'version': (None, '2.0.0.1054'),
|
||||||
|
'filesize': (None, chunk_size),
|
||||||
|
'chunk': (None, chunk_id),
|
||||||
|
'chunks': (None, chunk_total_num),
|
||||||
|
'md5': (None, cipher.md5_bytes(chunk_data)),
|
||||||
|
'file': (local_file_name, chunk_data, 'application/octet-stream')
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
url=upload_url,
|
||||||
|
files=files,
|
||||||
|
cookies={
|
||||||
|
'PHPSESSID': server_file_name
|
||||||
|
},
|
||||||
|
)
|
||||||
|
print(r.status_code)
|
||||||
|
print(r.content)
|
||||||
|
|
||||||
|
if r.status_code == 200 and r.json()['OK'] == 1:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def upload_video_part(access_token, sid, mid, video_part: VideoPart, max_retry=5, cb=None):
|
||||||
|
"""
|
||||||
|
upload a video file.
|
||||||
|
Args:
|
||||||
|
access_token: access token generated by login api.
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
video_part: local video file data.
|
||||||
|
max_retry: max retry number for each chunk.
|
||||||
|
cb: 回调
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
status: success or fail.
|
||||||
|
server_file_name: server file name by pre_upload api.
|
||||||
|
"""
|
||||||
|
if cb is None:
|
||||||
|
cb = lambda f, c, t: None
|
||||||
|
if not isinstance(video_part, VideoPart):
|
||||||
|
return False
|
||||||
|
if video_part.server_file_name is not None:
|
||||||
|
return True
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'User-Agent': '',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
"http://member.bilibili.com/preupload?access_key={}&mid={}&profile=ugcfr%2Fpc3".format(access_token, mid),
|
||||||
|
headers=headers,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
},
|
||||||
|
verify=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
pre_upload_data = r.json()
|
||||||
|
upload_url = pre_upload_data['url']
|
||||||
|
complete_upload_url = pre_upload_data['complete']
|
||||||
|
server_file_name = pre_upload_data['filename']
|
||||||
|
local_file_name = video_part.path
|
||||||
|
|
||||||
|
file_size = os.path.getsize(local_file_name)
|
||||||
|
chunk_total_num = int(math.ceil(file_size / CHUNK_SIZE))
|
||||||
|
file_hash = hashlib.md5()
|
||||||
|
with open(local_file_name, 'rb') as f:
|
||||||
|
for chunk_id in range(0, chunk_total_num):
|
||||||
|
chunk_data = f.read(CHUNK_SIZE)
|
||||||
|
cb(video_part, chunk_id, chunk_total_num)
|
||||||
|
status = Retry(max_retry=max_retry, success_return_value=True).run(
|
||||||
|
upload_chunk,
|
||||||
|
upload_url,
|
||||||
|
server_file_name,
|
||||||
|
os.path.basename(local_file_name),
|
||||||
|
chunk_data,
|
||||||
|
CHUNK_SIZE,
|
||||||
|
chunk_id,
|
||||||
|
chunk_total_num
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return False
|
||||||
|
file_hash.update(chunk_data)
|
||||||
|
print(file_hash.hexdigest())
|
||||||
|
|
||||||
|
# complete upload
|
||||||
|
post_data = {
|
||||||
|
'chunks': chunk_total_num,
|
||||||
|
'filesize': file_size,
|
||||||
|
'md5': file_hash.hexdigest(),
|
||||||
|
'name': os.path.basename(local_file_name),
|
||||||
|
'version': '2.0.0.1054',
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
url=complete_upload_url,
|
||||||
|
data=post_data,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
print(r.status_code)
|
||||||
|
print(r.content)
|
||||||
|
|
||||||
|
video_part.server_file_name = server_file_name
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def upload(access_token,
|
||||||
|
sid,
|
||||||
|
mid,
|
||||||
|
parts,
|
||||||
|
copyright: int,
|
||||||
|
title: str,
|
||||||
|
tid: int,
|
||||||
|
tag: str,
|
||||||
|
desc: str,
|
||||||
|
source: str = '',
|
||||||
|
cover: str = '',
|
||||||
|
no_reprint: int = 0,
|
||||||
|
open_elec: int = 1,
|
||||||
|
max_retry: int = 5,
|
||||||
|
thread_pool_workers: int = 1):
|
||||||
|
"""
|
||||||
|
upload video.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
access_token: oauth2 access token.
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
parts: VideoPart list.
|
||||||
|
copyright: 原创/转载.
|
||||||
|
title: 投稿标题.
|
||||||
|
tid: 分区id.
|
||||||
|
tag: 标签.
|
||||||
|
desc: 投稿简介.
|
||||||
|
source: 转载地址.
|
||||||
|
cover: 封面图片文件路径.
|
||||||
|
no_reprint: 可否转载.
|
||||||
|
open_elec: 充电.
|
||||||
|
max_retry: max retry time for each chunk.
|
||||||
|
thread_pool_workers: max upload threads.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(aid, bvid)
|
||||||
|
aid: av号
|
||||||
|
bvid: bv号
|
||||||
|
"""
|
||||||
|
if not isinstance(parts, list):
|
||||||
|
parts = [parts]
|
||||||
|
|
||||||
|
status = True
|
||||||
|
with ThreadPoolExecutor(max_workers=thread_pool_workers) as tpe:
|
||||||
|
t_list = []
|
||||||
|
for video_part in parts:
|
||||||
|
print("upload {} added in pool".format(video_part.title))
|
||||||
|
t_obj = tpe.submit(upload_video_part, access_token, sid, mid, video_part, max_retry)
|
||||||
|
t_obj.video_part = video_part
|
||||||
|
t_list.append(t_obj)
|
||||||
|
|
||||||
|
for t_obj in as_completed(t_list):
|
||||||
|
status = status and t_obj.result()
|
||||||
|
print("video part {} finished, status: {}".format(t_obj.video_part.title, t_obj.result()))
|
||||||
|
if not status:
|
||||||
|
print("upload failed")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
# cover
|
||||||
|
if os.path.isfile(cover):
|
||||||
|
try:
|
||||||
|
cover = upload_cover(access_token, sid, cover)
|
||||||
|
except:
|
||||||
|
cover = ''
|
||||||
|
else:
|
||||||
|
cover = ''
|
||||||
|
|
||||||
|
# submit
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'User-Agent': '',
|
||||||
|
}
|
||||||
|
post_data = {
|
||||||
|
'build': 1054,
|
||||||
|
'copyright': copyright,
|
||||||
|
'cover': cover,
|
||||||
|
'desc': desc,
|
||||||
|
'no_reprint': no_reprint,
|
||||||
|
'open_elec': open_elec,
|
||||||
|
'source': source,
|
||||||
|
'tag': tag,
|
||||||
|
'tid': tid,
|
||||||
|
'title': title,
|
||||||
|
'videos': []
|
||||||
|
}
|
||||||
|
for video_part in parts:
|
||||||
|
post_data['videos'].append({
|
||||||
|
"desc": video_part.desc,
|
||||||
|
"filename": video_part.server_file_name,
|
||||||
|
"title": video_part.title
|
||||||
|
})
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'access_key': access_token,
|
||||||
|
}
|
||||||
|
params['sign'] = cipher.sign_dict(params, APPSECRET)
|
||||||
|
r = requests.post(
|
||||||
|
url="http://member.bilibili.com/x/vu/client/add",
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
verify=False,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
},
|
||||||
|
json=post_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
print("submit")
|
||||||
|
print(r.status_code)
|
||||||
|
print(r.content.decode())
|
||||||
|
|
||||||
|
data = r.json()["data"]
|
||||||
|
return data["aid"], data["bvid"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_post_data(access_token, sid, avid):
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Host': 'member.bilibili.com',
|
||||||
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
|
'User-Agent': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"access_key": access_token,
|
||||||
|
"aid": avid,
|
||||||
|
"build": "1054"
|
||||||
|
}
|
||||||
|
|
||||||
|
params["sign"] = cipher.sign_dict(params, APPSECRET)
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
url="http://member.bilibili.com/x/client/archive/view",
|
||||||
|
headers=headers,
|
||||||
|
params=params,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return r.json()["data"]
|
||||||
|
|
||||||
|
|
||||||
|
def edit_videos(
|
||||||
|
access_token,
|
||||||
|
sid,
|
||||||
|
mid,
|
||||||
|
avid=None,
|
||||||
|
bvid=None,
|
||||||
|
parts=None,
|
||||||
|
insert_index=None,
|
||||||
|
copyright=None,
|
||||||
|
title=None,
|
||||||
|
tid=None,
|
||||||
|
tag=None,
|
||||||
|
desc=None,
|
||||||
|
source=None,
|
||||||
|
cover=None,
|
||||||
|
no_reprint=None,
|
||||||
|
open_elec=None,
|
||||||
|
max_retry: int = 5,
|
||||||
|
thread_pool_workers: int = 1):
|
||||||
|
"""
|
||||||
|
insert videos into existed post.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
access_token: oauth2 access token.
|
||||||
|
sid: session id.
|
||||||
|
mid: member id.
|
||||||
|
avid: av number,
|
||||||
|
bvid: bv string,
|
||||||
|
parts: VideoPart list.
|
||||||
|
insert_index: new video index.
|
||||||
|
copyright: 原创/转载.
|
||||||
|
title: 投稿标题.
|
||||||
|
tid: 分区id.
|
||||||
|
tag: 标签.
|
||||||
|
desc: 投稿简介.
|
||||||
|
source: 转载地址.
|
||||||
|
cover: cover url.
|
||||||
|
no_reprint: 可否转载.
|
||||||
|
open_elec: 充电.
|
||||||
|
max_retry: max retry time for each chunk.
|
||||||
|
thread_pool_workers: max upload threads.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(aid, bvid)
|
||||||
|
aid: av号
|
||||||
|
bvid: bv号
|
||||||
|
"""
|
||||||
|
if not avid and not bvid:
|
||||||
|
print("please provide avid or bvid")
|
||||||
|
return None, None
|
||||||
|
if not avid:
|
||||||
|
avid = cipher.bv2av(bvid)
|
||||||
|
if not isinstance(parts, list):
|
||||||
|
parts = [parts]
|
||||||
|
if type(avid) is str:
|
||||||
|
avid = int(avid)
|
||||||
|
|
||||||
|
post_video_data = get_post_data(access_token, sid, avid)
|
||||||
|
|
||||||
|
status = True
|
||||||
|
with ThreadPoolExecutor(max_workers=thread_pool_workers) as tpe:
|
||||||
|
t_list = []
|
||||||
|
for video_part in parts:
|
||||||
|
print("upload {} added in pool".format(video_part.title))
|
||||||
|
t_obj = tpe.submit(upload_video_part, access_token, sid, mid, video_part, max_retry)
|
||||||
|
t_obj.video_part = video_part
|
||||||
|
t_list.append(t_obj)
|
||||||
|
|
||||||
|
for t_obj in as_completed(t_list):
|
||||||
|
status = status and t_obj.result()
|
||||||
|
print("video part {} finished, status: {}".format(t_obj.video_part.title, t_obj.result()))
|
||||||
|
if not status:
|
||||||
|
print("upload failed")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'User-Agent': '',
|
||||||
|
}
|
||||||
|
submit_data = {
|
||||||
|
'aid': avid,
|
||||||
|
'build': 1054,
|
||||||
|
'copyright': post_video_data["archive"]["copyright"],
|
||||||
|
'cover': post_video_data["archive"]["cover"],
|
||||||
|
'desc': post_video_data["archive"]["desc"],
|
||||||
|
'no_reprint': post_video_data["archive"]["no_reprint"],
|
||||||
|
'open_elec': post_video_data["archive_elec"]["state"], # open_elec not tested
|
||||||
|
'source': post_video_data["archive"]["source"],
|
||||||
|
'tag': post_video_data["archive"]["tag"],
|
||||||
|
'tid': post_video_data["archive"]["tid"],
|
||||||
|
'title': post_video_data["archive"]["title"],
|
||||||
|
'videos': post_video_data["videos"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# cover
|
||||||
|
if os.path.isfile(cover):
|
||||||
|
try:
|
||||||
|
cover = upload_cover(access_token, sid, cover)
|
||||||
|
except:
|
||||||
|
cover = ''
|
||||||
|
else:
|
||||||
|
cover = ''
|
||||||
|
|
||||||
|
# edit archive data
|
||||||
|
if copyright:
|
||||||
|
submit_data["copyright"] = copyright
|
||||||
|
if title:
|
||||||
|
submit_data["title"] = title
|
||||||
|
if tid:
|
||||||
|
submit_data["tid"] = tid
|
||||||
|
if tag:
|
||||||
|
submit_data["tag"] = tag
|
||||||
|
if desc:
|
||||||
|
submit_data["desc"] = desc
|
||||||
|
if source:
|
||||||
|
submit_data["source"] = source
|
||||||
|
if cover:
|
||||||
|
submit_data["cover"] = cover
|
||||||
|
if no_reprint:
|
||||||
|
submit_data["no_reprint"] = no_reprint
|
||||||
|
if open_elec:
|
||||||
|
submit_data["open_elec"] = open_elec
|
||||||
|
|
||||||
|
if type(insert_index) is int:
|
||||||
|
for i, video_part in enumerate(parts):
|
||||||
|
submit_data['videos'].insert(insert_index + i, {
|
||||||
|
"desc": video_part.desc,
|
||||||
|
"filename": video_part.server_file_name,
|
||||||
|
"title": video_part.title
|
||||||
|
})
|
||||||
|
elif insert_index is None:
|
||||||
|
for video_part in parts:
|
||||||
|
submit_data['videos'].append({
|
||||||
|
"desc": video_part.desc,
|
||||||
|
"filename": video_part.server_file_name,
|
||||||
|
"title": video_part.title
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
print("wrong insert index")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'access_key': access_token,
|
||||||
|
}
|
||||||
|
params['sign'] = cipher.sign_dict(params, APPSECRET)
|
||||||
|
r = requests.post(
|
||||||
|
url="http://member.bilibili.com/x/vu/client/edit",
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
verify=False,
|
||||||
|
cookies={
|
||||||
|
'sid': sid
|
||||||
|
},
|
||||||
|
json=submit_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
print("edit submit")
|
||||||
|
print(r.status_code)
|
||||||
|
print(r.content.decode())
|
||||||
|
|
||||||
|
data = r.json()["data"]
|
||||||
|
return data["aid"], data["bvid"]
|
1
bilibiliuploader/util/__init__.py
Normal file
1
bilibiliuploader/util/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .cipher import *
|
119
bilibiliuploader/util/cipher.py
Normal file
119
bilibiliuploader/util/cipher.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import hashlib
|
||||||
|
import rsa
|
||||||
|
import base64
|
||||||
|
import subprocess
|
||||||
|
import platform
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
|
def md5(data: str):
|
||||||
|
"""
|
||||||
|
generate md5 hash of utf-8 encoded string.
|
||||||
|
"""
|
||||||
|
return hashlib.md5(data.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def md5_bytes(data: bytes):
|
||||||
|
"""
|
||||||
|
generate md5 hash of binary.
|
||||||
|
"""
|
||||||
|
return hashlib.md5(data).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def sign_str(data: str, app_secret: str):
|
||||||
|
"""
|
||||||
|
sign a string of request parameters
|
||||||
|
Args:
|
||||||
|
data: string of request parameters, must be sorted by key before input.
|
||||||
|
app_secret: a secret string coupled with app_key.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A hash string. len=32
|
||||||
|
"""
|
||||||
|
return md5(data + app_secret)
|
||||||
|
|
||||||
|
|
||||||
|
def sign_dict(data: dict, app_secret: str):
|
||||||
|
"""
|
||||||
|
sign a dictionary of request parameters
|
||||||
|
Args:
|
||||||
|
data: dictionary of request parameters.
|
||||||
|
app_secret: a secret string coupled with app_key.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A hash string. len=32
|
||||||
|
"""
|
||||||
|
data_str = []
|
||||||
|
keys = list(data.keys())
|
||||||
|
keys.sort()
|
||||||
|
for key in keys:
|
||||||
|
data_str.append("{}={}".format(key, data[key]))
|
||||||
|
data_str = "&".join(data_str)
|
||||||
|
data_str = data_str + app_secret
|
||||||
|
return md5(data_str)
|
||||||
|
|
||||||
|
|
||||||
|
def login_sign_dict_bin(data: dict):
|
||||||
|
data_str = []
|
||||||
|
keys = list(data.keys())
|
||||||
|
keys.sort()
|
||||||
|
for key in keys:
|
||||||
|
data_str.append("{}={}".format(key, data[key]))
|
||||||
|
data_str = "&".join(data_str)
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
if platform.system().lower() == 'windows':
|
||||||
|
print(data_str)
|
||||||
|
print(subprocess.Popen([os.path.join(package_directory, "sign.exe"), data_str], stdout=subprocess.PIPE).communicate()[0].decode().strip())
|
||||||
|
|
||||||
|
return subprocess.Popen([os.path.join(package_directory, "sign.exe"), data_str], stdout=subprocess.PIPE).communicate()[0].decode().strip()
|
||||||
|
if platform.system().lower() == 'linux':
|
||||||
|
return subprocess.Popen([os.path.join(package_directory, "sign.out"), data_str], stdout=subprocess.PIPE).communicate()[0].decode().strip()
|
||||||
|
raise Exception("Operating System is not supported.")
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_login_password(password, hash, pubkey):
|
||||||
|
"""
|
||||||
|
encrypt password for login api.
|
||||||
|
Args:
|
||||||
|
password: plain text of user password.
|
||||||
|
hash: hash provided by /api/oauth2/getKey.
|
||||||
|
pubkey: public key provided by /api/oauth2/getKey.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An encrypted cipher of password.
|
||||||
|
"""
|
||||||
|
return base64.b64encode(rsa.encrypt(
|
||||||
|
(hash + password).encode('utf-8'),
|
||||||
|
rsa.PublicKey.load_pkcs1_openssl_pem(pubkey.encode()),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def av2bv(av: int):
|
||||||
|
table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'
|
||||||
|
tr = {}
|
||||||
|
for i in range(58):
|
||||||
|
tr[table[i]] = i
|
||||||
|
s = [11, 10, 3, 8, 4, 6]
|
||||||
|
xor = 177451812
|
||||||
|
add = 8728348608
|
||||||
|
|
||||||
|
av = (av ^ xor) + add
|
||||||
|
r = list('BV1 4 1 7 ')
|
||||||
|
for i in range(6):
|
||||||
|
r[s[i]] = table[av // 58 ** i % 58]
|
||||||
|
return ''.join(r)
|
||||||
|
|
||||||
|
|
||||||
|
def bv2av(bv: str):
|
||||||
|
table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'
|
||||||
|
tr = {}
|
||||||
|
for i in range(58):
|
||||||
|
tr[table[i]] = i
|
||||||
|
s = [11, 10, 3, 8, 4, 6]
|
||||||
|
xor = 177451812
|
||||||
|
add = 8728348608
|
||||||
|
|
||||||
|
r = 0
|
||||||
|
for i in range(6):
|
||||||
|
r += tr[bv[s[i]]] * 58 ** i
|
||||||
|
return (r - add) ^ xor
|
18
bilibiliuploader/util/retry.py
Normal file
18
bilibiliuploader/util/retry.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class Retry:
|
||||||
|
def __init__(self, max_retry, success_return_value):
|
||||||
|
self.max_retry = max_retry
|
||||||
|
self.success_return_value = success_return_value
|
||||||
|
|
||||||
|
def run(self, func, *args, **kwargs):
|
||||||
|
status = False
|
||||||
|
for i in range(0, self.max_retry):
|
||||||
|
try:
|
||||||
|
return_value = func(*args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
return_value = not self.success_return_value
|
||||||
|
if return_value == self.success_return_value:
|
||||||
|
status = True
|
||||||
|
break
|
||||||
|
return status
|
BIN
bilibiliuploader/util/sign.exe
Normal file
BIN
bilibiliuploader/util/sign.exe
Normal file
Binary file not shown.
BIN
bilibiliuploader/util/sign.out
Normal file
BIN
bilibiliuploader/util/sign.out
Normal file
Binary file not shown.
@ -1,174 +1,153 @@
|
|||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import m3u8
|
|
||||||
import queue
|
|
||||||
import threading
|
import threading
|
||||||
from config import config
|
import Common
|
||||||
from api import XiGuaLiveApi
|
import os
|
||||||
from bilibili import *
|
import requests
|
||||||
|
|
||||||
q = queue.Queue()
|
session = requests.session()
|
||||||
base_uri = ""
|
|
||||||
isUpload = False
|
|
||||||
uq = queue.Queue()
|
|
||||||
d = datetime.strftime(datetime.now(),"%Y_%m_%d")
|
|
||||||
|
|
||||||
class downloader(XiGuaLiveApi):
|
|
||||||
files = []
|
|
||||||
playlist: str = None
|
|
||||||
|
|
||||||
def updRoomInfo(self):
|
def download():
|
||||||
super(downloader, self).updRoomInfo()
|
while Common.api.isLive and not Common.forceNotDownload:
|
||||||
self.updPlayList()
|
if not Common.streamUrl:
|
||||||
|
Common.appendError("Download with No StreamUrl Specific")
|
||||||
def updPlayList(self):
|
break
|
||||||
if "playInfo" not in self._rawRoomInfo or "Main" not in self._rawRoomInfo["playInfo"]:
|
path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv")
|
||||||
if self.playlist is None:
|
base_path = Common.config["path"]
|
||||||
self.apiChangedError("无法获取直播链接")
|
if not os.path.isdir(base_path):
|
||||||
self.playlist = False
|
os.makedirs(base_path)
|
||||||
else:
|
|
||||||
self.playlist = self._rawRoomInfo["playInfo"]["Main"]["1"]["Url"]["HlsUrl"]
|
|
||||||
|
|
||||||
def onLike(self, user):
|
|
||||||
pass
|
|
||||||
def onAd(self, i):
|
|
||||||
pass
|
|
||||||
def onChat(self, chat):
|
|
||||||
pass
|
|
||||||
def onEnter(self, msg):
|
|
||||||
pass
|
|
||||||
def onJoin(self, user):
|
|
||||||
pass
|
|
||||||
def onLeave(self, json):
|
|
||||||
self.updRoomInfo()
|
|
||||||
def onMessage(self, msg):
|
|
||||||
pass
|
|
||||||
def onPresent(self, gift):
|
|
||||||
pass
|
|
||||||
def onPresentEnd(self, gift):
|
|
||||||
pass
|
|
||||||
def onSubscribe(self, user):
|
|
||||||
pass
|
|
||||||
def preDownload(self):
|
|
||||||
global base_uri
|
|
||||||
if self.playlist:
|
|
||||||
try:
|
try:
|
||||||
p = m3u8.load(self.playlist)
|
p = session.get(Common.streamUrl, stream=True, timeout=3)
|
||||||
except:
|
p.raise_for_status()
|
||||||
self.updRoomInfo()
|
except Exception as e:
|
||||||
|
Common.appendError("Download >{}< with Exception [{}]".format(path,e.__str__()))
|
||||||
|
break
|
||||||
|
Common.api.initSave(os.path.join(base_path, path)+".xml")
|
||||||
|
Common.appendDownloadStatus("Download >{}< Start".format(path))
|
||||||
|
f = open(os.path.join(base_path, path), "wb")
|
||||||
|
_size = 0
|
||||||
|
try:
|
||||||
|
for T in p.iter_content(chunk_size=Common.config["c_s"]):
|
||||||
|
if Common.forceNotDownload:
|
||||||
|
Common.modifyLastDownloadStatus("Force Stop Download".format(path))
|
||||||
return
|
return
|
||||||
base_uri = p.base_uri
|
f.write(T)
|
||||||
for i in p.files:
|
_size += len(T)
|
||||||
if i not in self.files:
|
Common.modifyLastDownloadStatus(
|
||||||
self.files.append(i)
|
"Downloading >{}< @ {:.2f}%".format(path, 100.0 * _size / Common.config["p_s"]))
|
||||||
print("{} : Add Sequence {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"),
|
if _size > Common.config["p_s"] and not Common.config["dlO"]:
|
||||||
len(self.files)))
|
Common.modifyLastDownloadStatus("Download >{}< Exceed MaxSize".format(path))
|
||||||
q.put(i)
|
|
||||||
self.genNewName()
|
|
||||||
def genNewName(self):
|
|
||||||
if len(self.files) > 800:
|
|
||||||
q.put(True)
|
|
||||||
self.files.clear()
|
|
||||||
|
|
||||||
|
|
||||||
def download(path=datetime.strftime(datetime.now(),"%Y%m%d_%H%M.ts")):
|
|
||||||
global isUpload
|
|
||||||
print("{} : Download Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
|
||||||
n = False
|
|
||||||
isUpload = False
|
|
||||||
i = q.get()
|
|
||||||
while True:
|
|
||||||
if isinstance(i, bool):
|
|
||||||
print("{} : Download Daemon Receive Command {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
|
||||||
break
|
break
|
||||||
print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
Common.modifyLastDownloadStatus("Download >{}< Finished".format(path))
|
||||||
try:
|
except Exception as e:
|
||||||
_p = requests.get("{}{}".format(base_uri,i))
|
Common.appendError("Download >{}< With Exception {}".format(path, e.__str__()))
|
||||||
except:
|
Common.api.updRoomInfo(True)
|
||||||
continue
|
finally:
|
||||||
f = open(path, "ab")
|
|
||||||
f.write(_p.content)
|
|
||||||
f.close()
|
f.close()
|
||||||
n=True
|
if os.path.getsize(os.path.join(base_path, path)) < Common.config["i_s"]:
|
||||||
i = q.get()
|
Common.modifyLastDownloadStatus("Downloaded File >{}< is too small, will ignore it".format(path))
|
||||||
if n:
|
else:
|
||||||
uq.put(path)
|
Common.encodeQueue.put(os.path.join(base_path, path))
|
||||||
print("{} : Download Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
Common.doUpdatePlaylist()
|
||||||
isUpload = True
|
Common.api.updRoomInfo(True)
|
||||||
|
|
||||||
|
|
||||||
|
def encode():
|
||||||
def upload(date = datetime.strftime(datetime.now(), "%Y_%m_%d")):
|
Common.appendEncodeStatus("Encode Daemon Starting")
|
||||||
print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
while True:
|
||||||
i = uq.get()
|
i = Common.encodeQueue.get()
|
||||||
|
Common.encodeVideo(i)
|
||||||
|
|
||||||
|
|
||||||
|
def upload():
|
||||||
|
date = datetime.strftime(datetime.now(), Common.config["sdf"])
|
||||||
|
Common.appendUploadStatus("Upload Daemon Starting")
|
||||||
|
i = Common.uploadQueue.get()
|
||||||
while True:
|
while True:
|
||||||
if isinstance(i, bool):
|
|
||||||
if i is True:
|
if i is True:
|
||||||
print("自动投稿中,请稍后")
|
Common.publishVideo(date)
|
||||||
b.finishUpload(config["t_t"].format(date),17, config["tag"],config["des"],
|
|
||||||
source= "https://live.ixigua.com/userlive/97621754276", no_reprint= 0)
|
|
||||||
print("{} : Upload Daemon Receive Command {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
|
||||||
break
|
break
|
||||||
print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
|
||||||
try:
|
try:
|
||||||
b.preUpload(VideoPart(i, i))
|
Common.uploadVideo(i)
|
||||||
except:
|
except Exception as e:
|
||||||
|
Common.appendError(e.__str__())
|
||||||
continue
|
continue
|
||||||
i = uq.get()
|
finally:
|
||||||
print("{} : Upload Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
time.sleep(90)
|
||||||
|
i = Common.uploadQueue.get()
|
||||||
|
Common.appendUploadStatus("Upload Daemon Quiting")
|
||||||
|
|
||||||
|
|
||||||
b = Bilibili()
|
t = threading.Thread(target=download, args=())
|
||||||
b.login(config["b_u"], config["b_p"])
|
ut = threading.Thread(target=upload, args=())
|
||||||
|
et = threading.Thread(target=encode, args=())
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
room = 97621754276 # 永恒
|
def awakeEncode():
|
||||||
# room = 75366565294
|
global et
|
||||||
# room = 83940182312 #Dae
|
if et.is_alive():
|
||||||
# room = 5947850784 #⑦
|
return True
|
||||||
# room = 58649240617 #戏
|
et = threading.Thread(target=encode, args=())
|
||||||
if len(sys.argv) > 1:
|
et.setDaemon(True)
|
||||||
try:
|
et.start()
|
||||||
room = int(sys.argv[1])
|
return False
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
print("西瓜直播录播助手 by JerryYan")
|
def awakeDownload():
|
||||||
api = downloader(room)
|
global t
|
||||||
print("进入", api.roomLiver, "的直播间")
|
if t.is_alive():
|
||||||
if not api.isValidRoom:
|
return True
|
||||||
input("房间不存在")
|
t = threading.Thread(target=download, args=())
|
||||||
sys.exit()
|
|
||||||
print("=" * 30)
|
|
||||||
_preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts")
|
|
||||||
t = threading.Thread(target=download, args=(_preT,))
|
|
||||||
ut = threading.Thread(target=upload, args=(d,))
|
|
||||||
while True:
|
|
||||||
if api.isLive:
|
|
||||||
if d is None:
|
|
||||||
d = datetime.strftime(datetime.now(), "%Y_%m_%d")
|
|
||||||
if not t.is_alive():
|
|
||||||
_preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts")
|
|
||||||
t = threading.Thread(target=download, args=(_preT,))
|
|
||||||
t.setDaemon(True)
|
t.setDaemon(True)
|
||||||
t.start()
|
t.start()
|
||||||
if not ut.is_alive():
|
Common.api.updRoomInfo()
|
||||||
ut = threading.Thread(target=upload, args=(d,))
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def awakeUpload():
|
||||||
|
global ut
|
||||||
|
if ut.is_alive():
|
||||||
|
return True
|
||||||
|
ut = threading.Thread(target=upload, args=())
|
||||||
ut.setDaemon(True)
|
ut.setDaemon(True)
|
||||||
ut.start()
|
ut.start()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
Common.refreshDownloader()
|
||||||
|
if not Common.api.isValidUser:
|
||||||
|
Common.appendError("[{}]用户未找到".format(Common.api.name))
|
||||||
|
return
|
||||||
|
while True:
|
||||||
|
if Common.api.isLive and not Common.forceNotBroadcasting:
|
||||||
|
if not Common.forceNotDownload:
|
||||||
|
awakeDownload()
|
||||||
|
if not Common.forceNotUpload:
|
||||||
|
awakeUpload()
|
||||||
|
if not Common.forceNotEncode:
|
||||||
|
awakeEncode()
|
||||||
try:
|
try:
|
||||||
api.preDownload()
|
Common.api.getDanmaku()
|
||||||
except:
|
except Exception as e:
|
||||||
pass
|
Common.appendError(e.__str__())
|
||||||
time.sleep(3)
|
finally:
|
||||||
|
time.sleep(1)
|
||||||
else:
|
else:
|
||||||
q.put(False)
|
try:
|
||||||
if isUpload:
|
Common.api.updRoomInfo()
|
||||||
uq.put(True)
|
except Exception as e:
|
||||||
isUpload = False
|
Common.appendError(e.__str__())
|
||||||
else:
|
Common.refreshDownloader()
|
||||||
pass
|
if not Common.api.broadcaster:
|
||||||
# print("主播未开播,等待1分钟后重试")
|
Common.refreshDownloader()
|
||||||
time.sleep(60)
|
if Common.forceStartEncodeThread:
|
||||||
d=None
|
awakeEncode()
|
||||||
api.updRoomInfo()
|
Common.forceStartEncodeThread = False
|
||||||
|
if Common.forceStartUploadThread:
|
||||||
|
awakeUpload()
|
||||||
|
Common.forceStartUploadThread = False
|
||||||
|
if Common.doDelay():
|
||||||
|
Common.uploadQueue.put(True)
|
||||||
|
time.sleep(5)
|
||||||
|
12
requirements.txt
Normal file
12
requirements.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
psutil>=5.9.0
|
||||||
|
certifi>=2020.4.5.1
|
||||||
|
chardet>=3.0.4
|
||||||
|
idna>=2.9
|
||||||
|
pyasn1>=0.4.8
|
||||||
|
requests>=2.23.0
|
||||||
|
rsa>=4.0
|
||||||
|
urllib3>=1.25.9
|
||||||
|
flask>=2.0.2
|
||||||
|
flask_cors>=3.0.10
|
||||||
|
protobuf>=3.19.3
|
||||||
|
python-dotenv>=0.19.2
|
25
static/device.js
Normal file
25
static/device.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
function deviceUpdate(){
|
||||||
|
$.ajax(
|
||||||
|
"/stats/device",
|
||||||
|
{
|
||||||
|
success: function (res){
|
||||||
|
$("#memTotal").text(res.data.status.memTotal)
|
||||||
|
$("#memUsed").text(res.data.status.memUsed)
|
||||||
|
$("#memUsage").text(res.data.status.memUsage)
|
||||||
|
$("#diskTotal").text(res.data.status.diskTotal)
|
||||||
|
$("#diskUsed").text(res.data.status.diskUsed)
|
||||||
|
$("#diskUsage").text(res.data.status.diskUsage)
|
||||||
|
$("#cpu").text(res.data.status.cpu)
|
||||||
|
$("#memUsageP").val(res.data.status.memUsage)
|
||||||
|
$("#diskUsageP").val(res.data.status.diskUsage)
|
||||||
|
$("#cpuP").val(res.data.status.cpu)
|
||||||
|
$("#inSpeed").text(res.data.status.inSpeed)
|
||||||
|
$("#outSpeed").text(res.data.status.outSpeed)
|
||||||
|
$("#doCleanTime").text(res.data.status.doCleanTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceUpdate()
|
||||||
|
setInterval(deviceUpdate,2000)
|
59
static/index.js
Normal file
59
static/index.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
function taskUpdate(){
|
||||||
|
$.ajax(
|
||||||
|
"/stats",
|
||||||
|
{
|
||||||
|
success: function (res){
|
||||||
|
$("#broadcaster").text(res.data.broadcast.broadcaster)
|
||||||
|
$("#isBroadcasting").text(res.data.broadcast.isBroadcasting)
|
||||||
|
$("#streamUrl").text(res.data.broadcast.streamUrl)
|
||||||
|
$("#delayTime").text(res.data.broadcast.delayTime)
|
||||||
|
$("#forceNotBroadcasting").text(res.data.config.forceNotBroadcasting)
|
||||||
|
$("#forceNotDownload").text(res.data.config.forceNotDownload)
|
||||||
|
$("#forceNotUpload").text(res.data.config.forceNotUpload)
|
||||||
|
$("#forceNotEncode").text(res.data.config.forceNotEncode)
|
||||||
|
$("#downloadOnly").text(res.data.config.downloadOnly)
|
||||||
|
$("#updateTime").text(res.data.broadcast.updateTime)
|
||||||
|
$("#encodeQueueSize").text(res.data.encodeQueueSize)
|
||||||
|
$("#uploadQueueSize").text(res.data.uploadQueueSize)
|
||||||
|
$("#download").html(function(){
|
||||||
|
var ret = ""
|
||||||
|
res.data.download.reverse().forEach(function(obj){
|
||||||
|
ret += "<tr><td class='time'>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
|
||||||
|
})
|
||||||
|
return "<table>" + ret + "</table>"
|
||||||
|
})
|
||||||
|
$("#encode").html(function(){
|
||||||
|
var ret = ""
|
||||||
|
res.data.encode.reverse().forEach(function(obj){
|
||||||
|
ret += "<tr><td class='time'>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
|
||||||
|
})
|
||||||
|
return "<table>" + ret + "</table>"
|
||||||
|
})
|
||||||
|
$("#upload").html(function(){
|
||||||
|
var ret = ""
|
||||||
|
res.data.upload.reverse().forEach(function(obj){
|
||||||
|
ret += "<tr><td class='time'>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
|
||||||
|
})
|
||||||
|
return "<table>" + ret + "</table>"
|
||||||
|
})
|
||||||
|
$("#error").html(function(){
|
||||||
|
var ret = ""
|
||||||
|
res.data.error.reverse().forEach(function(obj){
|
||||||
|
ret += "<tr><td class='time'>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
|
||||||
|
})
|
||||||
|
return "<table>" + ret + "</table>"
|
||||||
|
})
|
||||||
|
$("#operation").html(function(){
|
||||||
|
var ret = ""
|
||||||
|
res.data.operation.reverse().forEach(function(obj){
|
||||||
|
ret += "<tr><td class='time'>" + obj.datetime + "</td><td>" + obj.message + "</td></tr>"
|
||||||
|
})
|
||||||
|
return "<table>" + ret + "</table>"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
taskUpdate()
|
||||||
|
setInterval(taskUpdate,8000)
|
30
templates/device.html
Normal file
30
templates/device.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<h1>机器状态</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>CPU使用率</td>
|
||||||
|
<td><progress id="cpuP" max="100" value="0"></progress></td>
|
||||||
|
<td><span id="cpu"></span>%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>内存使用率</td>
|
||||||
|
<td><progress id="memUsageP" max="100" value="0"></progress></td>
|
||||||
|
<td><span id="memUsed"></span>/<span id="memTotal"></span>(<span id="memUsage"></span>%)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>磁盘使用率</td>
|
||||||
|
<td><progress id="diskUsageP" max="100" value="0"></progress></td>
|
||||||
|
<td><span id="diskUsed"></span>/<span id="diskTotal"></span>(<span id="diskUsage"></span>%)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>网络速率</td>
|
||||||
|
<td>↓ <span id="inSpeed"></span>/s</td>
|
||||||
|
<td>↑ <span id="outSpeed"></span>/s</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>文件清理</td>
|
||||||
|
<td></td>
|
||||||
|
<td>@ <span id="doCleanTime"></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<script src="/static/device.js"></script>
|
||||||
|
|
26
templates/files.html
Normal file
26
templates/files.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh_CN">
|
||||||
|
<head>
|
||||||
|
<title>文件</title>
|
||||||
|
{% include 'head.html' %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<h1>所有录像文件</h1>
|
||||||
|
<p>部分录像文件已转移至百度云,请在<a href="https://pan.baidu.com/s/1ECnwiHnsm-3dSXNJGWlR2g">这里</a>下载 提取码: ddxt</p>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>文件名</td><td>文件大小</td><td>链接</td>
|
||||||
|
</tr>
|
||||||
|
{%for i in files %}
|
||||||
|
<tr>
|
||||||
|
<td>{{i.name}}</td><td>{{i.size}}</td><td><a href="/files/download/{{i.name}}">下载文件</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<hr/>
|
||||||
|
<h3><a href="/">录播信息页</a></h3>
|
||||||
|
{% include 'device.html' %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
templates/head.html
Normal file
13
templates/head.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<meta charset="UTF-8">
|
||||||
|
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
|
||||||
|
<style>
|
||||||
|
td{
|
||||||
|
border: solid 1px lightgray;
|
||||||
|
}
|
||||||
|
.title{
|
||||||
|
width: 6em;
|
||||||
|
}
|
||||||
|
.time{
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
</style>
|
86
templates/index.html
Normal file
86
templates/index.html
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh_CN">
|
||||||
|
<head>
|
||||||
|
<title>录播</title>
|
||||||
|
{% include 'head.html' %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<h1>基本信息</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>主播名</td>
|
||||||
|
<td><span id="broadcaster"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否正在直播</td>
|
||||||
|
<td><span id="isBroadcasting"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>直播视频流地址</td>
|
||||||
|
<td><span id="streamUrl"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>信息更新时间</td>
|
||||||
|
<td><span id="updateTime"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>延迟投稿时间</td>
|
||||||
|
<td><span id="delayTime"></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<hr/>
|
||||||
|
<h1>特殊设置</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>是否设置强制认为不直播</td>
|
||||||
|
<td><span id="forceNotBroadcasting"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否设置强制不下载</td>
|
||||||
|
<td><span id="forceNotDownload"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否设置强制不上传</td>
|
||||||
|
<td><span id="forceNotUpload"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否设置强制不转码</td>
|
||||||
|
<td><span id="forceNotEncode"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否设置为仅下载(不上传不转码)</td>
|
||||||
|
<td><span id="downloadOnly"></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<hr/>
|
||||||
|
<h1>当前状态</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>下载日志</td>
|
||||||
|
<td><span id="download"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>转码日志<br>队列<span id="encodeQueueSize"></span></td>
|
||||||
|
<td><span id="encode"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>上传日志<br>队列<span id="uploadQueueSize"></span></td>
|
||||||
|
<td><span id="upload"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>错误日志</td>
|
||||||
|
<td><span id="error"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='title'>操作日志</td>
|
||||||
|
<td><span id="operation"></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<hr/>
|
||||||
|
<h3><a href="/files/">所有录播文件</a></h3>
|
||||||
|
{% include 'device.html' %}
|
||||||
|
</div>
|
||||||
|
<script src="../static/index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user