├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── api.py
├── function.py
├── images
├── 22332.png
├── demo1.png
├── demo2.png
└── logo.ico
├── login.py
├── login.ui
├── login_func.py
├── main.py
├── requirements.txt
├── resources.qrc
├── resources_rc.py
├── setting.py
├── setting.ui
├── setting_func.py
├── soft_cfg.py
├── windows.py
└── windows.ui
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | *.json
6 | cache/
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | pip-wheel-metadata/
26 | share/python-wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 | MANIFEST
31 |
32 | # PyInstaller
33 | # Usually these files are written by a python script from a template
34 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
35 | *.manifest
36 | *.spec
37 |
38 | # Installer logs
39 | pip-log.txt
40 | pip-delete-this-directory.txt
41 |
42 | # Unit test / coverage reports
43 | htmlcov/
44 | .tox/
45 | .nox/
46 | .coverage
47 | .coverage.*
48 | .cache
49 | nosetests.xml
50 | coverage.xml
51 | *.cover
52 | *.py,cover
53 | .hypothesis/
54 | .pytest_cache/
55 |
56 | # Translations
57 | *.mo
58 | *.pot
59 |
60 | # Django stuff:
61 | *.log
62 | local_settings.py
63 | db.sqlite3
64 | db.sqlite3-journal
65 |
66 | # Flask stuff:
67 | instance/
68 | .webassets-cache
69 |
70 | # Scrapy stuff:
71 | .scrapy
72 |
73 | # Sphinx documentation
74 | docs/_build/
75 |
76 | # PyBuilder
77 | target/
78 |
79 | # Jupyter Notebook
80 | .ipynb_checkpoints
81 |
82 | # IPython
83 | profile_default/
84 | ipython_config.py
85 |
86 | # pyenv
87 | .python-version
88 |
89 | # pipenv
90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
93 | # install all needed dependencies.
94 | #Pipfile.lock
95 |
96 | # celery beat schedule file
97 | celerybeat-schedule
98 |
99 | # SageMath parsed files
100 | *.sage.py
101 |
102 | # Environments
103 | .env
104 | .venv
105 | env/
106 | venv/
107 | ENV/
108 | env.bak/
109 | venv.bak/
110 |
111 | # Spyder project settings
112 | .spyderproject
113 | .spyproject
114 |
115 | # Rope project settings
116 | .ropeproject
117 |
118 | # mkdocs documentation
119 | /site
120 |
121 | # mypy
122 | .mypy_cache/
123 | .dmypy.json
124 | dmypy.json
125 |
126 | # Pyre type checker
127 | .pyre/
128 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
- Bilibili-Up-Helper -
2 |
3 | 哔哩哔哩UP主助手,更方便的掌握粉丝动态,查看实时数据
4 |
5 | 
6 |
7 | 更详细的Readme文档正在编辑中,软件帮助文档:[https://www.toodo.fun/funs/learn/files/article.php?id=58](https://www.toodo.fun/funs/learn/files/article.php?id=58)
--------------------------------------------------------------------------------
/api.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import json
4 | import requests
5 | import time
6 | from urllib import parse
7 | import rsa
8 |
9 |
10 | class BD:
11 | def __init__(self):
12 | self.app_key = "1d8b6e7d45233436"
13 | self._session = requests.Session()
14 | self._session.headers.update({'User-Agent': "Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)"})
15 | self.get_cookies = lambda: self._session.cookies.get_dict(domain=".bilibili.com")
16 | self.get_uid = lambda: self.get_cookies().get("DedeUserID", "")
17 | self.main_info = {
18 | "nickname": "",
19 | "face": "",
20 | "coins": 0,
21 | "mid": "",
22 | 'level': 0,
23 | 'balance': 0,
24 | "follower": 0,
25 | 'experience': {
26 | 'current': 0,
27 | 'next': 0,
28 | },
29 | 'video': {
30 | "coin": 0,
31 | "favorite": 0,
32 | "like": 0,
33 | "view": 0,
34 | "danmaku": 0,
35 | "reply": 0,
36 | "share": 0,
37 | },
38 | "article": {
39 | "view": 0,
40 | "reply": 0,
41 | "like": 0,
42 | "favorite": 0,
43 | "coin": 0,
44 | "share": 0,
45 | },
46 | "rating": {
47 | "creative": 0,
48 | "influence": 0,
49 | "credit": 0,
50 | }
51 | }
52 | self.notify = {
53 | "at": 0,
54 | "chat": 0,
55 | "like": 0,
56 | "reply": 0,
57 | "sys_msg": 0,
58 | }
59 | self.videos = {
60 | "url": [],
61 | "face": [],
62 | "tag": [],
63 | "title": [],
64 | "view": [],
65 | "danmaku": [],
66 | "reply": [],
67 | "coin": [],
68 | "favorite": [],
69 | "like": [],
70 | "share": [],
71 | "create_time": [],
72 | "state_panel": [],
73 | }
74 | self.article = {
75 | "url": [],
76 | "face": [],
77 | "tag": [],
78 | "title": [],
79 | "view": [],
80 | "reply": [],
81 | "coin": [],
82 | "favorite": [],
83 | "like": [],
84 | "share": [],
85 | "create_time": [],
86 | }
87 | self.reply = {
88 | "title": [],
89 | 'url': [],
90 | "bvid": [],
91 | "id": [],
92 | "floor": [],
93 | "face": [],
94 | "replier": [],
95 | "message": [],
96 | "ctime": [],
97 | "parent": [],
98 | "parent_name": [],
99 | "parent_message": [],
100 | "like": [],
101 | }
102 | self.danmaku = {
103 | "title": [],
104 | 'url': [],
105 | "uname": [],
106 | "id": [],
107 | "message": [],
108 | "ctime": [],
109 | }
110 |
111 | def _requests(self, method, url, decode_level=2, retry=10, timeout=15, **kwargs):
112 | if method in ["get", "post"]:
113 | for _ in range(retry + 1):
114 | try:
115 | response = getattr(self._session, method)(url, timeout=timeout, **kwargs)
116 | return response.json() if decode_level == 2 else response.content if decode_level == 1 else response
117 | except:
118 | pass
119 | return None
120 |
121 | # 验证码识别
122 | def _solve_captcha(self, image):
123 | url = "https://bili.dev:2233/captcha"
124 | payload = {'image': base64.b64encode(image).decode("utf-8")}
125 | response = self._requests("post", url, json=payload)
126 | return response['message'] if response and response.get("code") == 0 else None
127 |
128 | @staticmethod
129 | def calc_sign(param):
130 | salt = "560c52ccd288fed045859ed18bffd973"
131 | sign_hash = hashlib.md5()
132 | sign_hash.update(f"{param}{salt}".encode())
133 | return sign_hash.hexdigest()
134 |
135 | def login(self, **kwargs):
136 | def by_cookies():
137 | url = f"https://api.bilibili.com/x/space/myinfo"
138 | headers = {'Host': "api.bilibili.com"}
139 | response = self._requests("get", url, headers=headers)
140 | if response and response.get("code") != -101:
141 | return True
142 | else:
143 | return False
144 |
145 | def by_token():
146 | param = f"access_key={self.access_token}&appkey={self.app_key}&ts={int(time.time())}"
147 | url = f"https://passport.bilibili.com/api/v2/oauth2/info?{param}&sign={self.calc_sign(param)}"
148 | response = self._requests("get", url)
149 | if response and response.get("code") == 0:
150 | self._session.cookies.set('DedeUserID', str(response['data']['mid']), domain=".bilibili.com")
151 | param = f"access_key={self.access_token}&appkey={self.app_key}&gourl=https%3A%2F%2Faccount.bilibili.com%2Faccount%2Fhome&ts={int(time.time())}"
152 | url = f"https://passport.bilibili.com/api/login/sso?{param}&sign={self.calc_sign(param)}"
153 | self._requests("get", url, decode_level=0)
154 | if all(key in self.get_cookies() for key in
155 | ["bili_jct", "DedeUserID", "DedeUserID__ckMd5", "sid", "SESSDATA"]):
156 | return True
157 | else:
158 | pass
159 | url = f"https://passport.bilibili.com/api/v2/oauth2/refresh_token"
160 | param = f"access_key={self.access_token}&appkey={self.app_key}&refresh_token={self.refresh_token}&ts={int(time.time())}"
161 | payload = f"{param}&sign={self.calc_sign(param)}"
162 | headers = {'Content-type': "application/x-www-form-urlencoded"}
163 | response = self._requests("post", url, data=payload, headers=headers)
164 | if response and response.get("code") == 0:
165 | for cookie in response['data']['cookie_info']['cookies']:
166 | self._session.cookies.set(cookie['name'], cookie['value'], domain=".bilibili.com")
167 | self.access_token = response['data']['token_info']['access_token']
168 | self.refresh_token = response['data']['token_info']['refresh_token']
169 | return True
170 | else:
171 | self.access_token = ""
172 | self.refresh_token = ""
173 | return False
174 |
175 | def by_passwd():
176 | def get_key():
177 | url = f"https://passport.bilibili.com/api/oauth2/getKey"
178 | payload = {
179 | 'appkey': self.app_key,
180 | 'sign': self.calc_sign(f"appkey={self.app_key}"),
181 | }
182 | while True:
183 | response = self._requests("post", url, data=payload)
184 | if response and response.get("code") == 0:
185 | return {
186 | 'key_hash': response['data']['hash'],
187 | 'pub_key': rsa.PublicKey.load_pkcs1_openssl_pem(response['data']['key'].encode()),
188 | }
189 | else:
190 | time.sleep(1)
191 |
192 | while True:
193 | key = get_key()
194 | key_hash, pub_key = key['key_hash'], key['pub_key']
195 | url = f"https://passport.bilibili.com/api/v2/oauth2/login"
196 | param = f"appkey={self.app_key}&password={parse.quote_plus(base64.b64encode(rsa.encrypt(f'{key_hash}{self.password}'.encode(), pub_key)))}&username={parse.quote_plus(self.username)}"
197 | payload = f"{param}&sign={self.calc_sign(param)}"
198 | headers = {'Content-type': "application/x-www-form-urlencoded"}
199 | response = self._requests("post", url, data=payload, headers=headers)
200 | while True:
201 | if response and response.get("code") is not None:
202 | if response['code'] == -105:
203 | url = f"https://passport.bilibili.com/captcha"
204 | headers = {'Host': "passport.bilibili.com"}
205 | response = self._requests("get", url, headers=headers, decode_level=1)
206 | captcha = self._solve_captcha(response)
207 | if captcha:
208 | key = get_key()
209 | key_hash, pub_key = key['key_hash'], key['pub_key']
210 | url = f"https://passport.bilibili.com/api/v2/oauth2/login"
211 | param = f"appkey={self.app_key}&captcha={captcha}&password={parse.quote_plus(base64.b64encode(rsa.encrypt(f'{key_hash}{self.password}'.encode(), pub_key)))}&username={parse.quote_plus(self.username)}"
212 | payload = f"{param}&sign={self.calc_sign(param)}"
213 | headers = {'Content-type': "application/x-www-form-urlencoded"}
214 | response = self._requests("post", url, data=payload, headers=headers)
215 | else:
216 | time.sleep(10)
217 |
218 | elif response['code'] == -449:
219 | time.sleep(1)
220 | response = self._requests("post", url, data=payload, headers=headers)
221 | elif response['code'] == 0 and response['data']['status'] == 0:
222 | for cookie in response['data']['cookie_info']['cookies']:
223 | self._session.cookies.set(cookie['name'], cookie['value'], domain=".bilibili.com")
224 | self.access_token = response['data']['token_info']['access_token']
225 | self.refresh_token = response['data']['token_info']['refresh_token']
226 | return True
227 | else:
228 | return False
229 | else:
230 | time.sleep(60)
231 |
232 | self._session.cookies.clear()
233 | for name in ["bili_jct", "DedeUserID", "DedeUserID__ckMd5", "sid", "SESSDATA"]:
234 | value = kwargs.get(name)
235 | if value:
236 | self._session.cookies.set(name, value, domain=".bilibili.com")
237 | self.access_token = kwargs.get("access_token", "")
238 | self.refresh_token = kwargs.get("refresh_token", "")
239 | self.username = kwargs.get("username", "")
240 | self.password = kwargs.get("password", "")
241 | if (not self.access_token or not self.refresh_token) and all(
242 | key in self.get_cookies() for key in
243 | ["bili_jct", "DedeUserID", "DedeUserID__ckMd5", "sid", "SESSDATA"]) and by_cookies():
244 | print("cookies登陆成功")
245 | return True
246 | elif self.access_token and self.refresh_token and by_token():
247 | print("token登录成功")
248 | return True
249 | elif self.username and self.password and by_passwd():
250 | print("密码登陆成功")
251 | return True
252 | else:
253 | self._session.cookies.clear()
254 | return False
255 |
256 | def get_main_info(self):
257 | self.main_info = {
258 | "nickname": "",
259 | "face": "",
260 | "coins": 0,
261 | "mid": "",
262 | 'level': 0,
263 | 'balance': 0,
264 | "follower": 0,
265 | 'experience': {
266 | 'current': 0,
267 | 'next': 0,
268 | },
269 | 'video': {
270 | "coin": 0,
271 | "favorite": 0,
272 | "like": 0,
273 | "view": 0,
274 | "danmaku": 0,
275 | "reply": 0,
276 | "share": 0,
277 | },
278 | "article": {
279 | "view": 0,
280 | "reply": 0,
281 | "like": 0,
282 | "favorite": 0,
283 | "coin": 0,
284 | "share": 0,
285 | },
286 | "rating": {
287 | "creative": 0,
288 | "influence": 0,
289 | "credit": 0,
290 | }
291 | }
292 | url = f"https://api.bilibili.com/x/space/myinfo?jsonp=jsonp"
293 | headers = {
294 | 'Host': "api.bilibili.com",
295 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
296 | }
297 | headers2 = {
298 | 'Host': "member.bilibili.com",
299 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
300 | }
301 | response = self._requests("get", url, headers=headers)
302 | response0 = self._requests("get", "https://api.bilibili.com/studio/growup/web/up/rating/stat", headers=headers)
303 | if response0 and response0.get("code") == 0:
304 | self.main_info["rating"]["creative"] = response0['data']['creative']
305 | self.main_info["rating"]["influence"] = response0['data']['influence']
306 | self.main_info['rating']["credit"] = response0['data']['credit']
307 | response2 = self._requests("get", "https://member.bilibili.com/x/web/elec/balance", headers=headers2)
308 | if response and response.get("code") == 0 and response2 and response2.get("code") == 0:
309 | self.main_info['experience']['current'] = response['data']['level_exp']['current_exp']
310 | self.main_info['experience']['next'] = response['data']['level_exp']['next_exp']
311 | self.main_info['face'] = response['data']['face']
312 | self.main_info['level'] = response['data']['level']
313 | self.main_info['nickname'] = response['data']['name']
314 | self.main_info['mid'] = self.get_uid()
315 | self.main_info['follower'] = response['data']['follower']
316 | self.main_info['coins'] = response['data']['coins']
317 | self.main_info['balance'] = response2['data']["wallet"]["sponsorBalance"]
318 | response3 = self._requests("get",
319 | f"https://member.bilibili.com/x/web/archives?status=is_pubing%2Cpubed%2Cnot_pubed&pn=1&ps=10&coop=1",
320 | # &interactive=1",
321 | headers=headers2)
322 | if response3 and response3.get("code") == 0:
323 | count = response3["data"]["page"]["count"]
324 | response3 = self._requests("get",
325 | f"https://member.bilibili.com/x/web/archives?status=is_pubing%2Cpubed%2Cnot_pubed&pn=1&ps={count}&coop=1",
326 | # &interactive=1",
327 | headers=headers2)
328 | if response3 and response3.get("code") == 0:
329 | likes, views, reply, danmaku, share, favorite, coin = 0, 0, 0, 0, 0, 0, 0
330 | if response3["data"]["arc_audits"]:
331 | for i in response3["data"]["arc_audits"]:
332 | likes += i["stat"]["like"]
333 | views += i["stat"]["view"]
334 | reply += i["stat"]["reply"]
335 | danmaku += i["stat"]["danmaku"]
336 | share += i["stat"]["share"]
337 | favorite += i["stat"]["favorite"]
338 | coin += i["stat"]["coin"]
339 | self.main_info['video']["like"] = likes
340 | self.main_info['video']["view"] = views
341 | self.main_info['video']["reply"] = reply
342 | self.main_info['video']["danmaku"] = danmaku
343 | self.main_info['video']["share"] = share
344 | self.main_info['video']["favorite"] = favorite
345 | self.main_info['video']["coin"] = coin
346 | response = self._requests("get",
347 | f"https://api.bilibili.com/x/article/creative/article/list?group=0&sort=&pn=1&mobi_app=pc",
348 | headers=headers)
349 | if response and response.get("code") == 0:
350 | count = response["artlist"]["page"]["total"]
351 | if count > 0:
352 | for i in response["artlist"]["articles"]:
353 | self.main_info["article"]["view"] += i["stats"]["view"]
354 | self.main_info["article"]["reply"] += i["stats"]["reply"]
355 | self.main_info["article"]["coin"] += i["stats"]["coin"]
356 | self.main_info["article"]["favorite"] += i["stats"]["favorite"]
357 | self.main_info["article"]["like"] += i["stats"]["like"]
358 | self.main_info["article"]["share"] += i["stats"]["share"]
359 | if count > 20:
360 | if count % 20 == 0:
361 | pn = int(count / 20)
362 | else:
363 | pn = int(count / 20) + 1
364 | for i in range(2, pn + 1):
365 | response = self._requests("get",
366 | f"https://api.bilibili.com/x/article/creative/article/list?group=0&sort=&pn={i}&mobi_app=pc",
367 | headers=headers)
368 | if response and response.get("code") == 0:
369 | if response["artlist"]["articles"]:
370 | for j in response["artlist"]["articles"]:
371 | self.main_info["article"]["view"] += j["stats"]["view"]
372 | self.main_info["article"]["reply"] += j["stats"]["reply"]
373 | self.main_info["article"]["coin"] += j["stats"]["coin"]
374 | self.main_info["article"]["favorite"] += j["stats"]["favorite"]
375 | self.main_info["article"]["like"] += j["stats"]["like"]
376 | self.main_info["article"]["share"] += j["stats"]["share"]
377 | return True
378 | else:
379 | return False
380 |
381 | def get_notify(self):
382 | url = f"https://api.bilibili.com/x/msgfeed/unread?build=0&mobi_app=web"
383 | headers = {
384 | 'Host': "api.bilibili.com",
385 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
386 | }
387 | response = self._requests("get", url, headers=headers)
388 | if response and response.get("code") == 0:
389 | self.notify["at"] = response['data']['at']
390 | self.notify["chat"] = response['data']["chat"]
391 | self.notify["reply"] = response['data']["reply"]
392 | self.notify["like"] = response['data']["like"]
393 | self.notify["sys_msg"] = response['data']["sys_msg"]
394 | return True
395 | else:
396 | return False
397 |
398 | def get_video(self):
399 | headers2 = {
400 | 'Host': "member.bilibili.com",
401 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
402 | }
403 | response3 = self._requests("get",
404 | f"https://member.bilibili.com/x/web/archives?status=is_pubing%2Cpubed%2Cnot_pubed&pn=1&ps=10&coop=1",
405 | # &interactive=1",
406 | headers=headers2)
407 | if response3 and response3.get("code") == 0:
408 | count = response3["data"]["page"]["count"]
409 | response3 = self._requests("get",
410 | f"https://member.bilibili.com/x/web/archives?status=is_pubing%2Cpubed%2Cnot_pubed&pn=1&ps={count}&coop=1",
411 | # &interactive=1",
412 | headers=headers2)
413 | if response3 and response3.get("code") == 0:
414 | if response3["data"]["arc_audits"]:
415 | for i in response3["data"]["arc_audits"]:
416 | self.videos["face"].append(i["Archive"]["cover"])
417 | self.videos["url"].append(f"https://www.bilibili.com/video/{i['Archive']['bvid']}")
418 | self.videos["tag"].append(i["typename"])
419 | self.videos["title"].append(i["Archive"]["title"])
420 | self.videos["view"].append(i["stat"]["view"])
421 | self.videos["danmaku"].append(i["stat"]["danmaku"])
422 | self.videos["reply"].append(i["stat"]["reply"])
423 | self.videos["coin"].append(i["stat"]["coin"])
424 | self.videos["favorite"].append(i["stat"]["favorite"])
425 | self.videos["like"].append(i["stat"]["like"])
426 | self.videos["share"].append(i["stat"]["share"])
427 | self.videos["create_time"].append(i["Archive"]["ptime"])
428 | self.videos["state_panel"].append(i["state_panel"])
429 | return True
430 | else:
431 | return False
432 | else:
433 | return False
434 |
435 | def get_article(self):
436 | headers = {
437 | 'Host': "api.bilibili.com",
438 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
439 | }
440 | response = self._requests("get",
441 | f"https://api.bilibili.com/x/article/creative/article/list?group=0&sort=&pn=1&mobi_app=pc",
442 | headers=headers)
443 | if response and response.get("code") == 0:
444 | count = response["artlist"]["page"]["total"]
445 | if count > 0:
446 | for i in response["artlist"]["articles"]:
447 | self.article["url"].append(i["view_url"])
448 | self.article["face"].append(i["origin_image_urls"][0])
449 | self.article["tag"].append(i["category"]["name"])
450 | self.article["title"].append(i["title"])
451 | self.article["view"].append(i["stats"]["view"])
452 | self.article["reply"].append(i["stats"]["reply"])
453 | self.article["coin"].append(i["stats"]["coin"])
454 | self.article["favorite"].append(i["stats"]["favorite"])
455 | self.article["like"].append(i["stats"]["like"])
456 | self.article["share"].append(i["stats"]["share"])
457 | self.article["create_time"].append(i["publish_time"])
458 | if count > 20:
459 | if count % 20 == 0:
460 | pn = int(count / 20)
461 | else:
462 | pn = int(count / 20) + 1
463 | for i in range(2, pn + 1):
464 | response = self._requests("get",
465 | f"https://api.bilibili.com/x/article/creative/article/list?group=0&sort=&pn={i}&mobi_app=pc",
466 | headers=headers)
467 | if response and response.get("code") == 0:
468 | if response["artlist"]["articles"]:
469 | for j in response["artlist"]["articles"]:
470 | self.article["url"].append(j["view_url"])
471 | self.article["face"].append(j["origin_image_urls"][0])
472 | self.article["tag"].append(j["category"]["name"])
473 | self.article["title"].append(j["title"])
474 | self.article["view"].append(j["stats"]["view"])
475 | self.article["reply"].append(j["stats"]["reply"])
476 | self.article["coin"].append(j["stats"]["coin"])
477 | self.article["favorite"].append(j["stats"]["favorite"])
478 | self.article["like"].append(j["stats"]["like"])
479 | self.article["share"].append(j["stats"]["share"])
480 | self.article["create_time"].append(j["publish_time"])
481 | return True
482 | else:
483 | return False
484 |
485 | def get_reply(self):
486 | self.reply = {
487 | "title": [],
488 | 'url': [],
489 | "bvid": [],
490 | "id": [],
491 | "floor": [],
492 | "face": [],
493 | "replier": [],
494 | "message": [],
495 | "ctime": [],
496 | "parent": [],
497 | "parent_name": [],
498 | "parent_message": [],
499 | "like": [],
500 | }
501 | headers = {
502 | 'Host': "member.bilibili.com",
503 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
504 | }
505 | response = self._requests("get",
506 | f"https://member.bilibili.com/x/web/replies?order=ctime&filter=-1&is_hidden=0&type=1&bvid=&pn=1&ps=1",
507 | headers=headers)
508 | if response and response.get("code") == 0:
509 | count = response["pager"]["total"]
510 | if count > 100:
511 | count = 100 # 只显示最新的100条评论
512 | response = self._requests("get",
513 | f"https://member.bilibili.com/x/web/replies?order=ctime&filter=-1&is_hidden=0&type=1&bvid=&pn=1&ps={count}",
514 | headers=headers)
515 | if response and response.get("code") == 0:
516 | if response["data"]:
517 | for i in response["data"]:
518 | try:
519 | self.reply['title'].append(i['title'])
520 | self.reply['url'].append(f"https://www.bilibili.com/video/{i['bvid']}")
521 | self.reply['id'].append(i['id'])
522 | self.reply['floor'].append(i['floor'])
523 | self.reply['replier'].append(i['replier'])
524 | self.reply['message'].append(i['message'])
525 | self.reply['ctime'].append(i['ctime'])
526 | self.reply['face'].append(i['cover'])
527 | # self.reply['parent'].append(i['parent'])
528 | if i.get("parent_info"):
529 | self.reply['parent'].append(1)
530 | parent = 1
531 | else:
532 | self.reply['parent'].append(0)
533 | parent = 0
534 | if parent == 0:
535 | self.reply['parent_name'].append("")
536 | self.reply['parent_message'].append("")
537 | else:
538 | self.reply['parent_name'].append(i['root_info']['member']['uname'])
539 | self.reply['parent_message'].append(i['root_info']['content']['message'])
540 | self.reply['like'].append(i['like'])
541 | except Exception as e:
542 | print(f"api.get_reply: {e, i}")
543 | pass
544 | return True
545 | else:
546 | return False
547 | else:
548 | return False
549 |
550 | def get_danmaku(self):
551 | self.danmaku = {
552 | "title": [],
553 | 'url': [],
554 | "id": [],
555 | "uname": [],
556 | "message": [],
557 | "ctime": [],
558 | }
559 | headers = {
560 | 'Host': "api.bilibili.com",
561 | 'Referer': f"https://space.bilibili.com/{self.get_uid()}/",
562 | }
563 | response = self._requests("get",
564 | f"https://api.bilibili.com/x/v2/dm/recent?pn=1&ps=1",
565 | headers=headers)
566 | if response and response.get("code") == 0:
567 | count = response["data"]["page"]["total"]
568 | if count > 500:
569 | count = 500 # 只显示最新的100条评论
570 | response = self._requests("get",
571 | f"https://api.bilibili.com/x/v2/dm/recent?pn=1&ps={count}",
572 | headers=headers)
573 | if response and response.get("code") == 0:
574 | if response["data"]["result"]:
575 | for i in response["data"]["result"]:
576 | try:
577 | self.danmaku['title'].append(i['title'])
578 | self.danmaku['url'].append(f"https://www.bilibili.com/video/{i['bvid']}")
579 | self.danmaku['id'].append(i['id'])
580 | self.danmaku['uname'].append(i['uname'])
581 | self.danmaku['message'].append(i['msg'])
582 | self.danmaku['ctime'].append(i['ctime'])
583 | except Exception as e:
584 | print(f"api.get_reply: {e, i}")
585 | pass
586 | return True
587 | else:
588 | return False
589 | else:
590 | return False
591 |
592 |
593 | if __name__ == '__main__':
594 | app = BD()
595 | login_info = {}
596 | try:
597 | with open("config.json", "r") as f:
598 | login_info = json.loads(f.readline())
599 | if app.login(**login_info):
600 | print("A登录成功")
601 | cookies = app.get_cookies()
602 | for i in cookies:
603 | login_info[i] = cookies[i]
604 | login_info["access_token"] = app.access_token
605 | login_info["refresh_token"] = app.refresh_token
606 | with open("config.json", "w") as f:
607 | f.write(json.dumps(login_info))
608 | if app.get_main_info():
609 | print(app.main_info)
610 | else:
611 | print("A登陆失败")
612 | except:
613 | pass
614 |
--------------------------------------------------------------------------------
/function.py:
--------------------------------------------------------------------------------
1 | import time
2 | import requests
3 | from PyQt5 import QtWidgets, QtCore, QtGui
4 | from PyQt5.QtCore import QThread, pyqtSignal, Qt, QSize
5 | from PyQt5.QtGui import QImage, QPixmap, QIcon, QCursor, QMovie
6 | from PyQt5.QtWidgets import QMessageBox, QSystemTrayIcon, QMenu, QApplication, QAction, qApp, QDesktopWidget, QWidget, \
7 | QHBoxLayout, QLabel, QVBoxLayout, QPushButton, QListWidgetItem
8 | from windows import Ui_MainWindow
9 | from setting_func import setting_UI
10 | import qtawesome
11 | import api
12 | import json
13 | import os
14 | import soft_cfg
15 | import resources_rc
16 |
17 |
18 | def pic_cache(url):
19 | if not os.path.exists("cache"):
20 | os.mkdir("cache")
21 | if os.path.exists(f"cache/{url.split('/')[-1]}"):
22 | pass
23 | else:
24 | pic = requests.get(url).content
25 | try:
26 | with open(f"cache/{url.split('/')[-1]}", "wb") as f:
27 | f.write(pic)
28 | except Exception as e:
29 | print(e)
30 | qApp.quit()
31 | return f"cache/{url.split('/')[-1]}"
32 |
33 |
34 | class fun_main(Ui_MainWindow, QtWidgets.QMainWindow):
35 | def __init__(self, cookies):
36 | super(fun_main, self).__init__()
37 |
38 | # 版本控制
39 | self.version = soft_cfg.version
40 | self.soft_name = soft_cfg.soft_name
41 |
42 | # self.load_data()
43 | self.setupUi(self)
44 | self.setWindowOpacity(1) # 设置窗口透明度
45 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 主窗口透明
46 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
47 | # self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) # 窗口始终置顶
48 | # self.setWindowFlag(Qt.Tool) # 隐藏任务栏图标
49 | self.setWindowIcon(QIcon(':/images/logo.ico'))
50 | self.init_systray()
51 | self.set_win_center()
52 | self.signal_on_button()
53 | self.set_icon()
54 | self.getSettingSignal({})
55 | self.m_flag = False
56 | self.notify_flag = False
57 | self.notify_enable = True
58 | self.cookies = cookies
59 | self.video_url = {}
60 | self.article_url = {}
61 | self.reply_url = {}
62 | self.danmaku_url = {}
63 | self.main_thread()
64 | self.notify_thread()
65 | self.video_thread()
66 | self.article_thread()
67 | self.reply_thread()
68 | self.danmaku_thread()
69 | self.update_thread()
70 |
71 | def Setting(self):
72 | my = setting_UI()
73 | my.mySignal.connect(self.getSettingSignal)
74 | my.exec_()
75 |
76 | def init_UI(self):
77 | try:
78 | with open("UI_config.json", "r") as f:
79 | msm = json.loads(f.readline())
80 | self.getSettingSignal(msm)
81 | except:
82 | pass
83 |
84 | def getSettingSignal(self, msm):
85 | if not msm:
86 | try:
87 | with open("UI_config.json", "r") as f:
88 | msm = json.loads(f.readline())
89 | except Exception as e:
90 | print(e)
91 | msm = {'color': ['#4568DC', '#B06AB3'], 'pic': ':/images/demo1.png'}
92 | else:
93 | with open("UI_config.json", "w") as f:
94 | f.write(json.dumps(msm))
95 | # print(msm)
96 | self.gif = QMovie(msm.get("pic"))
97 | self.gif.setScaledSize(QSize(200, 200))
98 | self.label_left_b1.setMovie(self.gif)
99 | self.gif.start()
100 | # self.label_left_b1.setPixmap(QtGui.QPixmap(msm.get("pic")))
101 | # self.label_left_b1.setScaledContents(True)
102 | # self.label_left_b1.setPixmap(QtGui.QPixmap("images/22332.png"))
103 | self.widget_top.setStyleSheet(
104 | "QWidget#widget_top{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0" + f" {msm.get('color')[0]},stop:1 {msm.get('color')[1]})" + ";border-top-left-radius:2px;border-top-right-radius:2px;}")
105 | self.progressBar.setStyleSheet(
106 | "QProgressBar::chunk{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0" + f" {msm.get('color')[0]},stop:1 {msm.get('color')[1]})" + ";}")
107 |
108 | def signal_on_button(self):
109 | self.pushButton_close.clicked.connect(self.win_close)
110 | self.pushButton_min.clicked.connect(self.showMinimized)
111 | self.pushButton_feedback.clicked.connect(lambda: self.open_browser(soft_cfg.feedback_url))
112 | self.pushButton_notify.clicked.connect(self.notify_clicked)
113 | self.listWidget.itemClicked.connect(self.vitem_clicked)
114 | self.listWidget_article.itemClicked.connect(self.aitem_clicked)
115 | self.listWidget_reply.itemClicked.connect(self.ritem_clicked)
116 | self.listWidget_danmaku.itemClicked.connect(self.ditem_clicked)
117 | self.pushButton_vrenew.clicked.connect(self.video_thread)
118 | self.pushButton_arenew.clicked.connect(self.article_thread)
119 | self.pushButton_rrenew.clicked.connect(self.reply_thread)
120 | self.pushButton_drenew.clicked.connect(self.danmaku_thread)
121 | self.pushButton_setting.clicked.connect(self.Setting)
122 | self.pushButton_max.clicked.connect(self.window_max)
123 |
124 | def set_icon(self):
125 | self.pushButton_notify.setIcon(qtawesome.icon('fa.bell', color="white"))
126 | self.pushButton_feedback.setIcon(qtawesome.icon('fa.envelope-o', color="white"))
127 | self.pushButton_min.setIcon(qtawesome.icon('fa.window-minimize', color='white'))
128 | self.pushButton_close.setIcon(qtawesome.icon('fa.close', color='white'))
129 | # self.pushButton_coin.setIcon(qtawesome.icon('fa.bold', color='blank'))
130 | # self.pushButton_balance.setIcon(qtawesome.icon('fa.flash', color='blank'))
131 | # self.pushButton_reply.setIcon(qtawesome.icon('fa.reply', color='blank'))
132 | # self.pushButton_like.setIcon(qtawesome.icon('fa.thumbs-up', color='blank'))
133 | # self.pushButton_sysnotify.setIcon(qtawesome.icon('fa.bell', color='blank'))
134 | self.pushButton_vrenew.setIcon(qtawesome.icon('fa.refresh', color='blank'))
135 | self.pushButton_arenew.setIcon(qtawesome.icon('fa.refresh', color='blank'))
136 | self.pushButton_rrenew.setIcon(qtawesome.icon('fa.refresh', color="blank"))
137 | self.pushButton_drenew.setIcon(qtawesome.icon('fa.refresh', color="blank"))
138 | self.pushButton_setting.setIcon(qtawesome.icon('fa.cog', color='white'))
139 | self.pushButton_max.setIcon(qtawesome.icon('fa.window-maximize', color='white'))
140 |
141 | def init_systray(self):
142 | self.tray = QSystemTrayIcon(self)
143 | self.tray.setIcon(QIcon(':/images/logo.ico'))
144 | self.tray.setToolTip("哔哩哔哩UP主助手")
145 | self.tray.activated.connect(self.tray_act) # 设置托盘点击事件处理函数
146 | self.tray_menu = QMenu(QApplication.desktop()) # 创建菜单
147 | self.tray_menu.setWindowFlags(self.tray_menu.windowFlags() | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
148 | self.tray_menu.setStyleSheet('''QMenu::item {border-radius: 4px;padding: 8px 48px 8px 16px;background-color: transparent;}
149 | QMenu::item:selected { background-color:rgb(240,245,255);}
150 | ''')
151 | self.NicknameAction = QAction('请叫我雯子小姐的小爷', self)
152 | self.tray_coin = QAction("硬币:0")
153 | self.tray_balance = QAction("电池:0")
154 | self.tray_follower = QAction("粉丝:0")
155 | self.LogoutAction = QAction('退出登录', self)
156 | self.FeedbackAction = QAction("反馈与建议", self)
157 | self.RestoreAction = QAction('显示主界面', self) # 添加一级菜单动作选项(还原主窗口)
158 | self.UpdateAction = QAction('检查更新', self)
159 | self.QuitAction = QAction('退出程序', self) # 添加一级菜单动作选项(退出程序)
160 | self.RestoreAction.triggered.connect(self.show)
161 | self.QuitAction.triggered.connect(self.close)
162 | self.LogoutAction.triggered.connect(self.logout)
163 | self.FeedbackAction.triggered.connect(lambda: self.open_browser(soft_cfg.feedback_url))
164 | self.UpdateAction.triggered.connect(lambda: self.update_thread(auto=False))
165 | self.tray_coin.setIcon(qtawesome.icon('fa.btc', color="blank"))
166 | self.tray_balance.setIcon(qtawesome.icon('fa.flash', color='blank'))
167 | self.tray_follower.setIcon(qtawesome.icon('fa.user', color='blank'))
168 | self.LogoutAction.setIcon(qtawesome.icon('fa.sign-out', color="blank"))
169 | self.FeedbackAction.setIcon(qtawesome.icon('fa.envelope-o', color="blank"))
170 | self.RestoreAction.setIcon(qtawesome.icon('fa.home', color='blank'))
171 | self.UpdateAction.setIcon(qtawesome.icon('fa.refresh', color='blank'))
172 | self.QuitAction.setIcon(qtawesome.icon('fa.sign-out', color='blank'))
173 | self.tray_menu.addAction(self.NicknameAction)
174 | self.tray_menu.addAction(self.tray_coin)
175 | self.tray_menu.addAction(self.tray_balance)
176 | self.tray_menu.addAction(self.tray_follower)
177 | self.tray_menu.addAction(self.LogoutAction)
178 | self.tray_menu.addSeparator()
179 | self.tray_menu.addAction(self.FeedbackAction)
180 | self.tray_menu.addAction(self.RestoreAction) # 为菜单添加动作
181 | self.tray_menu.addAction(self.UpdateAction)
182 | self.tray_menu.addAction(self.QuitAction)
183 | self.tray.setContextMenu(self.tray_menu) # 设置系统托盘菜单
184 | self.tray.messageClicked.connect(self.notify_clicked)
185 | self.tray.show()
186 |
187 | # self.tray.showMessage('Hello', '我藏好了', icon=0) # 参数1:标题 参数2:内容 参数3:图标(0没有图标 1信息图标 2警告图标 3错误图标),0还是有一个小图标
188 |
189 | def tray_act(self, reason):
190 | # 鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击
191 | if reason == 2 or reason == 3:
192 | self.show()
193 |
194 | def window_max(self):
195 | if self.isMaximized():
196 | self.showNormal()
197 | self.pushButton_max.setToolTip("窗口最大化")
198 | else:
199 | self.showMaximized()
200 | self.pushButton_max.setToolTip("恢复默认大小")
201 |
202 | def logout(self):
203 | with open("config.json", "w") as f:
204 | f.write("{}")
205 | QMessageBox.information(self, '小助手提示', '退出登录成功,请重新登录')
206 | self.tray.hide()
207 | self.destroy()
208 | qApp.exit(101)
209 |
210 | def set_win_center(self):
211 | qr = self.frameGeometry()
212 | cp = QDesktopWidget().availableGeometry().center()
213 | # 显示到屏幕中心
214 | qr.moveCenter(cp)
215 | self.move(qr.topLeft())
216 |
217 | def win_close(self):
218 | self.hide()
219 | # self.tray.showMessage('Hello', '我藏好了', icon=0)
220 |
221 | def open_browser(self, url):
222 | QtGui.QDesktopServices.openUrl(QtCore.QUrl(url))
223 |
224 | def notify_clicked(self):
225 | self.notify_flag = False
226 | self.pushButton_notify.setText("通知:你有 0 条未读消息")
227 | self.open_browser("https://message.bilibili.com/#/")
228 |
229 | def main_thread(self):
230 | try:
231 | self.pushButton_nickname.setText("正在获取信息中...")
232 | self.main_Thread = Main_Thread(self.cookies)
233 | self.main_Thread.display_signal.connect(self.change_UI)
234 | self.main_Thread.start()
235 | except Exception as e:
236 | print(e)
237 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
238 |
239 | def change_UI(self, msm):
240 | # print(f"UI: {msm}")
241 | if msm.get("error", 0) == 1:
242 | reply = QtWidgets.QMessageBox.question(self,
243 | '登录状态失效',
244 | "请重新登录",
245 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
246 | QtWidgets.QMessageBox.No)
247 | if reply == QtWidgets.QMessageBox.Yes:
248 | self.tray.hide()
249 | self.destroy()
250 | qApp.exit(101)
251 | else:
252 | self.tray.hide()
253 | self.destroy()
254 | qApp.exit(101)
255 | else:
256 | self.pushButton_nickname.setText(msm["nickname"])
257 | self.NicknameAction.setText(msm["nickname"])
258 | try:
259 | self.pushButton_nickname.clicked.disconnect()
260 | except Exception as e:
261 | print(f"clike: {e}")
262 | pass
263 | self.pushButton_nickname.clicked.connect(
264 | lambda: self.open_browser(f"https://space.bilibili.com/{msm['mid']}"))
265 | face = pic_cache(msm['face'])
266 | try:
267 | self.label_face.setPixmap(QPixmap(face))
268 | except Exception as e:
269 | print(f"face_Main: {e}")
270 | img = QImage.fromData(
271 | requests.get(msm["face"]).content)
272 | self.label_face.setPixmap(QPixmap.fromImage(img))
273 | self.label_face.setScaledContents(True)
274 | self.label_level.setText(f"等级 {msm['level']}")
275 | self.label_exp.setText(f'{msm["experience"]["current"]}/{msm["experience"]["next"]}')
276 | self.progressBar.setValue(int(msm["experience"]["current"] / msm["experience"]["next"] * 100))
277 | self.pushButton_coin.setText(f"硬币:{msm['coins']}")
278 | self.pushButton_balance.setText(f"电池:{msm['balance']}")
279 | self.label_follower.setText(f"粉丝\n{msm['follower']}")
280 | self.tray_coin.setText(f"硬币:{msm['coins']}")
281 | self.tray_balance.setText(f"电池:{msm['balance']}")
282 | self.tray_follower.setText(f"粉丝:{msm['follower']}")
283 | self.label_like.setText(f"点赞\n{msm['video']['like']}")
284 | self.label_view.setText(f"播放\n{msm['video']['view']}")
285 | self.label_reply.setText(f"评论\n{msm['video']['reply']}")
286 | self.label_danmaku.setText(f"弹幕\n{msm['video']['danmaku']}")
287 | self.label_share.setText(f"分享\n{msm['video']['share']}")
288 | self.label_favorite.setText(f"收藏\n{msm['video']['favorite']}")
289 | self.label_coin.setText(f"投币\n{msm['video']['coin']}")
290 | self.label_artview.setText(f"阅读量\n{msm['article']['view']}")
291 | self.label_artlike.setText(f"点赞\n{msm['article']['like']}")
292 | self.label_artcoin.setText(f"投币\n{msm['article']['coin']}")
293 | self.label_artreply.setText(f"评论\n{msm['article']['reply']}")
294 | self.label_artshare.setText(f"分享\n{msm['article']['share']}")
295 | self.label_artfav.setText(f"收藏\n{msm['article']['favorite']}")
296 | self.label_creative.setText(f"创作力\n{msm['rating']['creative']}")
297 | self.label_influence.setText(f"影响力\n{msm['rating']['influence']}")
298 | self.label_credit.setText(f"信用分\n{msm['rating']['credit']}")
299 | # self.label_balance.setText(f"充电\n{msm['balance']}")
300 | print("成功刷新UI")
301 |
302 | def notify_thread(self):
303 | try:
304 | self.notify_Thread = Notify_Thread(self.cookies)
305 | self.notify_Thread.display_signal.connect(self.Notify_UI)
306 | self.notify_Thread.start()
307 | except:
308 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
309 |
310 | def Notify_UI(self, msm):
311 | # print(f"notify: {msm}")
312 | if msm.get("error", 0) == 1:
313 | reply = QtWidgets.QMessageBox.question(self,
314 | '系统通知线程已经停止',
315 | "系统通知模块停止了工作(不影响主程序),是否重启软件尝试恢复",
316 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
317 | QtWidgets.QMessageBox.No)
318 | if reply == QtWidgets.QMessageBox.Yes:
319 | self.tray.hide()
320 | self.destroy()
321 | qApp.exit(101)
322 | else:
323 | pass
324 | else:
325 | notify = "通知:你有"
326 | tray_notify = "哔哩哔哩UP主助手\n"
327 | if msm.get("at") != 0:
328 | notify += f" {msm.get('at')} 条@你的消息 "
329 | tray_notify += f"@你的:{msm.get('at')}\n"
330 | if not self.notify_flag and self.notify_enable:
331 | self.notify_flag = True
332 | self.tray.showMessage('新的@消息', f"你收到了 {msm.get('at')} 条@消息", icon=1)
333 | if msm.get("chat") != 0:
334 | notify += f" {msm.get('chat')} 条聊天消息 "
335 | tray_notify += f"私信消息:{msm.get('chat')}\n"
336 | if not self.notify_flag and self.notify_enable:
337 | self.notify_flag = True
338 | self.tray.showMessage('新的聊天消息', f"你收到了 {msm.get('chat')} 条新的聊天消息", icon=1)
339 | if msm.get("reply") != 0:
340 | notify += f" {msm.get('reply')} 条回复你的消息 "
341 | tray_notify += f"回复消息:{msm.get('reply')}\n"
342 | if not self.notify_flag and self.notify_enable:
343 | self.notify_flag = True
344 | self.tray.showMessage('新的回复', f"你收到了 {msm.get('reply')} 条新的回复", icon=1)
345 | if msm.get("sys_msg") != 0:
346 | notify += f" {msm.get('sys_msg')} 条系统通知 "
347 | tray_notify += f"系统通知:{msm.get('sys_msg')}\n"
348 | if not self.notify_flag and self.notify_enable:
349 | self.notify_flag = True
350 | self.tray.showMessage("收到一条系统通知", f"你收到了 {msm.get('sys_msg')} 条新的系统通知", icon=1)
351 | if msm.get("like") != 0:
352 | notify += f" {msm.get('like')} 个新收到的赞 "
353 | tray_notify += f"收到的赞:{msm.get('like')}"
354 | if not self.notify_flag and self.notify_enable:
355 | self.notify_flag = True
356 | # self.tray.showMessage('新的点赞', f"你新收到了 {msm.get('like')} 个赞", icon=1)
357 | if msm.get("at") == msm.get("chat") == msm.get("like") == msm.get("reply") == msm.get("sys_msg") == 0:
358 | notify += f" 0 条未读消息"
359 | tray_notify += "没有未读消息"
360 | self.pushButton_notify.setText(notify)
361 | self.tray.setToolTip(tray_notify)
362 | print("成功刷新Notify")
363 |
364 | def video_thread(self):
365 | try:
366 | self.pushButton_vrenew.setText(f"获取中...")
367 | self.video_Thread = Video_Thread(self.cookies)
368 | self.video_Thread.display_signal.connect(self.Video_UI)
369 | self.video_Thread.start()
370 | except:
371 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
372 |
373 | def Video_UI(self, msm):
374 | # print(f"video: {msm}")
375 | if msm.get("error", 0) == 1:
376 | reply = QtWidgets.QMessageBox.question(self,
377 | '视频稿件线程出错',
378 | "视频稿件模块停止了工作(不影响主程序),是否重启软件尝试恢复",
379 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
380 | QtWidgets.QMessageBox.No)
381 | if reply == QtWidgets.QMessageBox.Yes:
382 | self.tray.hide()
383 | self.destroy()
384 | qApp.exit(101)
385 | else:
386 | pass
387 | else:
388 | a = time.time()
389 | try:
390 | self.listWidget.clear()
391 | except Exception as e:
392 | print(e)
393 | pass
394 | if msm["video_url"]:
395 | self.video_url = msm["video_url"]
396 | self.label_vtot.setText(f"共有 {len(self.video_url)} 个视频稿件")
397 | for i in msm["widgets"]:
398 | item = QListWidgetItem() # 创建QListWidgetItem对象
399 | item.setSizeHint(QSize(200, 100)) # 设置QListWidgetItem大小
400 | QApplication.processEvents()
401 | widget = self.get_item_wight(i) # 调用上面的函数获取对应
402 | QApplication.processEvents()
403 | self.listWidget.addItem(item) # 添加item
404 | self.listWidget.setItemWidget(item, widget)
405 | else:
406 | self.label_vtot.setText(f"暂时没有视频稿件")
407 | self.pushButton_vrenew.setText("")
408 |
409 | def article_thread(self):
410 | try:
411 | self.pushButton_arenew.setText(f"获取中...")
412 | self.article_Thread = Article_Thread(self.cookies)
413 | self.article_Thread.display_signal.connect(self.Article_UI)
414 | self.article_Thread.start()
415 | except:
416 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
417 |
418 | def Article_UI(self, msm):
419 | if msm.get("error", 0) == 1:
420 | reply = QtWidgets.QMessageBox.question(self,
421 | '专栏文章线程出错',
422 | "已经停止使用了专栏文章模块(不影响主程序),是否重启软件尝试恢复",
423 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
424 | QtWidgets.QMessageBox.No)
425 | if reply == QtWidgets.QMessageBox.Yes:
426 | self.tray.hide()
427 | self.destroy()
428 | qApp.exit(101)
429 | else:
430 | pass
431 | else:
432 | try:
433 | self.listWidget_article.clear()
434 | except Exception as e:
435 | print(e)
436 | pass
437 | if msm["article_url"]:
438 | self.article_url = msm["article_url"]
439 | self.label_atot.setText(f"共有 {len(self.article_url)} 个专栏文章")
440 | for i in msm["widgets"]:
441 | item = QListWidgetItem() # 创建QListWidgetItem对象
442 | item.setSizeHint(QSize(200, 100)) # 设置QListWidgetItem大小
443 | QApplication.processEvents()
444 | widget = self.get_item_wight(i) # 调用上面的函数获取对应
445 | QApplication.processEvents()
446 | self.listWidget_article.addItem(item) # 添加item
447 | self.listWidget_article.setItemWidget(item, widget)
448 | else:
449 | self.label_atot.setText(f"暂时没有专栏文章")
450 | self.pushButton_arenew.setText("")
451 |
452 | def reply_thread(self):
453 | try:
454 | self.pushButton_rrenew.setText(f"获取中...")
455 | self.reply_Thread = Reply_Thread(self.cookies)
456 | self.reply_Thread.display_signal.connect(self.Reply_UI)
457 | self.reply_Thread.start()
458 | except:
459 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
460 |
461 | def Reply_UI(self, msm):
462 | if msm.get("error", 0) == 1:
463 | reply = QtWidgets.QMessageBox.question(self,
464 | '评论线程出错',
465 | "已经停止使用评论功能(不影响主程序),是否重启软件尝试恢复",
466 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
467 | QtWidgets.QMessageBox.No)
468 | if reply == QtWidgets.QMessageBox.Yes:
469 | self.tray.hide()
470 | self.destroy()
471 | qApp.exit(101)
472 | else:
473 | pass
474 | else:
475 | try:
476 | self.listWidget_reply.clear()
477 | except Exception as e:
478 | print(e)
479 | pass
480 | if msm["reply_url"]:
481 | self.reply_url = msm["reply_url"]
482 | self.label_rtot.setText(f"共有 {len(self.reply_url)} 条评论(如果评论数大于100,则只显示最新的100条记录)")
483 | # self.label_rtot.setText(f"共有 {len(self.reply_url)} 条弹幕(如果评论数大于100,则只显示最新的100条记录)") if len(self.reply_url) > 500 else self.label_rtot.setText(f"共有 {len(self.reply_url)} 条评论")
484 | for i in msm["widgets"]:
485 | item = QListWidgetItem() # 创建QListWidgetItem对象
486 | QApplication.processEvents()
487 | widget = self.get_item_wight_reply(i) # 调用上面的函数获取对应
488 | item.setSizeHint(QSize(widget.width(), widget.height())) # 设置QListWidgetItem大小与widget相同
489 | QApplication.processEvents()
490 | self.listWidget_reply.addItem(item) # 添加item
491 | self.listWidget_reply.setItemWidget(item, widget)
492 | else:
493 | self.label_rtot.setText(f"暂时没有评论")
494 | self.pushButton_rrenew.setText("")
495 |
496 | def danmaku_thread(self):
497 | try:
498 | self.pushButton_drenew.setText(f"获取中...")
499 | self.danmaku_Thread = Danmaku_Thread(self.cookies)
500 | self.danmaku_Thread.display_signal.connect(self.Danmaku_UI)
501 | self.danmaku_Thread.start()
502 | except:
503 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
504 |
505 | def Danmaku_UI(self, msm):
506 | if msm.get("error", 0) == 1:
507 | reply = QtWidgets.QMessageBox.question(self,
508 | '评论线程出错',
509 | "已经停止使用评论功能(不影响主程序),是否重启软件尝试恢复",
510 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
511 | QtWidgets.QMessageBox.No)
512 | if reply == QtWidgets.QMessageBox.Yes:
513 | self.tray.hide()
514 | self.destroy()
515 | qApp.exit(101)
516 | else:
517 | pass
518 | else:
519 | try:
520 | self.listWidget_danmaku.clear()
521 | except Exception as e:
522 | print(e)
523 | pass
524 | if msm["danmaku_url"]:
525 | self.danmaku_url = msm["danmaku_url"]
526 | self.label_dtot.setText(f"共有 {len(self.danmaku_url)} 条弹幕(如果弹幕数大于500,则只显示最新的500条记录)")
527 | # self.label_dtot.setText(f"共有 {len(self.danmaku_url)} 条弹幕(如果弹幕数大于500,则只显示最新的500条记录)") if len(self.danmaku_url) > 500 else self.label_dtot.setText(f"共有 {len(self.danmaku_url)} 条弹幕")
528 | for i in msm["widgets"]:
529 | item = QListWidgetItem() # 创建QListWidgetItem对象
530 | QApplication.processEvents()
531 | widget = self.get_item_wight_danmaku(i) # 调用上面的函数获取对应
532 | item.setSizeHint(QSize(widget.width(), widget.height())) # 设置QListWidgetItem大小与widget相同
533 | QApplication.processEvents()
534 | self.listWidget_danmaku.addItem(item) # 添加item
535 | self.listWidget_danmaku.setItemWidget(item, widget)
536 | else:
537 | self.label_dtot.setText(f"暂时没有评论")
538 | self.pushButton_drenew.setText("")
539 |
540 | def update_thread(self, auto=True):
541 | try:
542 | self.update_Thread = Update_Thread(auto)
543 | self.update_Thread.display_signal.connect(self.Update_UI)
544 | self.update_Thread.start()
545 | except:
546 | QMessageBox.information(self, '小助手提示', '程序运行异常,请确定网络连接是否正常,然后尝试重启客户端,如问题还未解决,请点击反馈按钮留言')
547 |
548 | def Update_UI(self, msm):
549 | if msm.get("net", 1) == 0:
550 | if msm["Version"] == False or msm.get("Version", None) is None:
551 | QMessageBox.information(self, '小助手提示', '连接更新服务器失败')
552 | else:
553 | pass
554 | else:
555 | if msm['Version'] == self.version:
556 | if msm["auto"] == False:
557 | QMessageBox.information(self, '小助手提示', '已经是最新版本')
558 | else:
559 | pass
560 | else:
561 | if msm.get("hot_update", 0) == 0:
562 | reply = QtWidgets.QMessageBox.question(self,
563 | '发现新版本,是否立即更新',
564 | f'发现新版本:V{msm["Version"]},更新内容如下:\n\n{msm["Update_des"]}\n\n是否立即更新?',
565 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
566 | QtWidgets.QMessageBox.No)
567 | if reply == QtWidgets.QMessageBox.Yes:
568 | self.open_browser(msm["Update_url"])
569 | else:
570 | pass
571 | else:
572 | if msm.get("finish", False):
573 | QMessageBox.information(self, '软件升级完成',
574 | f'新版本:V{msm["Version"]},更新内容如下:\n\n{msm["Update_des"]}\n\n已经为您更新完成,下次重启软件后生效')
575 | else:
576 | QMessageBox.information(self, '软件升级失败', f'新版本:V{msm["Version"]},更新内容如下:\n\n{msm["Update_des"]}\n\n请尝试重启软件或留言反馈')
577 |
578 |
579 | # 视频稿件部分
580 | def get_item_wight(self, msms):
581 | # 读取属性
582 | face = msms["face"]
583 | tag = str(msms["tag"])
584 | title = str(msms["title"])
585 | btn_view = str(msms["view"])
586 | btn_reply = str(msms["reply"])
587 | btn_danmaku = msms.get("danmaku", -1) # str(msms["danmaku"])
588 | btn_coin = str(msms["coin"])
589 | btn_favorite = str(msms["favorite"])
590 | btn_like = str(msms["like"])
591 | btn_share = str(msms["share"])
592 | create_time = str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msms["create_time"])))
593 | state_panel = msms.get("state_panel", 0)
594 | wight = QWidget()
595 |
596 | wight.setObjectName("widget_main")
597 | wight.setStyleSheet(
598 | "QWidget#widget_main{background:Transparent;border:0px solid grey;}QWidget#widget_main:hover{background-color:rgba(240,245,255,0.8);}")
599 | wight.setMinimumSize(QtCore.QSize(0, 100))
600 | wight.setMaximumSize(QtCore.QSize(16777215, 100))
601 | layout_main = QHBoxLayout()
602 | layout_main.setContentsMargins(11, 0, 11, 0)
603 | layout_main.setSpacing(6)
604 | label_face = QLabel()
605 | label_face.setFixedSize(120, 76)
606 | try:
607 | img = QImage.fromData(face)
608 | label_face.setPixmap(QPixmap.fromImage(img))
609 | except:
610 | label_face.setPixmap(QPixmap(face))
611 | label_face.setScaledContents(True)
612 | layout_right = QVBoxLayout()
613 | layout_right_down = QHBoxLayout() # 右下的横向布局
614 | pushButton_view = QtWidgets.QPushButton()
615 | pushButton_view.setMinimumSize(QtCore.QSize(50, 30))
616 | pushButton_view.setMaximumSize(QtCore.QSize(80, 30))
617 | pushButton_view.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
618 | pushButton_view.setIcon(qtawesome.icon('fa.play-circle', color='#99A2AA'))
619 | pushButton_view.setText(btn_view)
620 | pushButton_reply = QtWidgets.QPushButton()
621 | pushButton_reply.setMinimumSize(QtCore.QSize(50, 30))
622 | pushButton_reply.setMaximumSize(QtCore.QSize(80, 30))
623 | pushButton_reply.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
624 | pushButton_reply.setIcon(qtawesome.icon('fa.comment', color="#99A2AA"))
625 | pushButton_reply.setText(btn_reply)
626 | pushButton_coin = QtWidgets.QPushButton()
627 | pushButton_coin.setMinimumSize(QtCore.QSize(50, 30))
628 | pushButton_coin.setMaximumSize(QtCore.QSize(80, 30))
629 | pushButton_coin.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
630 | pushButton_coin.setIcon(qtawesome.icon('fa.btc', color='#99A2AA'))
631 | pushButton_coin.setText(btn_coin)
632 | pushButton_favorite = QtWidgets.QPushButton()
633 | pushButton_favorite.setMinimumSize(QtCore.QSize(50, 30))
634 | pushButton_favorite.setMaximumSize(QtCore.QSize(80, 30))
635 | pushButton_favorite.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
636 | pushButton_favorite.setIcon(qtawesome.icon('fa.star', color='#99A2AA'))
637 | pushButton_favorite.setText(btn_favorite)
638 | pushButton_like = QtWidgets.QPushButton()
639 | pushButton_like.setMinimumSize(QtCore.QSize(50, 30))
640 | pushButton_like.setMaximumSize(QtCore.QSize(80, 30))
641 | pushButton_like.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
642 | pushButton_like.setIcon(qtawesome.icon('fa.thumbs-up', color='#99A2AA'))
643 | pushButton_like.setText(btn_like)
644 | pushButton_share = QtWidgets.QPushButton()
645 | pushButton_share.setMinimumSize(QtCore.QSize(50, 30))
646 | pushButton_share.setMaximumSize(QtCore.QSize(80, 30))
647 | pushButton_share.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
648 | pushButton_share.setIcon(qtawesome.icon('fa.share', color='#99A2AA'))
649 | pushButton_share.setText(btn_share)
650 | layout_right_down.addWidget(pushButton_view)
651 | if btn_danmaku != -1:
652 | pushButton_danmaku = QtWidgets.QPushButton()
653 | pushButton_danmaku.setMinimumSize(QtCore.QSize(50, 30))
654 | pushButton_danmaku.setMaximumSize(QtCore.QSize(80, 30))
655 | pushButton_danmaku.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
656 | pushButton_danmaku.setIcon(qtawesome.icon('fa.list-alt', color='#99A2AA'))
657 | pushButton_danmaku.setText(str(btn_danmaku))
658 | layout_right_down.addWidget(pushButton_danmaku)
659 | layout_right_down.addWidget(pushButton_reply)
660 | layout_right_down.addWidget(pushButton_coin)
661 | layout_right_down.addWidget(pushButton_favorite)
662 | layout_right_down.addWidget(pushButton_like)
663 | layout_right_down.addWidget(pushButton_share)
664 | layout_right_down.addWidget(QLabel(create_time))
665 | if state_panel == 1:
666 | label_state_panel = QtWidgets.QLabel()
667 | label_state_panel.setStyleSheet("QLabel{background:Transparent;border:0px solid grey;color:#5168D7}")
668 | label_state_panel.setMinimumSize(QtCore.QSize(30, 30))
669 | label_state_panel.setMaximumSize(QtCore.QSize(50, 30))
670 | # label_state_panel.setMaximumHeight(20)
671 | font = QtGui.QFont()
672 | font.setFamily("微软雅黑")
673 | font.setPointSize(7)
674 | label_state_panel.setFont(font)
675 | label_state_panel.setText("审稿中")
676 | layout_right_down.addWidget(label_state_panel)
677 | elif state_panel != 0:
678 | label_state_panel = QtWidgets.QLabel()
679 | label_state_panel.setStyleSheet("QLabel{background:Transparent;border:0px solid grey;color:red}")
680 | label_state_panel.setMinimumSize(QtCore.QSize(30, 30))
681 | label_state_panel.setMaximumSize(QtCore.QSize(50, 30))
682 | # label_state_panel.setMaximumHeight(20)
683 | font = QtGui.QFont()
684 | font.setFamily("微软雅黑")
685 | font.setPointSize(9)
686 | label_state_panel.setFont(font)
687 | label_state_panel.setText("已锁定")
688 | layout_right_down.addWidget(label_state_panel)
689 | layout_right_up = QHBoxLayout() # 右下的横向布局
690 | label_tag = QtWidgets.QLabel()
691 | label_tag.setAlignment(QtCore.Qt.AlignCenter)
692 | label_tag.setStyleSheet("QLabel{background:Transparent;border:1px solid grey;border-radius:5px;}")
693 | label_tag.setMaximumHeight(20)
694 | font = QtGui.QFont()
695 | font.setFamily("微软雅黑")
696 | font.setPointSize(7)
697 | label_tag.setFont(font)
698 | label_tag.setText(tag)
699 | layout_right_up.addWidget(label_tag)
700 | label_title = QtWidgets.QLabel()
701 | font = QtGui.QFont()
702 | font.setFamily("微软雅黑")
703 | font.setPointSize(10)
704 | font.setBold(True)
705 | font.setWeight(50)
706 | label_title.setFont(font)
707 | label_title.setText(title)
708 | layout_right_up.addWidget(label_title)
709 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
710 | layout_right_up.addItem(spacerItem)
711 | layout_main.addWidget(label_face) # 最左边的头像
712 | layout_right.addLayout(layout_right_up) # 右边的纵向布局
713 | layout_right.addLayout(layout_right_down) # 右下角横向布局
714 | layout_main.addLayout(layout_right) # 右边的布局
715 | wight.setLayout(layout_main) # 布局给wight
716 | return wight # 返回wight
717 |
718 | def get_item_wight_reply(self, msms):
719 | title = msms["title"]
720 | id = msms['id']
721 | like = msms["like"]
722 | face = msms["face"]
723 | floor = msms["floor"]
724 | replier = msms['replier']
725 | message = msms['message']
726 | ctime = msms['ctime']
727 | # ctime = str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msms["ctime"])))
728 | parent = msms['parent']
729 |
730 | wight = QWidget()
731 | wight.setObjectName("widget_main")
732 | wight.setStyleSheet(
733 | "QWidget#widget_main{background:Transparent;border:0px solid grey;}QWidget#widget_main:hover{background-color:rgba(240,245,255,0.8);}")
734 | layout_main = QHBoxLayout()
735 | layout_main.setContentsMargins(11, 0, 11, 0)
736 | layout_main.setSpacing(6)
737 | label_face = QLabel()
738 | label_face.setFixedSize(120, 76)
739 | try:
740 | img = QImage.fromData(face)
741 | label_face.setPixmap(QPixmap.fromImage(img))
742 | except:
743 | label_face.setPixmap(QPixmap(face))
744 | label_face.setScaledContents(True)
745 |
746 | layout_right = QVBoxLayout()
747 |
748 | layout_right_down = QHBoxLayout() # 右下的横向布局
749 | pushButton_like = QtWidgets.QPushButton()
750 | pushButton_like.setMinimumSize(QtCore.QSize(50, 30))
751 | pushButton_like.setMaximumSize(QtCore.QSize(80, 30))
752 | pushButton_like.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}")
753 | pushButton_like.setIcon(qtawesome.icon('fa.thumbs-up', color='#99A2AA'))
754 | pushButton_like.setText(f"{like}")
755 | font = QtGui.QFont()
756 | font.setFamily("微软雅黑")
757 | font.setPointSize(9)
758 | label_time = QLabel(f"{ctime}")
759 | label_time.setFont(font)
760 | layout_right_down.addWidget(label_time)
761 | layout_right_down.addWidget(pushButton_like)
762 |
763 | layout_right_middle = QVBoxLayout() # 右下的横向布局
764 | if parent == 1:
765 | font = QtGui.QFont()
766 | font.setFamily("微软雅黑")
767 | font.setPointSize(9)
768 | label_reply = QLabel(f"{message}")
769 | label_reply.setFont(font)
770 | label_reply.setStyleSheet("QLabel{color:Gray}")
771 | layout_right_middle.addWidget(label_reply)
772 | label_parent = QLabel(f"{msms['parent_name']}的评论: {msms['parent_message']}")
773 | label_parent.setStyleSheet("QLabel{color:DarkGray}")
774 | font = QtGui.QFont()
775 | font.setFamily("微软雅黑")
776 | font.setPointSize(8)
777 | label_parent.setFont(font)
778 | layout_right_middle.addWidget(label_parent)
779 | count = len(msms['parent_message'].split('\n')) + len(msms['message'].split('\n')) + 2
780 | else:
781 | count = len(msms['message'].split('\n')) + 2
782 | font = QtGui.QFont()
783 | font.setFamily("微软雅黑")
784 | font.setPointSize(9)
785 | label_reply = QLabel(f"{message}")
786 | label_reply.setFont(font)
787 | label_reply.setStyleSheet("QLabel{color:Gray}")
788 | layout_right_middle.addWidget(label_reply)
789 | # layout_right_middle.addWidget(QLabel(f"{message}"))
790 | wight.setMinimumSize(QtCore.QSize(0, 10))
791 | wight.setMaximumSize(QtCore.QSize(16777215, count * 30))
792 |
793 | layout_right_up = QHBoxLayout() # 右上的横向布局
794 | label_title = QtWidgets.QLabel()
795 | font = QtGui.QFont()
796 | font.setFamily("微软雅黑")
797 | font.setPointSize(9)
798 | font.setBold(True)
799 | font.setWeight(75)
800 | label_title.setFont(font)
801 | if parent == 0:
802 | label_title.setText(f"{replier} 在 #{floor} 的评论")
803 | else:
804 | label_title.setText(f"{replier} 回复 {msms['parent_name']} 在 #{floor} 的评论")
805 | layout_right_up.addWidget(label_title)
806 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
807 | layout_right_up.addItem(spacerItem)
808 | layout_right.addLayout(layout_right_up) # 右边的纵向布局
809 | layout_right.addLayout(layout_right_middle)
810 | layout_right.addLayout(layout_right_down) # 右下角横向布局
811 | layout_main.addWidget(label_face)
812 | layout_main.addLayout(layout_right) # 右边的布局
813 | wight.setLayout(layout_main) # 布局给wight
814 | return wight # 返回wight
815 |
816 | def get_item_wight_danmaku(self, msms):
817 | title = msms["title"]
818 | id = msms['id']
819 | uname = msms['uname']
820 | message = msms['message']
821 | ctime = str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msms["ctime"])))
822 |
823 | wight = QWidget()
824 | wight.setObjectName("widget_main")
825 | wight.setStyleSheet(
826 | "QWidget#widget_main{background:Transparent;border:0px solid grey;}QWidget#widget_main:hover{background-color:rgba(240,245,255,0.8);}")
827 | wight.setMinimumSize(QtCore.QSize(0, 10))
828 | wight.setMaximumSize(QtCore.QSize(16777215, 100))
829 | layout_main = QHBoxLayout()
830 | layout_main.setContentsMargins(11, 0, 11, 0)
831 | layout_main.setSpacing(6)
832 | layout_right = QVBoxLayout()
833 | layout_right_up = QHBoxLayout() # 右下的横向布局
834 | font = QtGui.QFont()
835 | font.setFamily("微软雅黑")
836 | font.setPointSize(7)
837 | label_title = QtWidgets.QLabel()
838 | font = QtGui.QFont()
839 | font.setFamily("微软雅黑")
840 | font.setPointSize(10)
841 | font.setBold(True)
842 | font.setWeight(50)
843 | label_title.setFont(font)
844 | label_title.setText(f"{uname}:{message}")
845 | layout_right_middle = QVBoxLayout() # 右下的横向布局
846 | font = QtGui.QFont()
847 | font.setFamily("微软雅黑")
848 | font.setPointSize(9)
849 | label_reply = QLabel(f"{ctime} 来自于:{title}")
850 | label_reply.setFont(font)
851 | label_reply.setStyleSheet("QLabel{color:Gray}")
852 | layout_right_middle.addWidget(label_reply)
853 | layout_right_up.addWidget(label_title)
854 | layout_right.addLayout(layout_right_up) # 右边的纵向布局
855 | layout_right.addLayout(layout_right_middle) # 右下角横向布局
856 | layout_main.addLayout(layout_right) # 右边的布局
857 | wight.setLayout(layout_main) # 布局给wight
858 | return wight # 返回wight
859 |
860 | def vitem_clicked(self, item):
861 | self.open_browser(self.video_url[self.listWidget.currentIndex().row()])
862 |
863 | def aitem_clicked(self, item):
864 | self.open_browser(self.article_url[self.listWidget_article.currentIndex().row()])
865 |
866 | def ritem_clicked(self, item):
867 | self.open_browser(self.reply_url[self.listWidget_reply.currentIndex().row()])
868 |
869 | def ditem_clicked(self, item):
870 | self.open_browser(self.danmaku_url[self.listWidget_danmaku.currentIndex().row()])
871 |
872 | def mousePressEvent(self, event):
873 | if event.button() == Qt.LeftButton:
874 | self.m_flag = True
875 | self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
876 | event.accept()
877 | self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
878 |
879 | def mouseMoveEvent(self, QMouseEvent):
880 | if Qt.LeftButton and self.m_flag:
881 | self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
882 | QMouseEvent.accept()
883 |
884 | def mouseReleaseEvent(self, QMouseEvent):
885 | self.m_flag = False
886 | self.setCursor(QCursor(Qt.ArrowCursor))
887 |
888 | def closeEvent(self, event):
889 | reply = QtWidgets.QMessageBox.question(self,
890 | '哔哩哔哩UP主助手',
891 | "是否要退出程序?",
892 | QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
893 | QtWidgets.QMessageBox.No)
894 | if reply == QtWidgets.QMessageBox.Yes:
895 | self.tray.hide()
896 | qApp.quit()
897 | else:
898 | event.ignore()
899 |
900 | def keyPressEvent(self, e):
901 | if e.key() == Qt.Key_Escape: # 重写Esc键事件
902 | self.close()
903 |
904 |
905 | class Main_Thread(QThread):
906 | display_signal = pyqtSignal(dict)
907 |
908 | def __init__(self, cookies):
909 | super().__init__()
910 | self.cookies = cookies
911 |
912 | def run(self):
913 | app = api.BD()
914 | login_info = {}
915 | try:
916 | if app.login(**self.cookies):
917 | while True:
918 | for _ in range(5):
919 | if app.get_main_info():
920 | self.display_signal.emit(app.main_info)
921 | break
922 | time.sleep(120)
923 | else:
924 | self.display_signal.emit({"error": 1})
925 | except:
926 | self.display_signal.emit({"error": 1})
927 |
928 |
929 | class Notify_Thread(QThread):
930 | display_signal = pyqtSignal(dict)
931 |
932 | def __init__(self, cookies):
933 | super().__init__()
934 | self.cookies = cookies
935 |
936 | def run(self):
937 | app = api.BD()
938 | login_info = {}
939 | try:
940 | if app.login(**self.cookies):
941 | while True:
942 | for _ in range(5):
943 | if app.get_notify():
944 | self.display_signal.emit(app.notify)
945 | break
946 | time.sleep(30)
947 | else:
948 | self.display_signal.emit({"error": 1})
949 | except:
950 | self.display_signal.emit({"error": 1})
951 |
952 |
953 | class Video_Thread(QThread):
954 | display_signal = pyqtSignal(dict)
955 |
956 | def __init__(self, cookies):
957 | super().__init__()
958 | self.cookies = cookies
959 |
960 | def run(self):
961 | app = api.BD()
962 | login_info = {}
963 | try:
964 | if app.login(**self.cookies):
965 | for _ in range(5):
966 | if app.get_video():
967 | msm = app.videos
968 | var = ["url", "face", "tag", "title", "view", "danmaku", "reply", "coin", "favorite", "like",
969 | "share", "create_time", "state_panel"]
970 | video_url = msm["url"]
971 | widgets = []
972 | for i in range(len(video_url)):
973 | msms = {}
974 | for j in var:
975 | if j == "face":
976 | msms[j] = pic_cache(msm[j][i])
977 | # msms[j] = requests.get(msm[j][i]).content
978 | else:
979 | msms[j] = msm[j][i]
980 | widgets.append(msms)
981 | self.display_signal.emit({"error": 0, "video_url": video_url, "widgets": widgets})
982 | break
983 | else:
984 | self.display_signal.emit({"error": 1})
985 | except Exception as e:
986 | print(e)
987 | self.display_signal.emit({"error": 1})
988 |
989 |
990 | class Article_Thread(QThread):
991 | display_signal = pyqtSignal(dict)
992 |
993 | def __init__(self, cookies):
994 | super().__init__()
995 | self.cookies = cookies
996 |
997 | def run(self):
998 | app = api.BD()
999 | login_info = {}
1000 | try:
1001 | if app.login(**self.cookies):
1002 | for _ in range(5):
1003 | if app.get_article():
1004 | msm = app.article
1005 | var = ["url", "face", "tag", "title", "view", "reply", "coin", "favorite", "like",
1006 | "share", "create_time"]
1007 | article_url = msm["url"]
1008 | widgets = []
1009 | for i in range(len(article_url)):
1010 | msms = {}
1011 | for j in var:
1012 | if j == "face":
1013 | msms[j] = pic_cache(msm[j][i])
1014 | # msms[j] = requests.get(msm[j][i]).content
1015 | else:
1016 | msms[j] = msm[j][i]
1017 | widgets.append(msms)
1018 | self.display_signal.emit({"error": 0, "article_url": article_url, "widgets": widgets})
1019 | break
1020 | else:
1021 | self.display_signal.emit({"error": 1})
1022 | except Exception as e:
1023 | print(e)
1024 | self.display_signal.emit({"error": 1})
1025 |
1026 |
1027 | class Reply_Thread(QThread):
1028 | display_signal = pyqtSignal(dict)
1029 |
1030 | def __init__(self, cookies):
1031 | super().__init__()
1032 | self.cookies = cookies
1033 |
1034 | def run(self):
1035 | app = api.BD()
1036 | login_info = {}
1037 | try:
1038 | if app.login(**self.cookies):
1039 | for _ in range(5):
1040 | if app.get_reply():
1041 | msm = app.reply
1042 | # print(msm)
1043 | var = ["title", "id", "floor", "face", "replier", "message", "ctime", "parent", "parent_name",
1044 | "parent_message", "like"]
1045 | reply_url = msm["url"]
1046 | widgets = []
1047 | for i in range(len(reply_url)):
1048 | msms = {}
1049 | for j in var:
1050 | if j == "face":
1051 | msms[j] = pic_cache(msm[j][i])
1052 | else:
1053 | msms[j] = msm[j][i]
1054 | widgets.append(msms)
1055 | self.display_signal.emit({"error": 0, "reply_url": reply_url, "widgets": widgets})
1056 | break
1057 | else:
1058 | self.display_signal.emit({"error": 1})
1059 | except Exception as e:
1060 | print(e)
1061 | self.display_signal.emit({"error": 1})
1062 |
1063 |
1064 | class Danmaku_Thread(QThread):
1065 | display_signal = pyqtSignal(dict)
1066 |
1067 | def __init__(self, cookies):
1068 | super().__init__()
1069 | self.cookies = cookies
1070 |
1071 | def run(self):
1072 | app = api.BD()
1073 | login_info = {}
1074 | try:
1075 | if app.login(**self.cookies):
1076 | for _ in range(5):
1077 | if app.get_danmaku():
1078 | msm = app.danmaku
1079 | # print(msm)
1080 | var = ["title", "id", "message", "ctime", "uname"]
1081 | reply_url = msm["url"]
1082 | widgets = []
1083 | for i in range(len(reply_url)):
1084 | msms = {}
1085 | for j in var:
1086 | msms[j] = msm[j][i]
1087 | widgets.append(msms)
1088 | self.display_signal.emit({"error": 0, "danmaku_url": reply_url, "widgets": widgets})
1089 | break
1090 | else:
1091 | self.display_signal.emit({"error": 1})
1092 | except Exception as e:
1093 | print(e)
1094 | self.display_signal.emit({"error": 1})
1095 |
1096 |
1097 | class Update_Thread(QThread):
1098 | display_signal = pyqtSignal(dict)
1099 |
1100 | def __init__(self, auto):
1101 | super().__init__()
1102 | self.auto = auto
1103 |
1104 | def run(self):
1105 | try:
1106 | # raise FileExistsError
1107 | result = json.loads(requests.get(soft_cfg.update_url, timeout=3).text)
1108 | except:
1109 | result = soft_cfg.result_test
1110 | if self.auto:
1111 | result["auto"] = True
1112 | else:
1113 | result["auto"] = False
1114 | if result.get("hot_update", 0) == 1:
1115 | try:
1116 | patch = requests.get(result.get("Update_url")).content
1117 | with open(f"{soft_cfg.soft_name}", "wb") as f:
1118 | f.write(patch)
1119 | result["finish"] = True
1120 | except Exception as e:
1121 | print(f"update: {e}")
1122 | with open("error.txt", "w") as f:
1123 | f.write(f"update: {e}")
1124 | result["finish"] = False
1125 |
1126 | self.display_signal.emit(result)
1127 |
--------------------------------------------------------------------------------
/images/22332.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MR5356/bilibili-up-helper/708796dc46f2c2020d1965107195f2e5c2ea82bf/images/22332.png
--------------------------------------------------------------------------------
/images/demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MR5356/bilibili-up-helper/708796dc46f2c2020d1965107195f2e5c2ea82bf/images/demo1.png
--------------------------------------------------------------------------------
/images/demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MR5356/bilibili-up-helper/708796dc46f2c2020d1965107195f2e5c2ea82bf/images/demo2.png
--------------------------------------------------------------------------------
/images/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MR5356/bilibili-up-helper/708796dc46f2c2020d1965107195f2e5c2ea82bf/images/logo.ico
--------------------------------------------------------------------------------
/login.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'login.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.13.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 |
10 | from PyQt5 import QtCore, QtGui, QtWidgets
11 |
12 |
13 | class Ui_Dialog(object):
14 | def setupUi(self, Dialog):
15 | Dialog.setObjectName("Dialog")
16 | Dialog.resize(400, 300)
17 | self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
18 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
19 | self.verticalLayout.setSpacing(0)
20 | self.verticalLayout.setObjectName("verticalLayout")
21 | self.widget = QtWidgets.QWidget(Dialog)
22 | self.widget.setObjectName("widget")
23 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget)
24 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
25 | self.verticalLayout_2.setSpacing(0)
26 | self.verticalLayout_2.setObjectName("verticalLayout_2")
27 | self.widget_top = QtWidgets.QWidget(self.widget)
28 | self.widget_top.setStyleSheet("QWidget#widget_top{border-image:url(:/images/22332.png);border-top-left-radius:2px;border-top-right-radius:2px;}")
29 | self.widget_top.setObjectName("widget_top")
30 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget_top)
31 | self.verticalLayout_3.setContentsMargins(5, 0, 5, 0)
32 | self.verticalLayout_3.setObjectName("verticalLayout_3")
33 | self.widget_2 = QtWidgets.QWidget(self.widget_top)
34 | self.widget_2.setMinimumSize(QtCore.QSize(0, 30))
35 | self.widget_2.setMaximumSize(QtCore.QSize(16777215, 30))
36 | self.widget_2.setObjectName("widget_2")
37 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_2)
38 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
39 | self.horizontalLayout.setObjectName("horizontalLayout")
40 | self.label = QtWidgets.QLabel(self.widget_2)
41 | self.label.setMinimumSize(QtCore.QSize(0, 30))
42 | self.label.setMaximumSize(QtCore.QSize(16777215, 30))
43 | font = QtGui.QFont()
44 | font.setBold(True)
45 | font.setWeight(75)
46 | self.label.setFont(font)
47 | self.label.setStyleSheet("QLabel{color:white}")
48 | self.label.setObjectName("label")
49 | self.horizontalLayout.addWidget(self.label)
50 | spacerItem = QtWidgets.QSpacerItem(181, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
51 | self.horizontalLayout.addItem(spacerItem)
52 | self.pushButton_close = QtWidgets.QPushButton(self.widget_2)
53 | self.pushButton_close.setMinimumSize(QtCore.QSize(30, 30))
54 | self.pushButton_close.setMaximumSize(QtCore.QSize(30, 30))
55 | self.pushButton_close.setStyleSheet("QPushButton{background:Transparent;text-align: left;color:white;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,255,255, 0.8);}")
56 | self.pushButton_close.setText("")
57 | self.pushButton_close.setObjectName("pushButton_close")
58 | self.horizontalLayout.addWidget(self.pushButton_close)
59 | self.verticalLayout_3.addWidget(self.widget_2)
60 | spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
61 | self.verticalLayout_3.addItem(spacerItem1)
62 | self.verticalLayout_2.addWidget(self.widget_top)
63 | self.widget_down = QtWidgets.QWidget(self.widget)
64 | self.widget_down.setStyleSheet("QWidget#widget_down{background:#F0F5FF;border-bottom-left-radius:2px;border-bottom-right-radius:2px}")
65 | self.widget_down.setObjectName("widget_down")
66 | self.gridLayout = QtWidgets.QGridLayout(self.widget_down)
67 | self.gridLayout.setContentsMargins(80, 20, 80, 20)
68 | self.gridLayout.setObjectName("gridLayout")
69 | self.label_2 = QtWidgets.QLabel(self.widget_down)
70 | self.label_2.setObjectName("label_2")
71 | self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
72 | self.lineEdit_user = QtWidgets.QLineEdit(self.widget_down)
73 | self.lineEdit_user.setStyleSheet("QLineEdit{background:Transparent;border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid gray;}\n"
74 | " QLineEdit:hover{border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid rgb(70,200,50);}")
75 | self.lineEdit_user.setObjectName("lineEdit_user")
76 | self.gridLayout.addWidget(self.lineEdit_user, 0, 1, 1, 1)
77 | self.label_3 = QtWidgets.QLabel(self.widget_down)
78 | self.label_3.setObjectName("label_3")
79 | self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
80 | self.lineEdit_passwd = QtWidgets.QLineEdit(self.widget_down)
81 | self.lineEdit_passwd.setStyleSheet("QLineEdit{background:Transparent;border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid gray;}\n"
82 | " QLineEdit:hover{border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid rgb(70,200,50);}")
83 | self.lineEdit_passwd.setEchoMode(QtWidgets.QLineEdit.Password)
84 | self.lineEdit_passwd.setObjectName("lineEdit_passwd")
85 | self.gridLayout.addWidget(self.lineEdit_passwd, 1, 1, 1, 1)
86 | self.pushButton_login = QtWidgets.QPushButton(self.widget_down)
87 | self.pushButton_login.setStyleSheet("QPushButton{background-color:#4D5E92;color:white;}\n"
88 | "QPushButton:hover{background-color:rgba(84,129,189, 0.8);}")
89 | self.pushButton_login.setObjectName("pushButton_login")
90 | self.gridLayout.addWidget(self.pushButton_login, 2, 0, 1, 2)
91 | self.verticalLayout_2.addWidget(self.widget_down)
92 | self.verticalLayout_2.setStretch(0, 1)
93 | self.verticalLayout_2.setStretch(1, 1)
94 | self.verticalLayout.addWidget(self.widget)
95 |
96 | self.retranslateUi(Dialog)
97 | QtCore.QMetaObject.connectSlotsByName(Dialog)
98 |
99 | def retranslateUi(self, Dialog):
100 | _translate = QtCore.QCoreApplication.translate
101 | Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
102 | self.label.setText(_translate("Dialog", "哔哩哔哩UP主助手登录"))
103 | self.pushButton_close.setToolTip(_translate("Dialog", "关闭
"))
104 | self.label_2.setText(_translate("Dialog", "账号:"))
105 | self.lineEdit_user.setPlaceholderText(_translate("Dialog", "请输入密码"))
106 | self.label_3.setText(_translate("Dialog", "密码:"))
107 | self.lineEdit_passwd.setPlaceholderText(_translate("Dialog", "请输入密码"))
108 | self.pushButton_login.setText(_translate("Dialog", "登录"))
109 | import resources_rc
110 |
--------------------------------------------------------------------------------
/login.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Dialog
15 |
16 |
17 |
18 | 0
19 |
20 |
21 | 0
22 |
23 |
24 | 0
25 |
26 |
27 | 0
28 |
29 |
30 | 0
31 |
32 | -
33 |
34 |
35 |
36 | 0
37 |
38 |
39 | 0
40 |
41 |
42 | 0
43 |
44 |
45 | 0
46 |
47 |
48 | 0
49 |
50 |
-
51 |
52 |
53 | QWidget#widget_top{border-image:url(:/images/22332.png);border-top-left-radius:2px;border-top-right-radius:2px;}
54 |
55 |
56 |
57 | 5
58 |
59 |
60 | 0
61 |
62 |
63 | 5
64 |
65 |
66 | 0
67 |
68 |
-
69 |
70 |
71 |
72 | 0
73 | 30
74 |
75 |
76 |
77 |
78 | 16777215
79 | 30
80 |
81 |
82 |
83 |
84 | 0
85 |
86 |
87 | 0
88 |
89 |
90 | 0
91 |
92 |
93 | 0
94 |
95 |
-
96 |
97 |
98 |
99 | 0
100 | 30
101 |
102 |
103 |
104 |
105 | 16777215
106 | 30
107 |
108 |
109 |
110 |
111 | 75
112 | true
113 |
114 |
115 |
116 | QLabel{color:white}
117 |
118 |
119 | 哔哩哔哩UP主助手登录
120 |
121 |
122 |
123 | -
124 |
125 |
126 | Qt::Horizontal
127 |
128 |
129 |
130 | 181
131 | 20
132 |
133 |
134 |
135 |
136 | -
137 |
138 |
139 |
140 | 30
141 | 30
142 |
143 |
144 |
145 |
146 | 30
147 | 30
148 |
149 |
150 |
151 | <html><head/><body><p>关闭</p></body></html>
152 |
153 |
154 | QPushButton{background:Transparent;text-align: left;color:white;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,255,255, 0.8);}
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | -
165 |
166 |
167 | Qt::Vertical
168 |
169 |
170 |
171 | 20
172 | 40
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | -
181 |
182 |
183 | QWidget#widget_down{background:#F0F5FF;border-bottom-left-radius:2px;border-bottom-right-radius:2px}
184 |
185 |
186 |
187 | 80
188 |
189 |
190 | 20
191 |
192 |
193 | 80
194 |
195 |
196 | 20
197 |
198 |
-
199 |
200 |
201 | 账号:
202 |
203 |
204 |
205 | -
206 |
207 |
208 | QLineEdit{background:Transparent;border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid gray;}
209 | QLineEdit:hover{border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid rgb(70,200,50);}
210 |
211 |
212 | 请输入密码
213 |
214 |
215 |
216 | -
217 |
218 |
219 | 密码:
220 |
221 |
222 |
223 | -
224 |
225 |
226 | QLineEdit{background:Transparent;border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid gray;}
227 | QLineEdit:hover{border-width:1px;border-radius:0px;font-size:12px;color:black;border-bottom:1px solid rgb(70,200,50);}
228 |
229 |
230 | QLineEdit::Password
231 |
232 |
233 | 请输入密码
234 |
235 |
236 |
237 | -
238 |
239 |
240 | QPushButton{background-color:#4D5E92;color:white;}
241 | QPushButton:hover{background-color:rgba(84,129,189, 0.8);}
242 |
243 |
244 | 登录
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
--------------------------------------------------------------------------------
/login_func.py:
--------------------------------------------------------------------------------
1 | import time
2 | import qtawesome
3 | from PyQt5.QtCore import QThread, pyqtSignal, Qt
4 | from PyQt5.QtGui import QCursor
5 | from PyQt5.QtWidgets import QMessageBox
6 | from login import Ui_Dialog
7 | from PyQt5 import QtWidgets, QtCore
8 | import function
9 | import api
10 | import json
11 |
12 |
13 | class login_UI(Ui_Dialog, QtWidgets.QDialog):
14 | def __init__(self):
15 | super(login_UI, self).__init__()
16 | self.setupUi(self)
17 | self.m_flag = False
18 | self.setFixedSize(self.width(), self.height())
19 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
20 | self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) # 窗口始终置顶
21 | self.pushButton_close.setIcon(qtawesome.icon('fa.close', color='blank'))
22 | self.pushButton_close.clicked.connect(self.close)
23 | self.pushButton_login.clicked.connect(self.login)
24 |
25 | def login(self):
26 | try:
27 | user = self.lineEdit_user.text()
28 | passwd = self.lineEdit_passwd.text()
29 | if user and passwd:
30 | self.pushButton_login.setText("登录中...")
31 | self.main_Thread = Main_Thread(user,passwd)
32 | self.main_Thread.display_signal.connect(self.change_UI)
33 | self.main_Thread.start()
34 | else:
35 | QMessageBox.information(self, '小助手提示', '账号或者密码不能为空')
36 | except:
37 | self.pushButton_login.setText("登录")
38 | QMessageBox.information(self, '小助手提示', '网络故障,请尝试重启客户端')
39 |
40 | def change_UI(self, msm):
41 | if msm.get("error", 0) != 1:
42 | ui = function.fun_main(msm)
43 | ui.show()
44 | time.sleep(1)
45 | self.close()
46 | else:
47 | self.pushButton_login.setText("登录")
48 | QMessageBox.information(self, '登陆失败', '账号或密码错误')
49 |
50 | def mousePressEvent(self, event):
51 | if event.button() == Qt.LeftButton:
52 | self.m_flag = True
53 | self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
54 | event.accept()
55 | self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
56 |
57 | def mouseMoveEvent(self, QMouseEvent):
58 | if Qt.LeftButton and self.m_flag:
59 | self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
60 | QMouseEvent.accept()
61 |
62 | def mouseReleaseEvent(self, QMouseEvent):
63 | self.m_flag = False
64 | self.setCursor(QCursor(Qt.ArrowCursor))
65 |
66 | def keyPressEvent(self, e):
67 | if e.key() == Qt.Key_Return: # 重写Esc键事件
68 | self.login()
69 | # self.close()
70 | elif e.key() == Qt.Key_Enter:
71 | self.login()
72 |
73 |
74 | class Main_Thread(QThread):
75 | display_signal = pyqtSignal(dict)
76 | def __init__(self, user, passwd):
77 | super().__init__()
78 | self.user = user
79 | self.passwd = passwd
80 |
81 | def run(self):
82 | app = api.BD()
83 | login_info = {}
84 | if app.login(username=self.user, password=self.passwd):
85 | cookies = app.get_cookies()
86 | for i in cookies:
87 | login_info[i] = cookies[i]
88 | login_info["access_token"] = app.access_token
89 | login_info["refresh_token"] = app.refresh_token
90 | login_info["username"] = self.user
91 | login_info["password"] = self.passwd
92 | with open("config.json", "w") as f:
93 | f.write(json.dumps(login_info))
94 | self.display_signal.emit(cookies)
95 | else:
96 | self.display_signal.emit({"error": 1})
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import login_func
3 | import function
4 | from PyQt5 import QtWidgets, QtGui, QtCore
5 | import json
6 | import api
7 |
8 | debug = 0
9 |
10 | def main():
11 | app = QtWidgets.QApplication(sys.argv)
12 | splash = QtWidgets.QSplashScreen(QtGui.QPixmap(":/images/demo1.png"))
13 | splash.showMessage("正在初始化程序...", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black)
14 | splash.show()
15 | QtWidgets.qApp.processEvents()
16 | if debug:
17 | ui = function.fun_main({})
18 | ui.show()
19 | else:
20 | splash.showMessage("正在检查登录状态...", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black)
21 | QtWidgets.qApp.processEvents()
22 | try:
23 | with open("config.json", "r") as f:
24 | login_info = json.loads(f.readline())
25 | check = api.BD()
26 | if check.login(**login_info):
27 | splash.showMessage("登录成功,即将打开主程序...", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black)
28 | QtWidgets.qApp.processEvents()
29 | cookies = check.get_cookies()
30 | for i in cookies:
31 | login_info[i] = cookies[i]
32 | login_info["access_token"] = check.access_token
33 | login_info["refresh_token"] = check.refresh_token
34 | with open("config.json", "w") as f:
35 | f.write(json.dumps(login_info))
36 | ui = function.fun_main(cookies)
37 | ui.show()
38 | splash.finish(ui)
39 | else:
40 | splash.showMessage("登陆状态失效,请重新登录...", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black)
41 | QtWidgets.qApp.processEvents()
42 | raise Exception("登陆状态失效")
43 | except Exception as e:
44 | print(e)
45 | login_w = login_func.login_UI()
46 | login_w.show()
47 | splash.finish(login_w)
48 | exit_code = app.exec_()
49 | if exit_code == 101:
50 | main()
51 | else:
52 | sys.exit()
53 |
54 | if __name__ == '__main__':
55 | main()
56 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | rsa==4.0
2 | requests==2.31.0
3 | QtAwesome==0.7.0
4 | PyQt5==5.14.0
5 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/logo.ico
4 | images/22332.png
5 | images/demo1.png
6 | images/demo2.png
7 |
8 |
9 |
--------------------------------------------------------------------------------
/setting.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'setting.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.14.1
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 |
10 | from PyQt5 import QtCore, QtGui, QtWidgets
11 |
12 |
13 | class Ui_Dialog(object):
14 | def setupUi(self, Dialog):
15 | Dialog.setObjectName("Dialog")
16 | Dialog.resize(600, 375)
17 | self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
18 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
19 | self.verticalLayout.setSpacing(0)
20 | self.verticalLayout.setObjectName("verticalLayout")
21 | self.widget_main = QtWidgets.QWidget(Dialog)
22 | self.widget_main.setStyleSheet("QWidget#widget_main{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0 #4568dc,stop:1 #b06ab3);border-top-left-radius:2px;border-top-right-radius:2px;}")
23 | self.widget_main.setObjectName("widget_main")
24 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget_main)
25 | self.verticalLayout_2.setObjectName("verticalLayout_2")
26 | self.tabWidget = QtWidgets.QTabWidget(self.widget_main)
27 | font = QtGui.QFont()
28 | font.setFamily("微软雅黑")
29 | font.setPointSize(8)
30 | self.tabWidget.setFont(font)
31 | self.tabWidget.setStyleSheet("QTabWidget::pane{border-width:1px;border-style:solid;border-color:rgba(255,255,255,0.7);background:transparent;}\n"
32 | "QTabWidget::tab-bar{background:transparent;subcontrol-position:left;}\n"
33 | "QTabBar::tab{min-width:70px;min-height:20px;background:transparent;}\n"
34 | "QTabBar::tab:selected{color: rgb(255,255,255);background-color:rgba(165,106,183,0.8);}\n"
35 | "QTabBar::tab:!selected{color: blank;background:transparent;}\n"
36 | "QTabBar::tab:hover{color: rgb(255,255,255);background-color:rgba(165,106,183,0.8);}")
37 | self.tabWidget.setTabPosition(QtWidgets.QTabWidget.North)
38 | self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
39 | self.tabWidget.setObjectName("tabWidget")
40 | self.tab = QtWidgets.QWidget()
41 | self.tab.setObjectName("tab")
42 | self.gridLayout = QtWidgets.QGridLayout(self.tab)
43 | self.gridLayout.setObjectName("gridLayout")
44 | self.widget = QtWidgets.QWidget(self.tab)
45 | self.widget.setObjectName("widget")
46 | self.gridLayout_2 = QtWidgets.QGridLayout(self.widget)
47 | self.gridLayout_2.setObjectName("gridLayout_2")
48 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
49 | self.gridLayout_2.addItem(spacerItem, 2, 2, 1, 1)
50 | self.radioButton_z = QtWidgets.QRadioButton(self.widget)
51 | self.radioButton_z.setObjectName("radioButton_z")
52 | self.gridLayout_2.addWidget(self.radioButton_z, 2, 6, 1, 1)
53 | self.label_3 = QtWidgets.QLabel(self.widget)
54 | self.label_3.setMinimumSize(QtCore.QSize(100, 0))
55 | self.label_3.setMaximumSize(QtCore.QSize(100, 16777215))
56 | font = QtGui.QFont()
57 | font.setFamily("微软雅黑")
58 | self.label_3.setFont(font)
59 | self.label_3.setObjectName("label_3")
60 | self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1)
61 | self.comboBox_z = QtWidgets.QComboBox(self.widget)
62 | font = QtGui.QFont()
63 | font.setFamily("微软雅黑")
64 | self.comboBox_z.setFont(font)
65 | self.comboBox_z.setObjectName("comboBox_z")
66 | self.gridLayout_2.addWidget(self.comboBox_z, 2, 1, 1, 1)
67 | self.label = QtWidgets.QLabel(self.widget)
68 | self.label.setMinimumSize(QtCore.QSize(100, 0))
69 | self.label.setMaximumSize(QtCore.QSize(100, 16777215))
70 | font = QtGui.QFont()
71 | font.setFamily("微软雅黑")
72 | self.label.setFont(font)
73 | self.label.setObjectName("label")
74 | self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1)
75 | self.label_2 = QtWidgets.QLabel(self.widget)
76 | font = QtGui.QFont()
77 | font.setFamily("微软雅黑")
78 | self.label_2.setFont(font)
79 | self.label_2.setObjectName("label_2")
80 | self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 7)
81 | self.label_pic = QtWidgets.QLabel(self.widget)
82 | self.label_pic.setMinimumSize(QtCore.QSize(100, 100))
83 | self.label_pic.setMaximumSize(QtCore.QSize(100, 100))
84 | font = QtGui.QFont()
85 | font.setFamily("Lucida Sans Unicode")
86 | self.label_pic.setFont(font)
87 | self.label_pic.setLayoutDirection(QtCore.Qt.LeftToRight)
88 | self.label_pic.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
89 | self.label_pic.setObjectName("label_pic")
90 | self.gridLayout_2.addWidget(self.label_pic, 4, 6, 1, 1)
91 | self.comboBox_d = QtWidgets.QComboBox(self.widget)
92 | font = QtGui.QFont()
93 | font.setFamily("微软雅黑")
94 | self.comboBox_d.setFont(font)
95 | self.comboBox_d.setObjectName("comboBox_d")
96 | self.gridLayout_2.addWidget(self.comboBox_d, 1, 1, 1, 6)
97 | self.lineEdit_choose = QtWidgets.QLineEdit(self.widget)
98 | self.lineEdit_choose.setObjectName("lineEdit_choose")
99 | self.gridLayout_2.addWidget(self.lineEdit_choose, 3, 1, 1, 2)
100 | self.pushButton_choose = QtWidgets.QPushButton(self.widget)
101 | self.pushButton_choose.setObjectName("pushButton_choose")
102 | self.gridLayout_2.addWidget(self.pushButton_choose, 3, 6, 1, 1)
103 | self.gridLayout.addWidget(self.widget, 0, 0, 1, 1)
104 | self.tabWidget.addTab(self.tab, "")
105 | self.tab_2 = QtWidgets.QWidget()
106 | self.tab_2.setObjectName("tab_2")
107 | self.tabWidget.addTab(self.tab_2, "")
108 | self.verticalLayout_2.addWidget(self.tabWidget)
109 | self.widget_2 = QtWidgets.QWidget(self.widget_main)
110 | self.widget_2.setObjectName("widget_2")
111 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_2)
112 | self.horizontalLayout.setObjectName("horizontalLayout")
113 | spacerItem1 = QtWidgets.QSpacerItem(253, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
114 | self.horizontalLayout.addItem(spacerItem1)
115 | self.pushButton_yes = QtWidgets.QPushButton(self.widget_2)
116 | self.pushButton_yes.setObjectName("pushButton_yes")
117 | self.horizontalLayout.addWidget(self.pushButton_yes)
118 | self.pushButton_no = QtWidgets.QPushButton(self.widget_2)
119 | self.pushButton_no.setObjectName("pushButton_no")
120 | self.horizontalLayout.addWidget(self.pushButton_no)
121 | self.pushButton_set = QtWidgets.QPushButton(self.widget_2)
122 | self.pushButton_set.setObjectName("pushButton_set")
123 | self.horizontalLayout.addWidget(self.pushButton_set)
124 | self.verticalLayout_2.addWidget(self.widget_2)
125 | self.verticalLayout.addWidget(self.widget_main)
126 |
127 | self.retranslateUi(Dialog)
128 | self.tabWidget.setCurrentIndex(0)
129 | QtCore.QMetaObject.connectSlotsByName(Dialog)
130 |
131 | def retranslateUi(self, Dialog):
132 | _translate = QtCore.QCoreApplication.translate
133 | Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
134 | self.radioButton_z.setText(_translate("Dialog", "自定义"))
135 | self.label_3.setText(_translate("Dialog", "助手精灵:"))
136 | self.label.setText(_translate("Dialog", "配色方案:"))
137 | self.label_2.setText(_translate("Dialog", "本界面的背景色以及图片均为演示效果,点击应用后可改变主界面效果"))
138 | self.label_pic.setText(_translate("Dialog", "演示图"))
139 | self.pushButton_choose.setText(_translate("Dialog", "选择图片"))
140 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Dialog", "界面设置"))
141 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Dialog", "系统设置"))
142 | self.pushButton_yes.setText(_translate("Dialog", "确认"))
143 | self.pushButton_no.setText(_translate("Dialog", "取消"))
144 | self.pushButton_set.setText(_translate("Dialog", "应用"))
145 |
--------------------------------------------------------------------------------
/setting.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 600
10 | 375
11 |
12 |
13 |
14 | Dialog
15 |
16 |
17 |
18 | 0
19 |
20 |
21 | 0
22 |
23 |
24 | 0
25 |
26 |
27 | 0
28 |
29 |
30 | 0
31 |
32 | -
33 |
34 |
35 | QWidget#widget_main{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0 #4568dc,stop:1 #b06ab3);border-top-left-radius:2px;border-top-right-radius:2px;}
36 |
37 |
38 |
-
39 |
40 |
41 |
42 | 微软雅黑
43 | 8
44 |
45 |
46 |
47 | QTabWidget::pane{border-width:1px;border-style:solid;border-color:rgba(255,255,255,0.7);background:transparent;}
48 | QTabWidget::tab-bar{background:transparent;subcontrol-position:left;}
49 | QTabBar::tab{min-width:70px;min-height:20px;background:transparent;}
50 | QTabBar::tab:selected{color: rgb(255,255,255);background-color:rgba(165,106,183,0.8);}
51 | QTabBar::tab:!selected{color: blank;background:transparent;}
52 | QTabBar::tab:hover{color: rgb(255,255,255);background-color:rgba(165,106,183,0.8);}
53 |
54 |
55 | QTabWidget::North
56 |
57 |
58 | QTabWidget::Rounded
59 |
60 |
61 | 0
62 |
63 |
64 |
65 | 界面设置
66 |
67 |
68 |
-
69 |
70 |
71 |
-
72 |
73 |
74 | Qt::Horizontal
75 |
76 |
77 |
78 | 40
79 | 20
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 | 自定义
88 |
89 |
90 |
91 | -
92 |
93 |
94 |
95 | 100
96 | 0
97 |
98 |
99 |
100 |
101 | 100
102 | 16777215
103 |
104 |
105 |
106 |
107 | 微软雅黑
108 |
109 |
110 |
111 | 助手精灵:
112 |
113 |
114 |
115 | -
116 |
117 |
118 |
119 | 微软雅黑
120 |
121 |
122 |
123 |
124 | -
125 |
126 |
127 |
128 | 100
129 | 0
130 |
131 |
132 |
133 |
134 | 100
135 | 16777215
136 |
137 |
138 |
139 |
140 | 微软雅黑
141 |
142 |
143 |
144 | 配色方案:
145 |
146 |
147 |
148 | -
149 |
150 |
151 |
152 | 微软雅黑
153 |
154 |
155 |
156 | 本界面的背景色以及图片均为演示效果,点击应用后可改变主界面效果
157 |
158 |
159 |
160 | -
161 |
162 |
163 |
164 | 100
165 | 100
166 |
167 |
168 |
169 |
170 | 100
171 | 100
172 |
173 |
174 |
175 |
176 | Lucida Sans Unicode
177 |
178 |
179 |
180 | Qt::LeftToRight
181 |
182 |
183 | 演示图
184 |
185 |
186 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
187 |
188 |
189 |
190 | -
191 |
192 |
193 |
194 | 微软雅黑
195 |
196 |
197 |
198 |
199 | -
200 |
201 |
202 | -
203 |
204 |
205 | 选择图片
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | 系统设置
217 |
218 |
219 |
220 |
221 | -
222 |
223 |
224 |
-
225 |
226 |
227 | Qt::Horizontal
228 |
229 |
230 |
231 | 253
232 | 20
233 |
234 |
235 |
236 |
237 | -
238 |
239 |
240 | 确认
241 |
242 |
243 |
244 | -
245 |
246 |
247 | 取消
248 |
249 |
250 |
251 | -
252 |
253 |
254 | 应用
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
--------------------------------------------------------------------------------
/setting_func.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import pyqtSignal, Qt, QSize
2 | from PyQt5.QtGui import QCursor, QMovie
3 | from PyQt5.QtWidgets import QFileDialog, QMessageBox
4 |
5 | from setting import Ui_Dialog
6 | from PyQt5 import QtWidgets, QtCore, QtGui
7 |
8 |
9 | class setting_UI(Ui_Dialog, QtWidgets.QDialog):
10 | mySignal = pyqtSignal(dict)
11 |
12 | def __init__(self):
13 | super(setting_UI, self).__init__()
14 | self.setupUi(self)
15 | self.m_flag = False
16 | self.setFixedSize(self.width(), self.height())
17 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
18 | self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) # 窗口始终置顶
19 | self.pushButton_yes.clicked.connect(self.win_close)
20 | self.pushButton_set.clicked.connect(self.sendChange)
21 | self.pushButton_no.clicked.connect(self.close)
22 | self.comboBox_d.currentIndexChanged.connect(self.change_color)
23 | self.comboBox_z.currentIndexChanged.connect(self.change_pic)
24 | self.colors = {
25 | "Can You Feel The Love Tonight": ["#4568DC", "#B06AB3"],
26 | "Meridian": ["#283c86", "#45a247"],
27 | "Mello": ["#c0392b", "#8e44ad"],
28 | "CryStal Clear": ["#159957", "#155799"],
29 | "Chitty Chitty Bang Bang": ["#007991", "#78ffd6"],
30 | "Blue Skies": ["#56CCF2", "#2F80ED"],
31 | "Cinnamint": ["#4AC29A", "#BDFFF3"],
32 | "Maldives": ["#B2FEFA", "#0ED2F7"],
33 | "Sha La La": ["#D66D75", "#E29587"],
34 | "Scooter": ["#36D1DC", "#5B86E5"],
35 | "Alive": ["#CB356B", "#BD3F32"],
36 | "Visions of Grandeur": ["#000046", "#1CB5E0"],
37 | "Sunkist": ["#F2994A", "#F2C94C"],
38 | "Coal": ["#EB5757", "#000000"],
39 | "Mini": ["#30E8BF", "#FF8235"],
40 | "Purplepine": ["#20002c", "#cbb4d4"],
41 | "Celestial": ["#C33764", "#1D2671"],
42 | "Pacific Dream": ["#34e89e", "#0f3443"],
43 | "Venice": ["#6190E8", "#A7BFE8"],
44 | "Orca": ["#44A08D", "#093637"],
45 | "Love and Liberty": ["#200122", "#6f0000"],
46 | "The Blue Lagoon": ["#43C6AC", "#191654"],
47 | "Under the Lake": ["#093028", "#237A57"],
48 | "Honey Dew": ["#43C6AC", "#F8FFAE"],
49 | "Roseanne": ["#FFAFBD", "#ffc3a0"],
50 | "What lies Beyond": ["#F0F2F0", "#000C40"],
51 | "Rose Colored Lenses": ["#E8CBC0", "#636FA4"],
52 | "Cocoaa Ice": ["#c0c0aa", "#1cefff"],
53 | "Vice City": ["#3494E6", "#EC6EAD"],
54 | "80's Purple": ["#41295a", "#2F0743"],
55 | "Cosmic Fusion": ["#ff00cc", "#333399"],
56 | "Nepal": ["#de6161", "#2657eb"],
57 | }
58 | for i in self.colors:
59 | self.comboBox_d.addItem(i)
60 | self.pics = {
61 | "demo1": ":/images/demo1.png",
62 | "demo2": ":/images/demo2.png",
63 | }
64 | for i in self.pics:
65 | self.comboBox_z.addItem(i)
66 | self.label_pic.setPixmap(QtGui.QPixmap(":/images/demo1.png"))
67 | self.label_pic.setScaledContents(True)
68 | self.radioButton_z.toggled.connect(self.choose_show)
69 | self.pushButton_choose.hide()
70 | self.lineEdit_choose.hide()
71 | self.pushButton_choose.clicked.connect(self.choose_pic)
72 |
73 | def win_close(self):
74 | self.sendChange()
75 | self.close()
76 |
77 | def choose_pic(self):
78 | fileName1, filetype = QFileDialog.getOpenFileName(self,
79 | "选取文件",
80 | "C:/",
81 | "All Pics (*.png *.jpg *.jpeg *.gif)")
82 | self.lineEdit_choose.setText(fileName1)
83 | self.gif = QMovie(fileName1)
84 | self.gif.setScaledSize(QSize(200, 200))
85 | self.label_pic.setMovie(self.gif)
86 | self.gif.start()
87 | # self.label_pic.setPixmap(QtGui.QPixmap(fileName1))
88 | # self.label_pic.setScaledContents(True)
89 |
90 | def choose_show(self):
91 | if self.radioButton_z.isChecked():
92 | self.lineEdit_choose.show()
93 | self.pushButton_choose.show()
94 |
95 | def change_pic(self):
96 | if self.radioButton_z.isChecked():
97 | self.lineEdit_choose.hide()
98 | self.pushButton_choose.hide()
99 | self.radioButton_z.toggle()
100 | pic = self.pics[self.comboBox_z.currentText()]
101 | self.label_pic.setPixmap(QtGui.QPixmap(pic))
102 | self.label_pic.setScaledContents(True)
103 |
104 | def change_color(self):
105 | color = self.colors[self.comboBox_d.currentText()]
106 | self.widget_main.setStyleSheet(
107 | "QWidget#widget_main{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0" + f" {color[0]},stop:1 {color[1]}" + ");border-top-left-radius:2px;border-top-right-radius:2px;}")
108 |
109 | def mousePressEvent(self, event):
110 | if event.button() == Qt.LeftButton:
111 | self.m_flag = True
112 | self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
113 | event.accept()
114 | self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
115 |
116 | def mouseMoveEvent(self, QMouseEvent):
117 | if Qt.LeftButton and self.m_flag:
118 | self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
119 | QMouseEvent.accept()
120 |
121 | def mouseReleaseEvent(self, QMouseEvent):
122 | self.m_flag = False
123 | self.setCursor(QCursor(Qt.ArrowCursor))
124 |
125 | def keyPressEvent(self, e):
126 | if e.key() == Qt.Key_Return: # 重写Esc键事件
127 | pass
128 | # self.close()
129 | elif e.key() == Qt.Key_Enter:
130 | pass
131 |
132 | def sendChange(self):
133 | color = self.colors[self.comboBox_d.currentText()]
134 | if self.radioButton_z.isChecked():
135 | pic = self.lineEdit_choose.text()
136 | if not pic:
137 | QMessageBox.information(self, '小助手提示', '图片不能为空')
138 | else:
139 | pic = self.pics[self.comboBox_z.currentText()]
140 | self.mySignal.emit({"color": color, "pic": pic}) # 发射信号
--------------------------------------------------------------------------------
/soft_cfg.py:
--------------------------------------------------------------------------------
1 | # 版本控制
2 | version = 1.2
3 | soft_name = "哔哩哔哩UP主助手.exe"
4 |
5 | # url 配置
6 | feedback_url = "https://toodo.fun/funs/learn/files/article.php?id=58"
7 | update_url = "https://www.toodo.fun/funs/bilibili/version.php"
8 |
9 | # 测试数据
10 | result_test = {
11 | "net": 1,
12 | "hot_update": 1,
13 | "Version": None,
14 | "Update_des": "1、更新了一\n2、更新了2222\n3、更新了333",
15 | "Update_url": "https://toodo.fun/funs/learn/files/article.php?id=58"
16 | }
17 |
--------------------------------------------------------------------------------
/windows.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'windows.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.14.1
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 |
10 | from PyQt5 import QtCore, QtGui, QtWidgets
11 |
12 |
13 | class Ui_MainWindow(object):
14 | def setupUi(self, MainWindow):
15 | MainWindow.setObjectName("MainWindow")
16 | MainWindow.setEnabled(True)
17 | MainWindow.resize(1200, 908)
18 | font = QtGui.QFont()
19 | font.setFamily("Arial")
20 | MainWindow.setFont(font)
21 | MainWindow.setToolTip("")
22 | MainWindow.setAnimated(True)
23 | self.centralwidget = QtWidgets.QWidget(MainWindow)
24 | self.centralwidget.setObjectName("centralwidget")
25 | self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
26 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
27 | self.gridLayout.setSpacing(0)
28 | self.gridLayout.setObjectName("gridLayout")
29 | self.widget_main = QtWidgets.QWidget(self.centralwidget)
30 | self.widget_main.setStyleSheet("QWidget#widget_main{background:#1F1F1F;border-radius:2px;}")
31 | self.widget_main.setObjectName("widget_main")
32 | self.gridLayout_2 = QtWidgets.QGridLayout(self.widget_main)
33 | self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
34 | self.gridLayout_2.setSpacing(0)
35 | self.gridLayout_2.setObjectName("gridLayout_2")
36 | self.widget_top = QtWidgets.QWidget(self.widget_main)
37 | self.widget_top.setMinimumSize(QtCore.QSize(0, 50))
38 | self.widget_top.setMaximumSize(QtCore.QSize(16777215, 50))
39 | self.widget_top.setStyleSheet("")
40 | self.widget_top.setObjectName("widget_top")
41 | self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.widget_top)
42 | self.horizontalLayout_5.setContentsMargins(0, 0, 5, 0)
43 | self.horizontalLayout_5.setSpacing(0)
44 | self.horizontalLayout_5.setObjectName("horizontalLayout_5")
45 | self.widget_top_l1 = QtWidgets.QWidget(self.widget_top)
46 | self.widget_top_l1.setMinimumSize(QtCore.QSize(0, 50))
47 | self.widget_top_l1.setMaximumSize(QtCore.QSize(16777215, 50))
48 | self.widget_top_l1.setObjectName("widget_top_l1")
49 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_top_l1)
50 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
51 | self.horizontalLayout.setSpacing(10)
52 | self.horizontalLayout.setObjectName("horizontalLayout")
53 | self.label_face = QtWidgets.QLabel(self.widget_top_l1)
54 | self.label_face.setMinimumSize(QtCore.QSize(50, 50))
55 | self.label_face.setMaximumSize(QtCore.QSize(50, 50))
56 | self.label_face.setStyleSheet("QLabel{border-radius:22px;background:Transparent}")
57 | self.label_face.setText("")
58 | self.label_face.setAlignment(QtCore.Qt.AlignCenter)
59 | self.label_face.setObjectName("label_face")
60 | self.horizontalLayout.addWidget(self.label_face)
61 | self.pushButton_nickname = QtWidgets.QPushButton(self.widget_top_l1)
62 | font = QtGui.QFont()
63 | font.setBold(True)
64 | font.setWeight(75)
65 | self.pushButton_nickname.setFont(font)
66 | self.pushButton_nickname.setStyleSheet("QPushButton{background:Transparent;text-align: left;color:white;}QPushButton:hover{color:rgba(255,255,255, 0.8);}")
67 | self.pushButton_nickname.setText("")
68 | self.pushButton_nickname.setObjectName("pushButton_nickname")
69 | self.horizontalLayout.addWidget(self.pushButton_nickname)
70 | self.horizontalLayout_5.addWidget(self.widget_top_l1)
71 | self.widget_top_l2 = QtWidgets.QWidget(self.widget_top)
72 | self.widget_top_l2.setMinimumSize(QtCore.QSize(0, 50))
73 | self.widget_top_l2.setMaximumSize(QtCore.QSize(16777215, 50))
74 | self.widget_top_l2.setObjectName("widget_top_l2")
75 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_top_l2)
76 | self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
77 | self.horizontalLayout_3.setSpacing(0)
78 | self.horizontalLayout_3.setObjectName("horizontalLayout_3")
79 | self.pushButton_notify = QtWidgets.QPushButton(self.widget_top_l2)
80 | font = QtGui.QFont()
81 | font.setFamily("微软雅黑")
82 | self.pushButton_notify.setFont(font)
83 | self.pushButton_notify.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
84 | self.pushButton_notify.setStyleSheet("QPushButton{background:Transparent;text-align: left;color:white;}QPushButton:hover{color:rgba(255,255,255, 0.8);}")
85 | self.pushButton_notify.setObjectName("pushButton_notify")
86 | self.horizontalLayout_3.addWidget(self.pushButton_notify)
87 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
88 | self.horizontalLayout_3.addItem(spacerItem)
89 | self.horizontalLayout_5.addWidget(self.widget_top_l2)
90 | self.widget_top_l3 = QtWidgets.QWidget(self.widget_top)
91 | self.widget_top_l3.setMinimumSize(QtCore.QSize(0, 50))
92 | self.widget_top_l3.setMaximumSize(QtCore.QSize(16777215, 50))
93 | self.widget_top_l3.setObjectName("widget_top_l3")
94 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget_top_l3)
95 | self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
96 | self.horizontalLayout_4.setSpacing(0)
97 | self.horizontalLayout_4.setObjectName("horizontalLayout_4")
98 | self.pushButton_feedback = QtWidgets.QPushButton(self.widget_top_l3)
99 | self.pushButton_feedback.setMinimumSize(QtCore.QSize(30, 30))
100 | self.pushButton_feedback.setMaximumSize(QtCore.QSize(30, 30))
101 | self.pushButton_feedback.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,112,158,0.8);}")
102 | self.pushButton_feedback.setText("")
103 | self.pushButton_feedback.setObjectName("pushButton_feedback")
104 | self.horizontalLayout_4.addWidget(self.pushButton_feedback)
105 | self.pushButton_setting = QtWidgets.QPushButton(self.widget_top_l3)
106 | self.pushButton_setting.setMinimumSize(QtCore.QSize(30, 30))
107 | self.pushButton_setting.setMaximumSize(QtCore.QSize(30, 30))
108 | self.pushButton_setting.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,112,158,0.8);}")
109 | self.pushButton_setting.setText("")
110 | self.pushButton_setting.setObjectName("pushButton_setting")
111 | self.horizontalLayout_4.addWidget(self.pushButton_setting)
112 | self.pushButton_min = QtWidgets.QPushButton(self.widget_top_l3)
113 | self.pushButton_min.setMinimumSize(QtCore.QSize(30, 30))
114 | self.pushButton_min.setMaximumSize(QtCore.QSize(30, 30))
115 | self.pushButton_min.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,112,158,0.8);}")
116 | self.pushButton_min.setText("")
117 | self.pushButton_min.setObjectName("pushButton_min")
118 | self.horizontalLayout_4.addWidget(self.pushButton_min)
119 | self.pushButton_max = QtWidgets.QPushButton(self.widget_top_l3)
120 | self.pushButton_max.setMinimumSize(QtCore.QSize(30, 30))
121 | self.pushButton_max.setMaximumSize(QtCore.QSize(30, 30))
122 | self.pushButton_max.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,112,158,0.8);}")
123 | self.pushButton_max.setText("")
124 | self.pushButton_max.setObjectName("pushButton_max")
125 | self.horizontalLayout_4.addWidget(self.pushButton_max)
126 | self.pushButton_close = QtWidgets.QPushButton(self.widget_top_l3)
127 | self.pushButton_close.setMinimumSize(QtCore.QSize(30, 30))
128 | self.pushButton_close.setMaximumSize(QtCore.QSize(30, 30))
129 | self.pushButton_close.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(255,112,158,0.8);}")
130 | self.pushButton_close.setText("")
131 | self.pushButton_close.setObjectName("pushButton_close")
132 | self.horizontalLayout_4.addWidget(self.pushButton_close)
133 | self.horizontalLayout_5.addWidget(self.widget_top_l3)
134 | self.horizontalLayout_5.setStretch(0, 3)
135 | self.horizontalLayout_5.setStretch(1, 8)
136 | self.horizontalLayout_5.setStretch(2, 1)
137 | self.gridLayout_2.addWidget(self.widget_top, 0, 0, 1, 1)
138 | self.widget_down = QtWidgets.QWidget(self.widget_main)
139 | self.widget_down.setStyleSheet("QWidget#widget_down{background:#F0F5FF;border-bottom-left-radius:2px;border-bottom-right-radius:2px;}")
140 | self.widget_down.setObjectName("widget_down")
141 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget_down)
142 | self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
143 | self.horizontalLayout_2.setSpacing(0)
144 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
145 | self.widget_left = QtWidgets.QWidget(self.widget_down)
146 | self.widget_left.setMinimumSize(QtCore.QSize(0, 0))
147 | self.widget_left.setMaximumSize(QtCore.QSize(300, 16777215))
148 | self.widget_left.setStyleSheet("QWidget#widget_left{background:#F0F5FF;border-bottom-left-radius:2px;border-right-width:1px;border-style:solid;border-color:rgba(69,104,220,0.3);}")
149 | self.widget_left.setObjectName("widget_left")
150 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget_left)
151 | self.verticalLayout_2.setContentsMargins(0, 11, 0, -1)
152 | self.verticalLayout_2.setObjectName("verticalLayout_2")
153 | self.widget_left_t1 = QtWidgets.QWidget(self.widget_left)
154 | self.widget_left_t1.setStyleSheet("QWidget#widget_left_t1{background:rgba(255,255,255,0.5);border-bottom-right-radius:2px;}")
155 | self.widget_left_t1.setObjectName("widget_left_t1")
156 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget_left_t1)
157 | self.verticalLayout_3.setContentsMargins(11, -1, 11, -1)
158 | self.verticalLayout_3.setObjectName("verticalLayout_3")
159 | self.widget_4 = QtWidgets.QWidget(self.widget_left_t1)
160 | self.widget_4.setObjectName("widget_4")
161 | self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.widget_4)
162 | self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
163 | self.horizontalLayout_7.setSpacing(0)
164 | self.horizontalLayout_7.setObjectName("horizontalLayout_7")
165 | self.label_level = QtWidgets.QLabel(self.widget_4)
166 | font = QtGui.QFont()
167 | font.setFamily("微软雅黑")
168 | self.label_level.setFont(font)
169 | self.label_level.setObjectName("label_level")
170 | self.horizontalLayout_7.addWidget(self.label_level)
171 | self.label_exp = QtWidgets.QLabel(self.widget_4)
172 | font = QtGui.QFont()
173 | font.setFamily("微软雅黑")
174 | self.label_exp.setFont(font)
175 | self.label_exp.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
176 | self.label_exp.setObjectName("label_exp")
177 | self.horizontalLayout_7.addWidget(self.label_exp)
178 | self.verticalLayout_3.addWidget(self.widget_4)
179 | self.progressBar = QtWidgets.QProgressBar(self.widget_left_t1)
180 | self.progressBar.setMaximumSize(QtCore.QSize(16777215, 10))
181 | self.progressBar.setStyleSheet("QProgressBar::chunk{background:qlineargradient(spread:pad,x1:0,y1:0,x2:1,y2:0,stop:0 #36d1dc,stop:1 #5b86e5);}")
182 | self.progressBar.setProperty("value", 0)
183 | self.progressBar.setTextVisible(False)
184 | self.progressBar.setObjectName("progressBar")
185 | self.verticalLayout_3.addWidget(self.progressBar)
186 | self.widget_5 = QtWidgets.QWidget(self.widget_left_t1)
187 | self.widget_5.setObjectName("widget_5")
188 | self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.widget_5)
189 | self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0)
190 | self.horizontalLayout_8.setObjectName("horizontalLayout_8")
191 | self.pushButton_coin = QtWidgets.QPushButton(self.widget_5)
192 | font = QtGui.QFont()
193 | font.setFamily("微软雅黑")
194 | self.pushButton_coin.setFont(font)
195 | self.pushButton_coin.setStyleSheet("QPushButton{background:Transparent;text-align: left;}")
196 | self.pushButton_coin.setObjectName("pushButton_coin")
197 | self.horizontalLayout_8.addWidget(self.pushButton_coin)
198 | self.pushButton_balance = QtWidgets.QPushButton(self.widget_5)
199 | font = QtGui.QFont()
200 | font.setFamily("微软雅黑")
201 | self.pushButton_balance.setFont(font)
202 | self.pushButton_balance.setStyleSheet("QPushButton{background:Transparent;text-align: left;}")
203 | self.pushButton_balance.setObjectName("pushButton_balance")
204 | self.horizontalLayout_8.addWidget(self.pushButton_balance)
205 | self.verticalLayout_3.addWidget(self.widget_5)
206 | self.verticalLayout_2.addWidget(self.widget_left_t1)
207 | self.widget_left_t8 = QtWidgets.QWidget(self.widget_left)
208 | self.widget_left_t8.setStyleSheet("QWidget#widget_left_t8{background:rgba(255,255,255,0.5);border-bottom-right-radius:2px;}")
209 | self.widget_left_t8.setObjectName("widget_left_t8")
210 | self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.widget_left_t8)
211 | self.verticalLayout_5.setObjectName("verticalLayout_5")
212 | self.label_3 = QtWidgets.QLabel(self.widget_left_t8)
213 | font = QtGui.QFont()
214 | font.setFamily("微软雅黑")
215 | font.setPointSize(8)
216 | self.label_3.setFont(font)
217 | self.label_3.setObjectName("label_3")
218 | self.verticalLayout_5.addWidget(self.label_3)
219 | self.widget_9 = QtWidgets.QWidget(self.widget_left_t8)
220 | self.widget_9.setObjectName("widget_9")
221 | self.horizontalLayout_16 = QtWidgets.QHBoxLayout(self.widget_9)
222 | self.horizontalLayout_16.setObjectName("horizontalLayout_16")
223 | self.label_creative = QtWidgets.QLabel(self.widget_9)
224 | font = QtGui.QFont()
225 | font.setFamily("微软雅黑")
226 | self.label_creative.setFont(font)
227 | self.label_creative.setAlignment(QtCore.Qt.AlignCenter)
228 | self.label_creative.setObjectName("label_creative")
229 | self.horizontalLayout_16.addWidget(self.label_creative)
230 | self.label_influence = QtWidgets.QLabel(self.widget_9)
231 | font = QtGui.QFont()
232 | font.setFamily("微软雅黑")
233 | self.label_influence.setFont(font)
234 | self.label_influence.setAlignment(QtCore.Qt.AlignCenter)
235 | self.label_influence.setObjectName("label_influence")
236 | self.horizontalLayout_16.addWidget(self.label_influence)
237 | self.label_credit = QtWidgets.QLabel(self.widget_9)
238 | font = QtGui.QFont()
239 | font.setFamily("微软雅黑")
240 | self.label_credit.setFont(font)
241 | self.label_credit.setAlignment(QtCore.Qt.AlignCenter)
242 | self.label_credit.setObjectName("label_credit")
243 | self.horizontalLayout_16.addWidget(self.label_credit)
244 | self.verticalLayout_5.addWidget(self.widget_9)
245 | self.verticalLayout_2.addWidget(self.widget_left_t8)
246 | self.widget_left_t5 = QtWidgets.QWidget(self.widget_left)
247 | self.widget_left_t5.setStyleSheet("QWidget#widget_left_t5{background:rgba(255,255,255,0.5);border-bottom-right-radius:2px;}")
248 | self.widget_left_t5.setObjectName("widget_left_t5")
249 | self.verticalLayout = QtWidgets.QVBoxLayout(self.widget_left_t5)
250 | self.verticalLayout.setObjectName("verticalLayout")
251 | self.label = QtWidgets.QLabel(self.widget_left_t5)
252 | font = QtGui.QFont()
253 | font.setFamily("微软雅黑")
254 | font.setPointSize(8)
255 | self.label.setFont(font)
256 | self.label.setObjectName("label")
257 | self.verticalLayout.addWidget(self.label)
258 | self.widget_left_t2 = QtWidgets.QWidget(self.widget_left_t5)
259 | self.widget_left_t2.setStyleSheet("QWidget#widget_left_t2{background:Transparent;border-bottom-right-radius:2px;}")
260 | self.widget_left_t2.setObjectName("widget_left_t2")
261 | self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.widget_left_t2)
262 | self.horizontalLayout_6.setContentsMargins(0, 11, 0, -1)
263 | self.horizontalLayout_6.setObjectName("horizontalLayout_6")
264 | self.label_follower = QtWidgets.QLabel(self.widget_left_t2)
265 | font = QtGui.QFont()
266 | font.setFamily("微软雅黑")
267 | self.label_follower.setFont(font)
268 | self.label_follower.setAlignment(QtCore.Qt.AlignCenter)
269 | self.label_follower.setObjectName("label_follower")
270 | self.horizontalLayout_6.addWidget(self.label_follower)
271 | self.label_view = QtWidgets.QLabel(self.widget_left_t2)
272 | font = QtGui.QFont()
273 | font.setFamily("微软雅黑")
274 | self.label_view.setFont(font)
275 | self.label_view.setAlignment(QtCore.Qt.AlignCenter)
276 | self.label_view.setObjectName("label_view")
277 | self.horizontalLayout_6.addWidget(self.label_view)
278 | self.label_like = QtWidgets.QLabel(self.widget_left_t2)
279 | font = QtGui.QFont()
280 | font.setFamily("微软雅黑")
281 | self.label_like.setFont(font)
282 | self.label_like.setAlignment(QtCore.Qt.AlignCenter)
283 | self.label_like.setObjectName("label_like")
284 | self.horizontalLayout_6.addWidget(self.label_like)
285 | self.label_coin = QtWidgets.QLabel(self.widget_left_t2)
286 | font = QtGui.QFont()
287 | font.setFamily("微软雅黑")
288 | self.label_coin.setFont(font)
289 | self.label_coin.setAlignment(QtCore.Qt.AlignCenter)
290 | self.label_coin.setObjectName("label_coin")
291 | self.horizontalLayout_6.addWidget(self.label_coin)
292 | self.verticalLayout.addWidget(self.widget_left_t2)
293 | self.widget_left_t3 = QtWidgets.QWidget(self.widget_left_t5)
294 | self.widget_left_t3.setStyleSheet("QWidget#widget_left_t3{background:Transparent;border-bottom-right-radius:2px;}")
295 | self.widget_left_t3.setObjectName("widget_left_t3")
296 | self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.widget_left_t3)
297 | self.horizontalLayout_9.setContentsMargins(0, -1, 0, -1)
298 | self.horizontalLayout_9.setObjectName("horizontalLayout_9")
299 | self.label_reply = QtWidgets.QLabel(self.widget_left_t3)
300 | font = QtGui.QFont()
301 | font.setFamily("微软雅黑")
302 | self.label_reply.setFont(font)
303 | self.label_reply.setAlignment(QtCore.Qt.AlignCenter)
304 | self.label_reply.setObjectName("label_reply")
305 | self.horizontalLayout_9.addWidget(self.label_reply)
306 | self.label_danmaku = QtWidgets.QLabel(self.widget_left_t3)
307 | font = QtGui.QFont()
308 | font.setFamily("微软雅黑")
309 | self.label_danmaku.setFont(font)
310 | self.label_danmaku.setAlignment(QtCore.Qt.AlignCenter)
311 | self.label_danmaku.setObjectName("label_danmaku")
312 | self.horizontalLayout_9.addWidget(self.label_danmaku)
313 | self.label_share = QtWidgets.QLabel(self.widget_left_t3)
314 | font = QtGui.QFont()
315 | font.setFamily("微软雅黑")
316 | self.label_share.setFont(font)
317 | self.label_share.setAlignment(QtCore.Qt.AlignCenter)
318 | self.label_share.setObjectName("label_share")
319 | self.horizontalLayout_9.addWidget(self.label_share)
320 | self.label_favorite = QtWidgets.QLabel(self.widget_left_t3)
321 | font = QtGui.QFont()
322 | font.setFamily("微软雅黑")
323 | self.label_favorite.setFont(font)
324 | self.label_favorite.setAlignment(QtCore.Qt.AlignCenter)
325 | self.label_favorite.setObjectName("label_favorite")
326 | self.horizontalLayout_9.addWidget(self.label_favorite)
327 | self.verticalLayout.addWidget(self.widget_left_t3)
328 | self.verticalLayout_2.addWidget(self.widget_left_t5)
329 | self.widget_left_t4 = QtWidgets.QWidget(self.widget_left)
330 | self.widget_left_t4.setStyleSheet("QWidget#widget_left_t4{background:rgba(255,255,255,0.5);border-bottom-right-radius:2px;}")
331 | self.widget_left_t4.setObjectName("widget_left_t4")
332 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.widget_left_t4)
333 | self.verticalLayout_4.setObjectName("verticalLayout_4")
334 | self.label_2 = QtWidgets.QLabel(self.widget_left_t4)
335 | font = QtGui.QFont()
336 | font.setFamily("微软雅黑")
337 | font.setPointSize(8)
338 | self.label_2.setFont(font)
339 | self.label_2.setObjectName("label_2")
340 | self.verticalLayout_4.addWidget(self.label_2)
341 | self.widget_left_t6 = QtWidgets.QWidget(self.widget_left_t4)
342 | self.widget_left_t6.setStyleSheet("QWidget#widget_left_t6{background:Transparent;border-bottom-right-radius:2px;}")
343 | self.widget_left_t6.setObjectName("widget_left_t6")
344 | self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.widget_left_t6)
345 | self.horizontalLayout_13.setContentsMargins(0, -1, 0, -1)
346 | self.horizontalLayout_13.setObjectName("horizontalLayout_13")
347 | self.label_artview = QtWidgets.QLabel(self.widget_left_t6)
348 | font = QtGui.QFont()
349 | font.setFamily("微软雅黑")
350 | self.label_artview.setFont(font)
351 | self.label_artview.setAlignment(QtCore.Qt.AlignCenter)
352 | self.label_artview.setObjectName("label_artview")
353 | self.horizontalLayout_13.addWidget(self.label_artview)
354 | self.label_artlike = QtWidgets.QLabel(self.widget_left_t6)
355 | font = QtGui.QFont()
356 | font.setFamily("微软雅黑")
357 | self.label_artlike.setFont(font)
358 | self.label_artlike.setAlignment(QtCore.Qt.AlignCenter)
359 | self.label_artlike.setObjectName("label_artlike")
360 | self.horizontalLayout_13.addWidget(self.label_artlike)
361 | self.label_artcoin = QtWidgets.QLabel(self.widget_left_t6)
362 | font = QtGui.QFont()
363 | font.setFamily("微软雅黑")
364 | self.label_artcoin.setFont(font)
365 | self.label_artcoin.setAlignment(QtCore.Qt.AlignCenter)
366 | self.label_artcoin.setObjectName("label_artcoin")
367 | self.horizontalLayout_13.addWidget(self.label_artcoin)
368 | self.verticalLayout_4.addWidget(self.widget_left_t6)
369 | self.widget_left_t7 = QtWidgets.QWidget(self.widget_left_t4)
370 | self.widget_left_t7.setStyleSheet("QWidget#widget_left_t7{background:Transparent;border-bottom-right-radius:2px;}")
371 | self.widget_left_t7.setObjectName("widget_left_t7")
372 | self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.widget_left_t7)
373 | self.horizontalLayout_14.setContentsMargins(0, -1, 0, -1)
374 | self.horizontalLayout_14.setObjectName("horizontalLayout_14")
375 | self.label_artreply = QtWidgets.QLabel(self.widget_left_t7)
376 | font = QtGui.QFont()
377 | font.setFamily("微软雅黑")
378 | self.label_artreply.setFont(font)
379 | self.label_artreply.setAlignment(QtCore.Qt.AlignCenter)
380 | self.label_artreply.setObjectName("label_artreply")
381 | self.horizontalLayout_14.addWidget(self.label_artreply)
382 | self.label_artshare = QtWidgets.QLabel(self.widget_left_t7)
383 | font = QtGui.QFont()
384 | font.setFamily("微软雅黑")
385 | self.label_artshare.setFont(font)
386 | self.label_artshare.setAlignment(QtCore.Qt.AlignCenter)
387 | self.label_artshare.setObjectName("label_artshare")
388 | self.horizontalLayout_14.addWidget(self.label_artshare)
389 | self.label_artfav = QtWidgets.QLabel(self.widget_left_t7)
390 | font = QtGui.QFont()
391 | font.setFamily("微软雅黑")
392 | self.label_artfav.setFont(font)
393 | self.label_artfav.setAlignment(QtCore.Qt.AlignCenter)
394 | self.label_artfav.setObjectName("label_artfav")
395 | self.horizontalLayout_14.addWidget(self.label_artfav)
396 | self.verticalLayout_4.addWidget(self.widget_left_t7)
397 | self.verticalLayout_2.addWidget(self.widget_left_t4)
398 | spacerItem1 = QtWidgets.QSpacerItem(20, 144, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
399 | self.verticalLayout_2.addItem(spacerItem1)
400 | self.widget_3 = QtWidgets.QWidget(self.widget_left)
401 | self.widget_3.setObjectName("widget_3")
402 | self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.widget_3)
403 | self.horizontalLayout_10.setContentsMargins(6, 6, 6, 6)
404 | self.horizontalLayout_10.setSpacing(6)
405 | self.horizontalLayout_10.setObjectName("horizontalLayout_10")
406 | self.label_left_b1 = QtWidgets.QLabel(self.widget_3)
407 | self.label_left_b1.setMinimumSize(QtCore.QSize(200, 200))
408 | self.label_left_b1.setMaximumSize(QtCore.QSize(200, 200))
409 | self.label_left_b1.setText("")
410 | self.label_left_b1.setTextFormat(QtCore.Qt.AutoText)
411 | self.label_left_b1.setPixmap(QtGui.QPixmap(":/images/demo1.png"))
412 | self.label_left_b1.setScaledContents(True)
413 | self.label_left_b1.setAlignment(QtCore.Qt.AlignCenter)
414 | self.label_left_b1.setOpenExternalLinks(False)
415 | self.label_left_b1.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
416 | self.label_left_b1.setObjectName("label_left_b1")
417 | self.horizontalLayout_10.addWidget(self.label_left_b1)
418 | self.verticalLayout_2.addWidget(self.widget_3)
419 | self.horizontalLayout_2.addWidget(self.widget_left)
420 | self.widget_right = QtWidgets.QWidget(self.widget_down)
421 | self.widget_right.setStyleSheet("QWidget#widget_right{background:#FFFFFF;border-bottom-right-radius:2px;}")
422 | self.widget_right.setObjectName("widget_right")
423 | self.gridLayout_3 = QtWidgets.QGridLayout(self.widget_right)
424 | self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
425 | self.gridLayout_3.setSpacing(0)
426 | self.gridLayout_3.setObjectName("gridLayout_3")
427 | self.tabWidget = QtWidgets.QTabWidget(self.widget_right)
428 | font = QtGui.QFont()
429 | font.setFamily("微软雅黑")
430 | font.setPointSize(10)
431 | self.tabWidget.setFont(font)
432 | self.tabWidget.setStyleSheet("QTabWidget::pane{border-top-width:1px;border-style:solid;border-color:rgba(69,104,220,0.3);background:transparent;}\n"
433 | "QTabWidget::tab-bar{background:transparent;subcontrol-position:left;}\n"
434 | "QTabBar::tab{min-width:70px;min-height:50px;background:transparent;}\n"
435 | "QTabBar::tab:selected{color: rgb(69,104,220);background-color:rgba(240,245,255,0.8);}\n"
436 | "QTabBar::tab:!selected{color: blank;background:transparent;}\n"
437 | "QTabBar::tab:hover{color: rgb(69,104,220);background-color:rgba(240,245,255,0.8);}")
438 | self.tabWidget.setObjectName("tabWidget")
439 | self.tab_2 = QtWidgets.QWidget()
440 | self.tab_2.setObjectName("tab_2")
441 | self.gridLayout_4 = QtWidgets.QGridLayout(self.tab_2)
442 | self.gridLayout_4.setObjectName("gridLayout_4")
443 | self.widget = QtWidgets.QWidget(self.tab_2)
444 | self.widget.setObjectName("widget")
445 | self.gridLayout_5 = QtWidgets.QGridLayout(self.widget)
446 | self.gridLayout_5.setContentsMargins(0, 0, 0, 0)
447 | self.gridLayout_5.setSpacing(0)
448 | self.gridLayout_5.setObjectName("gridLayout_5")
449 | self.listWidget = QtWidgets.QListWidget(self.widget)
450 | self.listWidget.setStyleSheet("QListWidget{background:transparent;border:0px solid grey;margin:10px;}")
451 | self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
452 | self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
453 | self.listWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
454 | self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
455 | self.listWidget.setViewMode(QtWidgets.QListView.ListMode)
456 | self.listWidget.setObjectName("listWidget")
457 | self.gridLayout_5.addWidget(self.listWidget, 1, 0, 1, 1)
458 | self.widget_2 = QtWidgets.QWidget(self.widget)
459 | self.widget_2.setObjectName("widget_2")
460 | self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.widget_2)
461 | self.horizontalLayout_11.setContentsMargins(0, 0, 0, 0)
462 | self.horizontalLayout_11.setSpacing(0)
463 | self.horizontalLayout_11.setObjectName("horizontalLayout_11")
464 | self.label_vtot = QtWidgets.QLabel(self.widget_2)
465 | font = QtGui.QFont()
466 | font.setFamily("微软雅黑")
467 | self.label_vtot.setFont(font)
468 | self.label_vtot.setText("")
469 | self.label_vtot.setObjectName("label_vtot")
470 | self.horizontalLayout_11.addWidget(self.label_vtot)
471 | spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
472 | self.horizontalLayout_11.addItem(spacerItem2)
473 | self.pushButton_vrenew = QtWidgets.QPushButton(self.widget_2)
474 | self.pushButton_vrenew.setMinimumSize(QtCore.QSize(30, 30))
475 | self.pushButton_vrenew.setMaximumSize(QtCore.QSize(100, 30))
476 | self.pushButton_vrenew.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(240,245,255,0.8);}")
477 | self.pushButton_vrenew.setText("")
478 | self.pushButton_vrenew.setObjectName("pushButton_vrenew")
479 | self.horizontalLayout_11.addWidget(self.pushButton_vrenew)
480 | self.gridLayout_5.addWidget(self.widget_2, 0, 0, 1, 1)
481 | self.gridLayout_4.addWidget(self.widget, 0, 0, 1, 1)
482 | self.tabWidget.addTab(self.tab_2, "")
483 | self.tab_3 = QtWidgets.QWidget()
484 | self.tab_3.setObjectName("tab_3")
485 | self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.tab_3)
486 | self.horizontalLayout_15.setObjectName("horizontalLayout_15")
487 | self.widget_6 = QtWidgets.QWidget(self.tab_3)
488 | self.widget_6.setObjectName("widget_6")
489 | self.gridLayout_6 = QtWidgets.QGridLayout(self.widget_6)
490 | self.gridLayout_6.setContentsMargins(0, 0, 0, 0)
491 | self.gridLayout_6.setSpacing(0)
492 | self.gridLayout_6.setObjectName("gridLayout_6")
493 | self.listWidget_article = QtWidgets.QListWidget(self.widget_6)
494 | self.listWidget_article.setStyleSheet("QListWidget{background:transparent;border:0px solid grey;margin:10px;}")
495 | self.listWidget_article.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
496 | self.listWidget_article.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
497 | self.listWidget_article.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
498 | self.listWidget_article.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
499 | self.listWidget_article.setViewMode(QtWidgets.QListView.ListMode)
500 | self.listWidget_article.setObjectName("listWidget_article")
501 | self.gridLayout_6.addWidget(self.listWidget_article, 1, 0, 1, 1)
502 | self.widget_7 = QtWidgets.QWidget(self.widget_6)
503 | self.widget_7.setObjectName("widget_7")
504 | self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.widget_7)
505 | self.horizontalLayout_12.setContentsMargins(0, 0, 0, 0)
506 | self.horizontalLayout_12.setSpacing(0)
507 | self.horizontalLayout_12.setObjectName("horizontalLayout_12")
508 | self.label_atot = QtWidgets.QLabel(self.widget_7)
509 | font = QtGui.QFont()
510 | font.setFamily("微软雅黑")
511 | self.label_atot.setFont(font)
512 | self.label_atot.setText("")
513 | self.label_atot.setObjectName("label_atot")
514 | self.horizontalLayout_12.addWidget(self.label_atot)
515 | spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
516 | self.horizontalLayout_12.addItem(spacerItem3)
517 | self.pushButton_arenew = QtWidgets.QPushButton(self.widget_7)
518 | self.pushButton_arenew.setMinimumSize(QtCore.QSize(30, 30))
519 | self.pushButton_arenew.setMaximumSize(QtCore.QSize(100, 30))
520 | self.pushButton_arenew.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(240,245,255,0.8);}")
521 | self.pushButton_arenew.setText("")
522 | self.pushButton_arenew.setObjectName("pushButton_arenew")
523 | self.horizontalLayout_12.addWidget(self.pushButton_arenew)
524 | self.gridLayout_6.addWidget(self.widget_7, 0, 0, 1, 1)
525 | self.horizontalLayout_15.addWidget(self.widget_6)
526 | self.tabWidget.addTab(self.tab_3, "")
527 | self.tab_4 = QtWidgets.QWidget()
528 | self.tab_4.setObjectName("tab_4")
529 | self.horizontalLayout_18 = QtWidgets.QHBoxLayout(self.tab_4)
530 | self.horizontalLayout_18.setObjectName("horizontalLayout_18")
531 | self.widget_8 = QtWidgets.QWidget(self.tab_4)
532 | self.widget_8.setObjectName("widget_8")
533 | self.gridLayout_7 = QtWidgets.QGridLayout(self.widget_8)
534 | self.gridLayout_7.setContentsMargins(0, 0, 0, 0)
535 | self.gridLayout_7.setSpacing(0)
536 | self.gridLayout_7.setObjectName("gridLayout_7")
537 | self.listWidget_reply = QtWidgets.QListWidget(self.widget_8)
538 | self.listWidget_reply.setStyleSheet("QListWidget{background:transparent;border:0px solid grey;margin:10px;}")
539 | self.listWidget_reply.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
540 | self.listWidget_reply.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
541 | self.listWidget_reply.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
542 | self.listWidget_reply.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
543 | self.listWidget_reply.setViewMode(QtWidgets.QListView.ListMode)
544 | self.listWidget_reply.setObjectName("listWidget_reply")
545 | self.gridLayout_7.addWidget(self.listWidget_reply, 1, 0, 1, 1)
546 | self.widget_10 = QtWidgets.QWidget(self.widget_8)
547 | self.widget_10.setObjectName("widget_10")
548 | self.horizontalLayout_17 = QtWidgets.QHBoxLayout(self.widget_10)
549 | self.horizontalLayout_17.setContentsMargins(0, 0, 0, 0)
550 | self.horizontalLayout_17.setSpacing(0)
551 | self.horizontalLayout_17.setObjectName("horizontalLayout_17")
552 | self.label_rtot = QtWidgets.QLabel(self.widget_10)
553 | font = QtGui.QFont()
554 | font.setFamily("微软雅黑")
555 | self.label_rtot.setFont(font)
556 | self.label_rtot.setText("")
557 | self.label_rtot.setObjectName("label_rtot")
558 | self.horizontalLayout_17.addWidget(self.label_rtot)
559 | spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
560 | self.horizontalLayout_17.addItem(spacerItem4)
561 | self.pushButton_rrenew = QtWidgets.QPushButton(self.widget_10)
562 | self.pushButton_rrenew.setMinimumSize(QtCore.QSize(30, 30))
563 | self.pushButton_rrenew.setMaximumSize(QtCore.QSize(100, 30))
564 | self.pushButton_rrenew.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(240,245,255,0.8);}")
565 | self.pushButton_rrenew.setText("")
566 | self.pushButton_rrenew.setObjectName("pushButton_rrenew")
567 | self.horizontalLayout_17.addWidget(self.pushButton_rrenew)
568 | self.gridLayout_7.addWidget(self.widget_10, 0, 0, 1, 1)
569 | self.horizontalLayout_18.addWidget(self.widget_8)
570 | self.tabWidget.addTab(self.tab_4, "")
571 | self.tab = QtWidgets.QWidget()
572 | self.tab.setObjectName("tab")
573 | self.horizontalLayout_25 = QtWidgets.QHBoxLayout(self.tab)
574 | self.horizontalLayout_25.setObjectName("horizontalLayout_25")
575 | self.widget_17 = QtWidgets.QWidget(self.tab)
576 | self.widget_17.setObjectName("widget_17")
577 | self.gridLayout_12 = QtWidgets.QGridLayout(self.widget_17)
578 | self.gridLayout_12.setContentsMargins(0, 0, 0, 0)
579 | self.gridLayout_12.setSpacing(0)
580 | self.gridLayout_12.setObjectName("gridLayout_12")
581 | self.listWidget_danmaku = QtWidgets.QListWidget(self.widget_17)
582 | self.listWidget_danmaku.setStyleSheet("QListWidget{background:transparent;border:0px solid grey;margin:10px;}")
583 | self.listWidget_danmaku.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
584 | self.listWidget_danmaku.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
585 | self.listWidget_danmaku.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
586 | self.listWidget_danmaku.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
587 | self.listWidget_danmaku.setViewMode(QtWidgets.QListView.ListMode)
588 | self.listWidget_danmaku.setObjectName("listWidget_danmaku")
589 | self.gridLayout_12.addWidget(self.listWidget_danmaku, 1, 0, 1, 1)
590 | self.widget_18 = QtWidgets.QWidget(self.widget_17)
591 | self.widget_18.setObjectName("widget_18")
592 | self.horizontalLayout_24 = QtWidgets.QHBoxLayout(self.widget_18)
593 | self.horizontalLayout_24.setContentsMargins(0, 0, 0, 0)
594 | self.horizontalLayout_24.setSpacing(0)
595 | self.horizontalLayout_24.setObjectName("horizontalLayout_24")
596 | self.label_dtot = QtWidgets.QLabel(self.widget_18)
597 | font = QtGui.QFont()
598 | font.setFamily("微软雅黑")
599 | self.label_dtot.setFont(font)
600 | self.label_dtot.setText("")
601 | self.label_dtot.setObjectName("label_dtot")
602 | self.horizontalLayout_24.addWidget(self.label_dtot)
603 | spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
604 | self.horizontalLayout_24.addItem(spacerItem5)
605 | self.pushButton_drenew = QtWidgets.QPushButton(self.widget_18)
606 | self.pushButton_drenew.setMinimumSize(QtCore.QSize(30, 30))
607 | self.pushButton_drenew.setMaximumSize(QtCore.QSize(100, 30))
608 | self.pushButton_drenew.setStyleSheet("QPushButton{background:Transparent;border:0px solid grey;}QPushButton:hover{background-color:rgba(240,245,255,0.8);}")
609 | self.pushButton_drenew.setText("")
610 | self.pushButton_drenew.setObjectName("pushButton_drenew")
611 | self.horizontalLayout_24.addWidget(self.pushButton_drenew)
612 | self.gridLayout_12.addWidget(self.widget_18, 0, 0, 1, 1)
613 | self.horizontalLayout_25.addWidget(self.widget_17)
614 | self.tabWidget.addTab(self.tab, "")
615 | self.gridLayout_3.addWidget(self.tabWidget, 0, 0, 1, 1)
616 | self.horizontalLayout_2.addWidget(self.widget_right)
617 | self.horizontalLayout_2.setStretch(0, 1)
618 | self.horizontalLayout_2.setStretch(1, 4)
619 | self.gridLayout_2.addWidget(self.widget_down, 1, 0, 1, 1)
620 | self.gridLayout.addWidget(self.widget_main, 0, 0, 1, 1)
621 | MainWindow.setCentralWidget(self.centralwidget)
622 | self.menubar = QtWidgets.QMenuBar(MainWindow)
623 | self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 26))
624 | self.menubar.setObjectName("menubar")
625 | MainWindow.setMenuBar(self.menubar)
626 |
627 | self.retranslateUi(MainWindow)
628 | self.tabWidget.setCurrentIndex(0)
629 | QtCore.QMetaObject.connectSlotsByName(MainWindow)
630 |
631 | def retranslateUi(self, MainWindow):
632 | _translate = QtCore.QCoreApplication.translate
633 | MainWindow.setWindowTitle(_translate("MainWindow", "哔哩哔哩UP主助手"))
634 | self.label_face.setToolTip(_translate("MainWindow", "头像
"))
635 | self.pushButton_nickname.setToolTip(_translate("MainWindow", "点击打开个人主页
"))
636 | self.pushButton_notify.setText(_translate("MainWindow", "暂无通知消息"))
637 | self.pushButton_feedback.setToolTip(_translate("MainWindow", "反馈与建议
"))
638 | self.pushButton_min.setToolTip(_translate("MainWindow", "最小化
"))
639 | self.pushButton_max.setToolTip(_translate("MainWindow", "窗口最大化
"))
640 | self.pushButton_close.setToolTip(_translate("MainWindow", "关闭
"))
641 | self.label_level.setText(_translate("MainWindow", "等级"))
642 | self.label_exp.setText(_translate("MainWindow", "0/∞"))
643 | self.pushButton_coin.setText(_translate("MainWindow", "硬币:"))
644 | self.pushButton_balance.setText(_translate("MainWindow", "电池:"))
645 | self.label_3.setText(_translate("MainWindow", "电磁力"))
646 | self.label_creative.setText(_translate("MainWindow", "创作力\n"
647 | "0"))
648 | self.label_influence.setText(_translate("MainWindow", "影响力\n"
649 | "0"))
650 | self.label_credit.setText(_translate("MainWindow", "信用分\n"
651 | "0"))
652 | self.label.setText(_translate("MainWindow", "视频稿件"))
653 | self.label_follower.setText(_translate("MainWindow", "粉丝\n"
654 | "0"))
655 | self.label_view.setText(_translate("MainWindow", "播放\n"
656 | "0"))
657 | self.label_like.setText(_translate("MainWindow", "点赞\n"
658 | "0"))
659 | self.label_coin.setText(_translate("MainWindow", "投币\n"
660 | "0"))
661 | self.label_reply.setText(_translate("MainWindow", "评论\n"
662 | "0"))
663 | self.label_danmaku.setText(_translate("MainWindow", "弹幕\n"
664 | "0"))
665 | self.label_share.setText(_translate("MainWindow", "分享\n"
666 | "0"))
667 | self.label_favorite.setText(_translate("MainWindow", "收藏\n"
668 | "0"))
669 | self.label_2.setText(_translate("MainWindow", "专栏文章"))
670 | self.label_artview.setText(_translate("MainWindow", "阅读量\n"
671 | "0"))
672 | self.label_artlike.setText(_translate("MainWindow", "点赞\n"
673 | "0"))
674 | self.label_artcoin.setText(_translate("MainWindow", "投币\n"
675 | "0"))
676 | self.label_artreply.setText(_translate("MainWindow", "评论\n"
677 | "0"))
678 | self.label_artshare.setText(_translate("MainWindow", "分享\n"
679 | "0"))
680 | self.label_artfav.setText(_translate("MainWindow", "收藏\n"
681 | "0"))
682 | self.pushButton_vrenew.setToolTip(_translate("MainWindow", "刷新
"))
683 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "视频稿件"))
684 | self.pushButton_arenew.setToolTip(_translate("MainWindow", "刷新
"))
685 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "专栏文章"))
686 | self.pushButton_rrenew.setToolTip(_translate("MainWindow", "刷新
"))
687 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "评论管理"))
688 | self.pushButton_drenew.setToolTip(_translate("MainWindow", "刷新
"))
689 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "弹幕管理"))
690 | import resources_rc
691 |
--------------------------------------------------------------------------------