├── .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 | ![软件运行主界面](https://toodo.fun/funs/tools/f2l/files/d41d8cd98f00b204e9800998ecf8427e5e9094555d7e4.png "软件运行主界面") 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 | --------------------------------------------------------------------------------