Skip to content

Commit 9e4d5db

Browse files
committed
✨ 增加添加与取消追漫
1 parent 2afc0b3 commit 9e4d5db

File tree

4 files changed

+173
-4
lines changed

4 files changed

+173
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@
105105
- 更多开发进度详情请看 [**项目清单表**](https://github.com/users/Zeal-L/projects/2/views/1)
106106
- **PS: 也欢迎小伙伴们多多的在Issues里提意见,不管是Bug还是操作逻辑,界面优化等等作者统统笑纳~**
107107
- 🟦 缓存更多资源,减少网络请求
108-
- 🟦 添加我的追漫界面,以及追漫功能
109108
- 🟦 对于有特典的漫画,提供特典下载界面
110109
- **已解决**
111110
-~~添加二维码扫码登入功能~~
@@ -116,6 +115,7 @@
116115
-~~除pdf以外添加不同的保存选项如 7z 或者 基本的文件夹图片~~
117116
-~~启动程序时多线程加载本地库存,避免用户等待太久~~
118117
-~~给打包好的程序添加版本号版权等属性信息~~
118+
-~~添加我的追漫界面,以及追漫功能~~
119119

120120
## 🏗️ 本地构建 / 编译
121121

src/Comic.py

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
MAX_RETRY_SMALL,
1818
RETRY_WAIT_EX,
1919
TIMEOUT_SMALL,
20+
__user_agent__,
2021
isCheckSumValid,
2122
logger,
2223
myStrFilter,
@@ -190,6 +191,14 @@ def getNumDownloaded(self) -> int:
190191
return self.num_downloaded
191192

192193
def getMyFavoriteComic(mainGUI: MainGUI) -> list[dict]:
194+
"""获取我的追漫列表
195+
196+
Args:
197+
mainGUI (MainGUI): 主页面
198+
199+
Returns:
200+
list[dict]: 我的追漫漫画详情列表
201+
"""
193202
favorite_list_url = "https://manga.bilibili.com/twirp/bookshelf.v1.Bookshelf/ListFavorite?device=pc&platform=web"
194203
headers = {
195204
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
@@ -236,4 +245,114 @@ def _() -> dict:
236245
logger.error(f"获取我的追漫多次后失败!\n{e}")
237246
logger.exception(e)
238247
return []
239-
248+
249+
def addComicToFavorite(mainGUI: MainGUI, comic_id: int) -> bool:
250+
"""添加漫画到我的追漫列表
251+
252+
Args:
253+
mainGUI (MainGUI): 主页面
254+
comic_id (int): 漫画ID
255+
256+
Returns:
257+
bool: 是否请求成功
258+
"""
259+
add_favorite_url = "https://manga.bilibili.com/twirp/bookshelf.v1.Bookshelf/AddFavorite?device=pc&platform=web"
260+
headers = {
261+
"user-agent": __user_agent__,
262+
"origin": "https://manga.bilibili.com",
263+
"referer": f"https://manga.bilibili.com/detail/mc{comic_id}",
264+
"cookie": f"SESSDATA={mainGUI.getConfig('cookie')}",
265+
}
266+
payload = {"comic_ids": str(comic_id)}
267+
268+
@retry(
269+
stop_max_delay=MAX_RETRY_SMALL - 5000,
270+
wait_exponential_multiplier=RETRY_WAIT_EX,
271+
)
272+
def _() -> None:
273+
try:
274+
res = requests.post(
275+
add_favorite_url,
276+
headers=headers,
277+
data=payload,
278+
timeout=TIMEOUT_SMALL - 3,
279+
)
280+
except requests.RequestException as e:
281+
logger.warning(f"添加到我的追漫列表失败! 重试中...\n{e}")
282+
raise e
283+
print(res.json())
284+
if res.status_code != 200 or res.json().get("code") != 0:
285+
reason = res.reason
286+
status_code = res.status_code
287+
if res.status_code != 200:
288+
reason = res.json().get("msg")
289+
status_code = res.json().get("code")
290+
291+
logger.warning(
292+
f"添加到我的追漫列表失败! 状态码:{status_code}, 理由: {reason} 重试中..."
293+
)
294+
raise requests.HTTPError()
295+
296+
try:
297+
_()
298+
return True
299+
except requests.RequestException as e:
300+
logger.error(f"添加到我的追漫列表多次后失败!\n{e}")
301+
logger.exception(e)
302+
return False
303+
304+
def delComicFromFavorite(mainGUI: MainGUI, comic_id: int) -> bool:
305+
"""从我的追漫列表移除
306+
307+
Args:
308+
mainGUI (MainGUI): 主页面
309+
comic_id (int): 漫画ID
310+
311+
Returns:
312+
bool: 是否请求成功
313+
"""
314+
del_favorite_url = "https://manga.bilibili.com/twirp/bookshelf.v1.Bookshelf/DeleteFavorite?device=pc&platform=web"
315+
headers = {
316+
"user-agent": __user_agent__,
317+
"origin": "https://manga.bilibili.com",
318+
"referer": f"https://manga.bilibili.com/detail/mc{comic_id}",
319+
"cookie": f"SESSDATA={mainGUI.getConfig('cookie')}",
320+
}
321+
payload = {"comic_ids": str(comic_id)}
322+
323+
@retry(
324+
stop_max_delay=MAX_RETRY_SMALL - 5000,
325+
wait_exponential_multiplier=RETRY_WAIT_EX,
326+
)
327+
def _() -> None:
328+
try:
329+
res = requests.post(
330+
del_favorite_url,
331+
headers=headers,
332+
data=payload,
333+
timeout=TIMEOUT_SMALL - 3,
334+
)
335+
except requests.RequestException as e:
336+
logger.warning(f"从我的追漫列表中移除失败! 重试中...\n{e}")
337+
raise e
338+
print(res.json())
339+
if res.status_code != 200 or res.json().get("code") != 0:
340+
reason = res.reason
341+
status_code = res.status_code
342+
if res.status_code != 200:
343+
reason = res.json().get("msg")
344+
status_code = res.json().get("code")
345+
346+
logger.warning(
347+
f"从我的追漫列表中移除失败! 状态码:{status_code}, 理由: {reason} 重试中..."
348+
)
349+
raise requests.HTTPError()
350+
351+
try:
352+
_()
353+
return True
354+
except requests.RequestException as e:
355+
logger.error(f"从我的追漫列表中移除多次后失败!\n{e}")
356+
logger.exception(e)
357+
return False
358+

src/Utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
__author__ = "Zeal L"
3333
__copyright__ = "Copyright (C) 2023-2024 Zeal L"
3434
__main_window_title__ = f"哔哩哔哩漫画下载器 v{__version__}"
35+
__user_agent__ = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
3536

3637
############################################################
3738
# 配置全局网络请求的 timeout 以及 max retry

src/ui/MangaUI.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
)
2525

2626
from src.BiliPlus import BiliPlusComic
27-
from src.Comic import Comic, getMyFavoriteComic
27+
from src.Comic import Comic, getMyFavoriteComic, addComicToFavorite, delComicFromFavorite
2828
from src.SearchComic import SearchComic
2929
from src.Utils import logger, openFileOrDir
3030

@@ -110,6 +110,35 @@ def mangaSearch(self) -> None:
110110
def updateSearchResult(self) -> None:
111111
self.mainGUI.listWidget_manga_search.clear()
112112
self.mainGUI.label_manga_search.setText(f"{len(self.search_info)}条结果")
113+
self.mainGUI.listWidget_manga_search.setContextMenuPolicy(Qt.CustomContextMenu)
114+
115+
116+
# ?###########################################################
117+
# ? 绑定右键漫画追漫事件
118+
def myMenu_addToFavorite(widget: QWidget, pos: QPoint) -> None:
119+
item = widget.itemAt(pos)
120+
if not item:
121+
return
122+
if not self.mainGUI.getConfig("cookie"):
123+
QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
124+
return
125+
126+
def _():
127+
info = item.data(Qt.UserRole)
128+
res = addComicToFavorite(self.mainGUI, info["id"])
129+
if res:
130+
self.mainGUI.signal_info_box.emit(f"追漫《{info["title"]}》成功!")
131+
else:
132+
self.mainGUI.signal_info_box.emit(f"追漫《{info["title"]}》失败!详情请查看日志文件!")
133+
134+
menu = QMenu()
135+
menu.addAction("添加到我的追漫", lambda: self.executor.submit(_))
136+
menu.exec_(widget.mapToGlobal(pos))
137+
138+
self.mainGUI.listWidget_manga_search.customContextMenuRequested.connect(
139+
partial(myMenu_addToFavorite, self.mainGUI.listWidget_manga_search)
140+
)
141+
113142
for item in self.search_info:
114143
# ?###########################################################
115144
# ? 替换爬取信息里的html标签
@@ -121,13 +150,15 @@ def updateSearchResult(self) -> None:
121150
)
122151
# ?###########################################################
123152
temp = QListWidgetItem()
153+
temp.setData(Qt.UserRole, item)
124154
self.mainGUI.listWidget_manga_search.addItem(temp)
125155
self.mainGUI.listWidget_manga_search.setItemWidget(
126156
temp,
127157
QLabel(
128158
f"{item['title']} by <span style='color:blue'>{item['author_name'][0]}</span>"
129159
),
130160
)
161+
131162
self.mainGUI.pushButton_manga_search_name.setEnabled(True)
132163

133164
############################################################
@@ -487,6 +518,23 @@ def _(_event: QEvent, widget: QWidget, comic: Comic) -> None:
487518
widget.mouseDoubleClickEvent = partial(self.updateComicInfoEvent, comic)
488519
widget.setLayout(h_Layout_myFavorite)
489520

521+
# ?###########################################################
522+
# ? 绑定右键取消追漫功能
523+
def myMenu_removeFavorite(widget: QWidget, pos: QPoint) -> None:
524+
def _():
525+
res = delComicFromFavorite(self.mainGUI, data["comic_id"])
526+
if res:
527+
self.mainGUI.signal_info_box.emit(f"追漫《{data["title"]}》成功!")
528+
else:
529+
self.mainGUI.signal_info_box.emit(f"追漫《{data["title"]}》失败!详情请查看日志文件!")
530+
531+
menu = QMenu()
532+
menu.addAction("取消追漫", lambda: self.executor.submit(_))
533+
menu.exec_(widget.mapToGlobal(pos))
534+
535+
widget.setContextMenuPolicy(Qt.CustomContextMenu)
536+
widget.customContextMenuRequested.connect(partial(myMenu_removeFavorite, widget))
537+
490538
# ? 按照标题的拼音顺序插入我的库存列表
491539
if self.mainGUI.v_Layout_myFavorite.count() == 0:
492540
self.mainGUI.v_Layout_myFavorite.addWidget(widget)
@@ -515,7 +563,8 @@ def _(_event: QEvent, widget: QWidget, comic: Comic) -> None:
515563
self.mainGUI.signal_warning_box.emit(
516564
f"未获取到我的追漫列表!\n请检查Cookie、网络连接或者重启软件\n更多详细信息请查看日志文件, 或联系开发者!"
517565
)
518-
self.mainGUI.signal_info_box.emit("同步完成!")
566+
else:
567+
self.mainGUI.signal_info_box.emit("同步完成!")
519568

520569
############################################################
521570
# 以下三个函数是为了获取漫画信息详情

0 commit comments

Comments
 (0)