Compare commits
337 Commits
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 |
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,实在是弄不懂
|
31
Chat.py
31
Chat.py
@ -1,31 +0,0 @@
|
||||
from User import User
|
||||
from Lottery import Lottery
|
||||
|
||||
|
||||
class Chat:
|
||||
|
||||
content: str =""
|
||||
user: User=None
|
||||
filterString:list = ["",]
|
||||
isFiltered = False
|
||||
|
||||
def __init__(self, json=None, lottery:Lottery = None):
|
||||
if json:
|
||||
self.parse(json)
|
||||
if lottery:
|
||||
self.filterString.append(lottery.content)
|
||||
|
||||
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__()
|
||||
|
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"
|
54
Gift.py
54
Gift.py
@ -1,54 +0,0 @@
|
||||
import requests
|
||||
from User import User
|
||||
|
||||
|
||||
class Gift:
|
||||
ID:int = 0
|
||||
count:int = 0
|
||||
roomID:int = 0
|
||||
giftList:dict = {}
|
||||
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 "common" in json and json["common"] is not None:
|
||||
if Gift.roomID != int(json["common"]["room_id"]):
|
||||
Gift.roomID = int(json["common"]["room_id"])
|
||||
self.update()
|
||||
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']
|
||||
if self.ID != 0 and self.ID in self.giftList:
|
||||
self.amount = self.giftList[self.ID]["Price"] * self.count
|
||||
else:
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
p = requests.get("https://i.snssdk.com/videolive/gift/get_gift_list?room_id={roomID}"
|
||||
"&version_code=730&device_platform=android".format(roomID = self.roomID))
|
||||
d = p.json()
|
||||
if "gift_info" not in d:
|
||||
print("错误:礼物更新失败")
|
||||
else:
|
||||
for i in d["gift_info"]:
|
||||
_id = int(i["id"])
|
||||
Gift.giftList[_id] = {"Name": i["name"], "Price": i["diamond_count"]}
|
||||
|
||||
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.
|
35
README.md
35
README.md
@ -1,16 +1,31 @@
|
||||
# XiguaLiveDanmakuHelper
|
||||
### 西瓜直播弹幕助手--控制台版
|
||||
|
||||
界面版:[q792602257/XiguaDanmakuHelperGUI](https://github.com/q792602257/XiguaDanmakuHelperGUI "C# ver")
|
||||
## 现在西瓜视频搜索接口无法使用,建议开发者自己找到自己的用户ID,写死加载即可
|
||||
|
||||
### 计划更新:
|
||||
+ Digg消息(点亮了喜欢)实例化
|
||||
+ √ ~~使用android app协议~~
|
||||
### 因西瓜直播弹幕接口换成了ProtoBuf,已经尝试解析出了部分proto
|
||||
|
||||
已使用
|
||||
除从用户ID获取roomID外,其他均改为Android Api
|
||||
### 从安卓9.4版本后 *(大概是)* 发现需要连接Websocket才能获取弹幕,且又是魔改protobuf(搞不懂),手动断开Websocket后才会轮询请求
|
||||
|
||||
+ √ ~~闲的无聊的时候看一看有没有好用的GUI轮子可以用用~~
|
||||
### ~~西瓜直播弹幕助手--界面版~~
|
||||
|
||||
已完成
|
||||
已基于BiliLive_dm制作出初代西瓜直播弹幕姬,api未跟进
|
||||
> 界面版:[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__()
|
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
|
@ -1,17 +1,18 @@
|
||||
# coding=utf-8
|
||||
import requests
|
||||
import time
|
||||
from LuckyUser import LuckyUser
|
||||
from .LuckyUser import LuckyUser
|
||||
|
||||
|
||||
class Lottery:
|
||||
ID: int = 0
|
||||
ID = 0
|
||||
isActive = False
|
||||
content = ""
|
||||
isFinished = False
|
||||
luckyUsers = []
|
||||
joinedUserCount = 0
|
||||
prizeName = ""
|
||||
finish:int = 0
|
||||
finish = 0
|
||||
|
||||
def __init__(self, json=None):
|
||||
if json:
|
||||
@ -54,8 +55,7 @@ class Lottery:
|
||||
self.isFinished = int(d["lottery_info"]["status"]) == 2
|
||||
self.joinedUserCount = int(d["lottery_info"]["candidate_num"])
|
||||
if self.isFinished:
|
||||
for i in d["lottery_info"]["lucky_users"]:
|
||||
self.luckyUsers.append(LuckyUser(i))
|
||||
self.luckyUsers = [ LuckyUser(i) for i in d["lottery_info"]["lucky_users"] ]
|
||||
|
||||
def __str__(self):
|
||||
if self.isFinished:
|
@ -1,4 +1,4 @@
|
||||
from User import User
|
||||
from .User import User
|
||||
|
||||
class LuckyUser:
|
||||
|
@ -1,10 +1,10 @@
|
||||
from User import User
|
||||
from .User import User
|
||||
|
||||
|
||||
class MemberMsg:
|
||||
type:int = 0
|
||||
content:str = ""
|
||||
user:User = None
|
||||
type = 0
|
||||
content = ""
|
||||
user = None
|
||||
|
||||
def __init__(self, json=None):
|
||||
if json:
|
@ -1,16 +1,34 @@
|
||||
class User:
|
||||
ID: int = 0
|
||||
name: str = ""
|
||||
brand: str = ""
|
||||
level: int = 0
|
||||
type: int = 0
|
||||
block: bool = False
|
||||
mute: bool = False
|
||||
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:
|
||||
@ -23,14 +41,17 @@ class User:
|
||||
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"]
|
||||
elif "room" in json and json["room"] is not None:
|
||||
if "user_info" in json["room"] and json["room"]["user_info"] is not None:
|
||||
self.ID = json["room"]['user_info']['user_id']
|
||||
self.name = json["room"]['user_info']['name']
|
||||
elif "anchor" in json and json["anchor"] is not None:
|
||||
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):
|
||||
@ -52,3 +73,5 @@ class User:
|
||||
def __unicode__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __repr__(self):
|
||||
return "西瓜用户【{}(ID:{})】".format(self.name, self.ID)
|
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()
|
98
WinMain.py
98
WinMain.py
@ -4,24 +4,26 @@ import time
|
||||
|
||||
import requests
|
||||
|
||||
from Gift import Gift
|
||||
from Lottery import Lottery
|
||||
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 public_hello
|
||||
import msvcrt
|
||||
import ctypes
|
||||
|
||||
SHOW_ALL = False
|
||||
|
||||
|
||||
def readInput(caption, default, timeout: int = 5):
|
||||
start_time = time.time()
|
||||
print('{}({})\r\n>'.format(caption, default), end="")
|
||||
input = ''
|
||||
while True:
|
||||
if msvcrt.kbhit():
|
||||
chr = msvcrt.getche()
|
||||
chr = msvcrt.getwche()
|
||||
if ord(chr) == 13: # enter_key
|
||||
break
|
||||
elif ord(chr) == 27:
|
||||
@ -30,13 +32,15 @@ def readInput(caption, default, timeout: int = 5):
|
||||
if input != "":
|
||||
input = input[:-1]
|
||||
msvcrt.putch(b" ")
|
||||
msvcrt.putch(b" ")
|
||||
msvcrt.putch(b"\b")
|
||||
msvcrt.putch(b"\b")
|
||||
if len(input) == 0:
|
||||
start_time = time.time()
|
||||
elif 32 > ord(chr) or 255 > ord(chr) > 126: # space_char
|
||||
continue
|
||||
else:
|
||||
input += chr.decode("utf8")
|
||||
input += chr
|
||||
if len(input) == 0 and (time.time() - start_time) > timeout:
|
||||
break
|
||||
|
||||
@ -74,8 +78,9 @@ FOREGROUND_YELLOW = 0x0e # yellow.
|
||||
FOREGROUND_WHITE = 0x0f # white.
|
||||
|
||||
# Windows CMD命令行 背景颜色定义 background colors
|
||||
BACKGROUND_BLUE = 0x10 # dark blue.
|
||||
BACKGROUND_GREEN = 0x20 # dark green.
|
||||
BACKGROUND_BLACK = 0x00 # dark blue.
|
||||
BACKGROUND_DARKBLUE = 0x10 # dark blue.
|
||||
BACKGROUND_DARKGREEN = 0x20 # dark green.
|
||||
BACKGROUND_DARKSKYBLUE = 0x30 # dark skyblue.
|
||||
BACKGROUND_DARKRED = 0x40 # dark red.
|
||||
BACKGROUND_DARKPINK = 0x50 # dark pink.
|
||||
@ -97,7 +102,7 @@ def set_cmd_text_color(color, handle=std_out_handle):
|
||||
|
||||
|
||||
def resetColor():
|
||||
set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_WHITE)
|
||||
|
||||
|
||||
class WinMain(Api):
|
||||
@ -108,7 +113,7 @@ class WinMain(Api):
|
||||
if self._tmp > 10:
|
||||
self._tmp = 0
|
||||
if self._tmp < 5:
|
||||
return "{} 的直播间 --弹幕助手 by JerryYan".format(self.roomLiver)
|
||||
return "{} 的直播间 --弹幕助手 by JerryYan".format(self.broadcaster)
|
||||
else:
|
||||
if self.roomPopularity == 0:
|
||||
self._tmp = 0
|
||||
@ -117,54 +122,64 @@ class WinMain(Api):
|
||||
return "人气:{} --弹幕助手 by JerryYan".format(self.roomPopularity)
|
||||
|
||||
def onMessage(self, msg: str):
|
||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
||||
print("消息 : ", msg)
|
||||
if SHOW_ALL:
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||
print("消息 : ", msg, end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onJoin(self, user: User):
|
||||
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
||||
print("欢迎", user, "加入了粉丝团")
|
||||
print("欢迎", user, "加入了粉丝团", end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onSubscribe(self, user: User):
|
||||
if SHOW_ALL:
|
||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
||||
print("用户", user, "关注了主播")
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||
print("用户", user, "关注了主播", end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onEnter(self, msg:MemberMsg):
|
||||
if SHOW_ALL:
|
||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
||||
print("提示 :", msg)
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||
print("提示 :", msg, end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onChat(self, chat: Chat):
|
||||
if SHOW_ALL:
|
||||
resetColor()
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_WHITE)
|
||||
if not chat.isFiltered:
|
||||
print(chat)
|
||||
print(chat, end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onLottery(self, i:Lottery):
|
||||
set_cmd_text_color(FOREGROUND_WHITE | BACKGROUND_DARKGRAY)
|
||||
print(i)
|
||||
print(i, end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onPresent(self, gift: Gift):
|
||||
if SHOW_ALL:
|
||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||
print("连击 :", gift)
|
||||
resetColor()
|
||||
|
||||
def onPresentEnd(self, gift: Gift):
|
||||
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
|
||||
print("感谢", gift)
|
||||
print("感谢", gift, end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onLike(self, user: User):
|
||||
if SHOW_ALL:
|
||||
set_cmd_text_color(FOREGROUND_DARKGRAY)
|
||||
print("用户", user, "点了喜欢")
|
||||
set_cmd_text_color(BACKGROUND_BLACK | FOREGROUND_DARKGRAY)
|
||||
print("用户", user, "点了喜欢", end="")
|
||||
resetColor()
|
||||
print()
|
||||
|
||||
def onLeave(self, json: any):
|
||||
return
|
||||
@ -175,19 +190,32 @@ def warning(*args):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
name = "永恒de草薙"
|
||||
resetColor()
|
||||
print("西瓜直播弹幕助手 by JerryYan")
|
||||
if len(sys.argv) > 1:
|
||||
name = "97621754276"
|
||||
if len(sys.argv) > 2:
|
||||
if sys.argv[-1] == "a":
|
||||
SHOW_ALL = True
|
||||
name = sys.argv[1]
|
||||
else:
|
||||
name = readInput("请输入主播用户名(请用拼音字母),默认为", name, 3)
|
||||
resetColor()
|
||||
public_hello()
|
||||
print("搜索【", name, "】", end="\t", flush=True)
|
||||
api = WinMain(name)
|
||||
print("进入", api.roomLiver, "的直播间")
|
||||
if not api.isValidRoom:
|
||||
input("房间不存在")
|
||||
if not api.isValidUser:
|
||||
input("用户不存在")
|
||||
sys.exit()
|
||||
print("OK")
|
||||
print(api.broadcaster.__repr__())
|
||||
print("更新房间信息,请稍后", end="\t", flush=True)
|
||||
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)
|
||||
while True:
|
||||
if api.isLive:
|
||||
@ -205,4 +233,4 @@ if __name__ == "__main__":
|
||||
print("主播未开播,等待1分钟后重试")
|
||||
resetColor()
|
||||
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
585
api.py
585
api.py
@ -1,206 +1,481 @@
|
||||
# coding=utf-8
|
||||
import sys
|
||||
|
||||
from MemberMsg import MemberMsg
|
||||
from User import User
|
||||
from Gift import Gift
|
||||
from Chat import Chat
|
||||
from Lottery import Lottery
|
||||
from Struct.MemberMsg import MemberMsg
|
||||
from Struct.User import User
|
||||
from Struct.Gift import Gift
|
||||
from Struct.Chat import Chat
|
||||
import requests
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from Xigua_pb2 import XiguaLive
|
||||
from XiguaMessage_pb2 import FansClubMessage, SocialMessage
|
||||
|
||||
s = requests.Session()
|
||||
|
||||
DEBUG: bool = False
|
||||
DEBUG = 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:
|
||||
isLive: bool = False
|
||||
isValidRoom: bool = False
|
||||
_rawRoomInfo = {}
|
||||
name: str = ""
|
||||
roomID: int = 0
|
||||
roomTitle: str = ""
|
||||
roomLiver: User = None
|
||||
roomPopularity: int = 0
|
||||
_cursor:str = "0"
|
||||
_updRoomCount:int = 0
|
||||
lottery:Lottery = None
|
||||
|
||||
def __init__(self, name: str = "永恒de草薙"):
|
||||
self.name = name
|
||||
def __init__(self, name=None):
|
||||
"""
|
||||
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._ext = ""
|
||||
self._cursor = "0"
|
||||
|
||||
def _updateRoomInfo(self, json):
|
||||
if "extra" in json:
|
||||
if "member_count" in json["extra"] and json["extra"]["member_count"] > 0:
|
||||
self.roomPopularity = json["extra"]["member_count"]
|
||||
elif "data" in json:
|
||||
if "popularity" in json["data"]:
|
||||
self.roomPopularity = json["data"]["popularity"]
|
||||
def _updateRoomPopularity(self, _data):
|
||||
"""
|
||||
更新房间人气的方法
|
||||
Update Room Popularity
|
||||
:param _data: Received Message
|
||||
"""
|
||||
if "extra" in _data:
|
||||
if "member_count" in _data["extra"] and _data["extra"]["member_count"] > 0:
|
||||
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)
|
||||
if DEBUG:
|
||||
print(*args)
|
||||
|
||||
def onPresent(self, gift: Gift):
|
||||
"""
|
||||
礼物连击中的消息
|
||||
Message On Sending Presents
|
||||
:param gift: Struct of Gift Message
|
||||
"""
|
||||
print("礼物连击 :", gift)
|
||||
|
||||
def onPresentEnd(self, gift: Gift):
|
||||
"""
|
||||
礼物送完了的提示信息
|
||||
Message On Finished Send Present
|
||||
:param gift: Struct of Gift Message
|
||||
"""
|
||||
print("感谢", gift)
|
||||
|
||||
def onAd(self, i):
|
||||
"""
|
||||
全局广播
|
||||
All Channel Broadcasting Message( Just An Ad )
|
||||
:param i: JSON DATA if you wanna using it
|
||||
"""
|
||||
# print(i)
|
||||
pass
|
||||
|
||||
def onChat(self, chat: Chat):
|
||||
"""
|
||||
聊天信息
|
||||
On Chatting
|
||||
:param chat: Struct of Chat Message
|
||||
"""
|
||||
if not chat.isFiltered:
|
||||
print(chat)
|
||||
|
||||
def onEnter(self, msg: MemberMsg):
|
||||
"""
|
||||
进入房间消息
|
||||
On Entering Room
|
||||
:param msg: Struct of Member Message
|
||||
"""
|
||||
print("提示 :", msg)
|
||||
|
||||
def onSubscribe(self, user: User):
|
||||
"""
|
||||
关注主播时的消息
|
||||
On Subscribe
|
||||
:param user: Struct of User Message
|
||||
"""
|
||||
print("消息 :", user, "关注了主播")
|
||||
|
||||
def onJoin(self, user: User):
|
||||
"""
|
||||
加入粉丝团消息
|
||||
:param user:
|
||||
"""
|
||||
print("欢迎", user, "加入了粉丝团")
|
||||
|
||||
def onMessage(self, msg: str):
|
||||
"""
|
||||
系统消息
|
||||
:param msg:
|
||||
"""
|
||||
print("消息 :", msg)
|
||||
|
||||
def onLike(self, user: User):
|
||||
"""
|
||||
点击喜欢的消息
|
||||
On Like
|
||||
:param user:
|
||||
"""
|
||||
print("用户", user, "点了喜欢")
|
||||
|
||||
def onLeave(self, json: any):
|
||||
"""
|
||||
下播消息
|
||||
On Liver Leave
|
||||
:param json:
|
||||
"""
|
||||
print("消息 :", "主播离开了")
|
||||
self.updRoomInfo()
|
||||
|
||||
def onLottery(self, i:Lottery):
|
||||
print("中奖消息 :", i)
|
||||
def _checkUsernameIsMatched(self, compare=None):
|
||||
"""
|
||||
验证主播名字是自己想要的那个
|
||||
Check name matched
|
||||
:return: bool: 是否匹配
|
||||
"""
|
||||
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):
|
||||
if self.isLive:
|
||||
p = s.post("https://i.snssdk.com/videolive/room/enter?version_code=730"
|
||||
"&device_platform=android",
|
||||
data="room_id={roomID}&version_code=730"
|
||||
"&device_platform=android".format(roomID=self.roomID),
|
||||
headers={"Content-Type":"application/x-www-form-urlencoded"})
|
||||
d = p.json()
|
||||
self.isValidRoom = d["base_resp"]["status_code"] == 0
|
||||
if d["base_resp"]["status_code"] != 0:
|
||||
def _forceSearchUser(self):
|
||||
"""
|
||||
搜索主播名
|
||||
:return:
|
||||
"""
|
||||
_formatData = {"TIMESTAMP": time.time() * 1000, "keyword": self.name}
|
||||
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||
_formatData['COMMON'] = _COMMON
|
||||
_url = SEARCH_USER_API.format_map(_formatData)
|
||||
d = self.getJson(_url)
|
||||
if d is None:
|
||||
print("搜索接口请求失败")
|
||||
return False
|
||||
if "room" not in d and d["room"] is None:
|
||||
self.apiChangedError("Api发生改变,请及时联系我")
|
||||
return False
|
||||
self._rawRoomInfo = d["room"]
|
||||
self.isLive = d["room"]["status"] == 2
|
||||
self.roomLiver = User(d)
|
||||
self.roomTitle = d["room"]["title"]
|
||||
self.roomPopularity = d["room"]["user_count"]
|
||||
l = Lottery(d)
|
||||
if l.isActive:
|
||||
self.lottery = l
|
||||
return True
|
||||
else:
|
||||
p = s.get("https://security.snssdk.com/video/app/search/live/?version_code=730&device_platform=android"
|
||||
"&format=json&keyword={}".format(self.name))
|
||||
d = p.json()
|
||||
self.broadcaster = None
|
||||
self.isValidUser = False
|
||||
self.isLive = False
|
||||
if "data" in d and d["data"] is not None:
|
||||
for i in d["data"]:
|
||||
if i["block_type"] != 0:
|
||||
if self.broadcaster is not None:
|
||||
break
|
||||
if i["card_type"] != 3:
|
||||
continue
|
||||
if len(i["cells"]) == 0:
|
||||
return
|
||||
self.isValidRoom = True
|
||||
self.isLive = i["cells"][0]["anchor"]["user_info"]["is_living"]
|
||||
self.roomID = int(i["cells"][0]["anchor"]["room_id"])
|
||||
self.roomLiver = User(i["cells"][0])
|
||||
if self.isLive:
|
||||
return self.updRoomInfo()
|
||||
else:
|
||||
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:
|
||||
self.isLive = False
|
||||
if self.isLive:
|
||||
self.roomID = self._rawRoomInfo['room_id']
|
||||
return self._getRoomInfo(True)
|
||||
return self.isLive
|
||||
|
||||
@staticmethod
|
||||
def findRoomByUserId(userId:int):
|
||||
p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=userId))
|
||||
if DEBUG:
|
||||
print(p.text)
|
||||
d = p.json()
|
||||
if "data" not in d or "title" not in d["data"] or "id" not in d["data"]:
|
||||
XiGuaLiveApi.apiChangedError("无法获取RoomID,请与我联系")
|
||||
return XiGuaLiveApi()
|
||||
return XiGuaLiveApi(d["data"]["id"])
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def searchLive(keyword):
|
||||
ret = []
|
||||
p = s.get("https://security.snssdk.com/video/app/search/live/?version_code=730&device_platform=android"
|
||||
"&format=json&keyword={}".format(keyword))
|
||||
d = p.json()
|
||||
if "data" in d:
|
||||
for i in d["data"]:
|
||||
if i["block_type"] != 0:
|
||||
continue
|
||||
for _i in i["cells"]:
|
||||
ret.append(_i["room"])
|
||||
return ret
|
||||
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):
|
||||
if not self.isValidRoom:
|
||||
"""
|
||||
获取弹幕
|
||||
"""
|
||||
self.updRoomInfo()
|
||||
if not self.isLive:
|
||||
return
|
||||
p = s.get("https://i.snssdk.com/videolive/im/get_msg?cursor={cursor}&room_id={roomID}"
|
||||
"&version_code=730&device_platform=android".format(
|
||||
roomID=self.roomID,
|
||||
cursor=self._cursor
|
||||
))
|
||||
d = p.json()
|
||||
if "data" not in d or "extra" not in d or "cursor" not in d["extra"]:
|
||||
if DEBUG:
|
||||
print(d)
|
||||
self.apiChangedError("数据结构改变,请与我联系")
|
||||
_formatData = {"TIMESTAMP": time.time() * 1000, "roomId": self.roomID}
|
||||
_COMMON = COMMON_GET_PARAM.format_map(_formatData)
|
||||
_formatData['COMMON'] = _COMMON
|
||||
_formatData['WEBCAST'] = WEBCAST_GET_PARAMS
|
||||
_url = DANMAKU_GET_API.format_map(_formatData)
|
||||
p = self.s.post(_url, data="room_id={roomId}&fetch_rule=0&cursor={cursor}&"
|
||||
"resp_content_type=protobuf&live_id=3&user_id=0&identity=audience&"
|
||||
"last_rtt=85&internal_ext={ext}"
|
||||
.format_map({"roomId":self.roomID, "cursor": self._cursor, "ext": self._ext}),
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"})
|
||||
if p.status_code != 200:
|
||||
return
|
||||
data = XiguaLive()
|
||||
data.ParseFromString(p.content)
|
||||
self._cursor = data.cursor
|
||||
self._ext = data.internal_ext
|
||||
for _each in data.data:
|
||||
if _each.method == "WebcastGiftMessage":
|
||||
_gift = Gift(_each.raw)
|
||||
if _gift.isAnimate() or _gift.isFinished:
|
||||
self.onPresentEnd(_gift)
|
||||
else:
|
||||
self._cursor = d["extra"]["cursor"]
|
||||
if DEBUG:
|
||||
print("Cursor", self._cursor)
|
||||
for i in d['data']:
|
||||
if DEBUG:
|
||||
print(i)
|
||||
if "common" not in i and "method" not in i["common"]:
|
||||
continue
|
||||
if i["common"]['method'] == "VideoLivePresentMessage":
|
||||
self.onPresent(Gift(i))
|
||||
elif i["common"]['method'] == "VideoLivePresentEndTipMessage":
|
||||
self.onPresentEnd(Gift(i))
|
||||
elif i["common"]['method'] == "VideoLiveRoomAdMessage":
|
||||
self.onAd(i)
|
||||
elif i["common"]['method'] == "VideoLiveChatMessage":
|
||||
self.onChat(Chat(i, self.lottery))
|
||||
elif i["common"]['method'] == "VideoLiveMemberMessage":
|
||||
self._updateRoomInfo(i)
|
||||
self.onEnter(MemberMsg(i))
|
||||
elif i["common"]['method'] == "VideoLiveSocialMessage":
|
||||
self.onSubscribe(User(i))
|
||||
elif i["common"]['method'] == "VideoLiveJoinDiscipulusMessage":
|
||||
self.onJoin(User(i))
|
||||
elif i["common"]['method'] == "VideoLiveControlMessage":
|
||||
print("消息:", "主播离开一小会")
|
||||
elif i["common"]['method'] == "VideoLiveDiggMessage":
|
||||
self.onLike(User(i))
|
||||
self.onPresent(_gift)
|
||||
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:
|
||||
pass
|
||||
if self.lottery is None or self.lottery.ID == 0:
|
||||
self.lottery = Lottery(i)
|
||||
self._updRoomCount += 1
|
||||
if self.lottery is not None and self.lottery.ID != 0:
|
||||
self.lottery.update()
|
||||
if self.lottery.isFinished:
|
||||
self.onLottery(self.lottery)
|
||||
self.lottery = None
|
||||
if self._updRoomCount > 120 or len(d['data']) == 0:
|
||||
self.updRoomInfo()
|
||||
self._updRoomCount = 0
|
||||
return
|
||||
|
||||
@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__":
|
||||
@ -209,25 +484,37 @@ if __name__ == "__main__":
|
||||
if sys.argv[-1] == "d":
|
||||
DEBUG = True
|
||||
name = sys.argv[1]
|
||||
print("西瓜直播弹幕助手 by JerryYan")
|
||||
public_hello()
|
||||
print("搜索【", name, "】", end="\t", flush=True)
|
||||
api = XiGuaLiveApi(name)
|
||||
if not api.isValidRoom:
|
||||
print(api.roomID)
|
||||
input("房间不存在")
|
||||
if not api.isValidUser:
|
||||
input("用户不存在")
|
||||
sys.exit()
|
||||
print("进入", api.roomLiver, "的直播间")
|
||||
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)
|
||||
while True:
|
||||
if api.isLive:
|
||||
try:
|
||||
api.getDanmaku()
|
||||
time.sleep(1)
|
||||
except requests.exceptions.BaseHTTPError:
|
||||
print("网络错误,请确认网络")
|
||||
time.sleep(5)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
time.sleep(1)
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
else:
|
||||
print("主播未开播,等待1分钟后重试")
|
||||
time.sleep(60)
|
||||
api.updRoomInfo()
|
||||
api.updRoomInfo(True)
|
||||
|
464
bilibili.py
464
bilibili.py
@ -1,162 +1,19 @@
|
||||
# coding=utf-8
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
|
||||
import rsa
|
||||
import math
|
||||
import base64
|
||||
import hashlib
|
||||
import requests
|
||||
from urllib import parse
|
||||
|
||||
from config import config
|
||||
|
||||
|
||||
class VideoPart:
|
||||
def __init__(self, path, title='', desc=''):
|
||||
self.path = path
|
||||
self.title = title
|
||||
self.desc = desc
|
||||
from bilibiliuploader import core, VideoPart
|
||||
|
||||
|
||||
class Bilibili:
|
||||
def __init__(self, cookie=None):
|
||||
self.files = []
|
||||
self.videos = []
|
||||
self.session = requests.session()
|
||||
if cookie:
|
||||
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)
|
||||
# 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 __init__(self):
|
||||
self.access_token = ""
|
||||
self.session_id = ""
|
||||
self.user_id = ""
|
||||
self.parts = []
|
||||
|
||||
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,
|
||||
parts,
|
||||
@ -190,97 +47,29 @@ class Bilibili:
|
||||
"""
|
||||
self.preUpload(parts)
|
||||
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(...)]
|
||||
:type parts: VideoPart or list<VideoPart>
|
||||
"""
|
||||
|
||||
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
|
||||
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:
|
||||
filepath = part.path
|
||||
filename = os.path.basename(filepath)
|
||||
filesize = os.path.getsize(filepath)
|
||||
self.files.append(part)
|
||||
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})
|
||||
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,
|
||||
@ -307,191 +96,26 @@ class Bilibili:
|
||||
:type cover: str
|
||||
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
|
||||
:type no_reprint: int
|
||||
:param copyright: (optional) 0=转载的, 1=自制的(default)
|
||||
:type copyright: int
|
||||
"""
|
||||
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
|
||||
from Common import appendUploadStatus, modifyLastUploadStatus, appendError
|
||||
if len(self.parts) == 0:
|
||||
return
|
||||
appendUploadStatus("[{}]投稿中,请稍后".format(title))
|
||||
copyright = 2 if source else 1
|
||||
r = self.session.post('https://member.bilibili.com/x/vu/web/add?csrf=' + self.csrf,
|
||||
json={
|
||||
"copyright": copyright,
|
||||
"source": source,
|
||||
"title": title,
|
||||
"tid": tid,
|
||||
"tag": ','.join(tag),
|
||||
"no_reprint": no_reprint,
|
||||
"desc": desc,
|
||||
"cover": cover,
|
||||
"mission_id": 0,
|
||||
"order_id": 0,
|
||||
"videos": self.videos}
|
||||
)
|
||||
print(r.text)
|
||||
if config["mv"]:
|
||||
for _p in self.files:
|
||||
shutil.move(_p.path, config["mtd"])
|
||||
elif config["del"]:
|
||||
for _p in self.files:
|
||||
os.remove(_p.path)
|
||||
try:
|
||||
avid, bvid = core.upload(self.access_token, self.session_id, self.user_id, self.parts, copyright,
|
||||
title=title, tid=tid, tag=','.join(tag), desc=desc, source=source, cover=cover, no_reprint=no_reprint)
|
||||
modifyLastUploadStatus("[{}]投稿成功;AVID【{}】,BVID【{}】".format(title, avid, bvid))
|
||||
self.clear()
|
||||
except Exception as e:
|
||||
modifyLastUploadStatus("[{}]投稿失败".format(title))
|
||||
appendError(e)
|
||||
|
||||
def appendUpload(self,
|
||||
aid,
|
||||
parts,
|
||||
title="",
|
||||
tid="",
|
||||
tag="",
|
||||
desc="",
|
||||
source='',
|
||||
cover='',
|
||||
no_reprint=1,
|
||||
):
|
||||
"""
|
||||
:param aid: just aid
|
||||
:type aid: int
|
||||
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
|
||||
:type parts: VideoPart or list<VideoPart>
|
||||
:param title: video's title
|
||||
:type title: str
|
||||
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
|
||||
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
|
||||
:type tid: int
|
||||
:param tag: video's tag
|
||||
:type tag: list<str>
|
||||
:param desc: video's description
|
||||
:type desc: str
|
||||
:param source: (optional) 转载地址
|
||||
:type source: str
|
||||
:param cover: (optional) cover's URL, use method *cover_up* to get
|
||||
:type cover: str
|
||||
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
|
||||
:type no_reprint: int
|
||||
"""
|
||||
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
|
||||
p = self.session.get("https://member.bilibili.com/x/web/archive/view?aid={}&history=".format(aid))
|
||||
j = p.json()
|
||||
if len(self.videos) == 0:
|
||||
for i in j['data']['videos']:
|
||||
self.videos.append({'filename': i['filename'],
|
||||
'title': i["title"],
|
||||
'desc': i["desc"]})
|
||||
if (title == ""): title = j["data"]["archive"]['title']
|
||||
if (tag == ""): tag = j["data"]["archive"]['tag']
|
||||
if (no_reprint == ""): no_reprint = j["data"]["archive"]['no_reprint']
|
||||
if (desc == ""): desc = j["data"]["archive"]['desc']
|
||||
if (source == ""): source = j["data"]["archive"]['source']
|
||||
if (tid == ""): tid = j["data"]["archive"]['tid']
|
||||
self.preUpload(parts)
|
||||
self.editUpload(aid, title, tid, tag, desc, source, cover, no_reprint)
|
||||
|
||||
def editUpload(self,
|
||||
aid,
|
||||
title,
|
||||
tid,
|
||||
tag,
|
||||
desc,
|
||||
source='',
|
||||
cover='',
|
||||
no_reprint=1,
|
||||
):
|
||||
"""
|
||||
:param aid: just aid
|
||||
:type aid: int
|
||||
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
|
||||
:type parts: VideoPart or list<VideoPart>
|
||||
:param title: video's title
|
||||
:type title: str
|
||||
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
|
||||
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
|
||||
:type tid: int
|
||||
:param tag: video's tag
|
||||
:type tag: list<str>
|
||||
:param desc: video's description
|
||||
:type desc: str
|
||||
:param source: (optional) 转载地址
|
||||
:type source: str
|
||||
:param cover: (optional) cover's URL, use method *cover_up* to get
|
||||
:type cover: str
|
||||
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
|
||||
:type no_reprint: int
|
||||
"""
|
||||
copyright = 2 if source else 1
|
||||
r = self.session.post('https://member.bilibili.com/x/vu/web/edit?csrf=' + self.csrf,
|
||||
json={
|
||||
"aid": aid,
|
||||
"copyright": copyright,
|
||||
"source": source,
|
||||
"title": title,
|
||||
"tid": tid,
|
||||
"tag": ','.join(tag),
|
||||
"no_reprint": no_reprint,
|
||||
"desc": desc,
|
||||
"cover": cover,
|
||||
"mission_id": 0,
|
||||
"order_id": 0,
|
||||
"videos": self.videos}
|
||||
)
|
||||
print(r.text)
|
||||
def reloadFromPrevious(self):
|
||||
...
|
||||
|
||||
def addChannel(self, name, intro=''):
|
||||
"""
|
||||
|
||||
: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']
|
||||
def clear(self):
|
||||
self.parts = []
|
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,189 +1,153 @@
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
import m3u8
|
||||
import queue
|
||||
import threading
|
||||
from config import config
|
||||
from api import XiGuaLiveApi
|
||||
from bilibili import *
|
||||
import Common
|
||||
import os
|
||||
import requests
|
||||
|
||||
q = queue.Queue()
|
||||
base_uri = ""
|
||||
isUpload = False
|
||||
uq = queue.Queue()
|
||||
session = requests.session()
|
||||
|
||||
|
||||
class downloader(XiGuaLiveApi):
|
||||
files = []
|
||||
playlist: str = None
|
||||
|
||||
def updRoomInfo(self):
|
||||
super(downloader, self).updRoomInfo()
|
||||
self.updPlayList()
|
||||
|
||||
def updPlayList(self):
|
||||
if self.isLive:
|
||||
if "stream_url" in self._rawRoomInfo:
|
||||
if self.playlist is None:
|
||||
self.apiChangedError("无法获取直播链接")
|
||||
self.playlist = False
|
||||
else:
|
||||
self.playlist = self._rawRoomInfo["stream_url"]["alternate_pull_url"]
|
||||
self.playlist = self.playlist.replace("_uhd","").replace("_sd","").replace("_ld","")
|
||||
else:
|
||||
print("未开播,等待开播")
|
||||
|
||||
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:
|
||||
def download():
|
||||
while Common.api.isLive and not Common.forceNotDownload:
|
||||
if not Common.streamUrl:
|
||||
Common.appendError("Download with No StreamUrl Specific")
|
||||
break
|
||||
path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv")
|
||||
base_path = Common.config["path"]
|
||||
if not os.path.isdir(base_path):
|
||||
os.makedirs(base_path)
|
||||
try:
|
||||
p = m3u8.load(self.playlist)
|
||||
except:
|
||||
self.updRoomInfo()
|
||||
p = session.get(Common.streamUrl, stream=True, timeout=3)
|
||||
p.raise_for_status()
|
||||
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
|
||||
base_uri = p.base_uri
|
||||
for i in p.files:
|
||||
if i not in self.files:
|
||||
self.files.append(i)
|
||||
print("{} : Add Sequence {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"),
|
||||
len(self.files)))
|
||||
q.put(i)
|
||||
else:
|
||||
print("PlayList {}".format(self.playlist))
|
||||
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))
|
||||
f.write(T)
|
||||
_size += len(T)
|
||||
Common.modifyLastDownloadStatus(
|
||||
"Downloading >{}< @ {:.2f}%".format(path, 100.0 * _size / Common.config["p_s"]))
|
||||
if _size > Common.config["p_s"] and not Common.config["dlO"]:
|
||||
Common.modifyLastDownloadStatus("Download >{}< Exceed MaxSize".format(path))
|
||||
break
|
||||
print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
||||
try:
|
||||
_p = requests.get("{}{}".format(base_uri, i))
|
||||
except:
|
||||
continue
|
||||
f = open(path, "ab")
|
||||
f.write(_p.content)
|
||||
Common.modifyLastDownloadStatus("Download >{}< Finished".format(path))
|
||||
except Exception as e:
|
||||
Common.appendError("Download >{}< With Exception {}".format(path, e.__str__()))
|
||||
Common.api.updRoomInfo(True)
|
||||
finally:
|
||||
f.close()
|
||||
n = True
|
||||
i = q.get()
|
||||
if n:
|
||||
isUpload = True
|
||||
uq.put(path)
|
||||
print("{} : Download Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
||||
if os.path.getsize(os.path.join(base_path, path)) < Common.config["i_s"]:
|
||||
Common.modifyLastDownloadStatus("Downloaded File >{}< is too small, will ignore it".format(path))
|
||||
else:
|
||||
Common.encodeQueue.put(os.path.join(base_path, path))
|
||||
Common.doUpdatePlaylist()
|
||||
Common.api.updRoomInfo(True)
|
||||
|
||||
|
||||
def upload(date=datetime.strftime(datetime.now(), "%Y_%m_%d")):
|
||||
print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
||||
i = uq.get()
|
||||
def encode():
|
||||
Common.appendEncodeStatus("Encode Daemon Starting")
|
||||
while True:
|
||||
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:
|
||||
if isinstance(i, bool):
|
||||
print("{} : Upload Daemon Receive Command {}"
|
||||
.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
||||
if i is True:
|
||||
print("自动投稿中,请稍后")
|
||||
b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"],
|
||||
source=config["src"], no_reprint=0)
|
||||
Common.publishVideo(date)
|
||||
break
|
||||
print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
|
||||
try:
|
||||
b.preUpload(VideoPart(i, i))
|
||||
except:
|
||||
Common.uploadVideo(i)
|
||||
except Exception as e:
|
||||
Common.appendError(e.__str__())
|
||||
continue
|
||||
i = uq.get()
|
||||
print("{} : Upload Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
|
||||
finally:
|
||||
time.sleep(90)
|
||||
i = Common.uploadQueue.get()
|
||||
Common.appendUploadStatus("Upload Daemon Quiting")
|
||||
|
||||
|
||||
b = Bilibili()
|
||||
b.login(config["b_u"], config["b_p"])
|
||||
t = threading.Thread(target=download, args=())
|
||||
ut = threading.Thread(target=upload, args=())
|
||||
et = threading.Thread(target=encode, args=())
|
||||
|
||||
if __name__ == "__main__":
|
||||
name = "永恒de草薙"
|
||||
# room = 75366565294
|
||||
# room = 83940182312 #Dae
|
||||
# room = 5947850784 #⑦
|
||||
# room = 58649240617 #戏
|
||||
if len(sys.argv) > 1:
|
||||
name = sys.argv[1]
|
||||
print("西瓜直播录播助手 by JerryYan")
|
||||
api = downloader(name)
|
||||
print("进入", api.roomLiver, "的直播间")
|
||||
if not api.isValidRoom:
|
||||
input("房间不存在")
|
||||
sys.exit()
|
||||
print("=" * 30)
|
||||
d = datetime.strftime(datetime.now(), "%Y_%m_%d")
|
||||
_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,))
|
||||
|
||||
def awakeEncode():
|
||||
global et
|
||||
if et.is_alive():
|
||||
return True
|
||||
et = threading.Thread(target=encode, args=())
|
||||
et.setDaemon(True)
|
||||
et.start()
|
||||
return False
|
||||
|
||||
|
||||
def awakeDownload():
|
||||
global t
|
||||
if t.is_alive():
|
||||
return True
|
||||
t = threading.Thread(target=download, args=())
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
if not ut.is_alive():
|
||||
ut = threading.Thread(target=upload, args=(d,))
|
||||
Common.api.updRoomInfo()
|
||||
return False
|
||||
|
||||
|
||||
def awakeUpload():
|
||||
global ut
|
||||
if ut.is_alive():
|
||||
return True
|
||||
ut = threading.Thread(target=upload, args=())
|
||||
ut.setDaemon(True)
|
||||
ut.start()
|
||||
api.preDownload()
|
||||
time.sleep(3)
|
||||
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:
|
||||
Common.api.getDanmaku()
|
||||
except Exception as e:
|
||||
Common.appendError(e.__str__())
|
||||
finally:
|
||||
time.sleep(1)
|
||||
else:
|
||||
if d is not None:
|
||||
q.put(False)
|
||||
d = None
|
||||
if isUpload:
|
||||
uq.put(True)
|
||||
isUpload = False
|
||||
else:
|
||||
del config
|
||||
from config import config
|
||||
# print("主播未开播,等待1分钟后重试")
|
||||
time.sleep(60)
|
||||
api.updRoomInfo()
|
||||
try:
|
||||
Common.api.updRoomInfo()
|
||||
except Exception as e:
|
||||
Common.appendError(e.__str__())
|
||||
Common.refreshDownloader()
|
||||
if not Common.api.broadcaster:
|
||||
Common.refreshDownloader()
|
||||
if Common.forceStartEncodeThread:
|
||||
awakeEncode()
|
||||
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