podflow 2025.1.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. Podflow/__init__.py +137 -0
  2. Podflow/basic/__init__.py +2 -0
  3. Podflow/basic/file_save.py +21 -0
  4. Podflow/basic/folder_build.py +16 -0
  5. Podflow/basic/get_duration.py +18 -0
  6. Podflow/basic/get_file_list.py +57 -0
  7. Podflow/basic/get_html_dict.py +30 -0
  8. Podflow/basic/http_client.py +75 -0
  9. Podflow/basic/list_merge_tidy.py +15 -0
  10. Podflow/basic/qr_code.py +55 -0
  11. Podflow/basic/split_dict.py +14 -0
  12. Podflow/basic/time_format.py +16 -0
  13. Podflow/basic/time_stamp.py +61 -0
  14. Podflow/basic/vary_replace.py +11 -0
  15. Podflow/basic/write_log.py +43 -0
  16. Podflow/bilibili/__init__.py +2 -0
  17. Podflow/bilibili/build.py +201 -0
  18. Podflow/bilibili/get.py +477 -0
  19. Podflow/bilibili/login.py +307 -0
  20. Podflow/config/__init__.py +2 -0
  21. Podflow/config/build_original.py +41 -0
  22. Podflow/config/channge_icon.py +163 -0
  23. Podflow/config/correct_channelid.py +230 -0
  24. Podflow/config/correct_config.py +103 -0
  25. Podflow/config/get_channelid.py +22 -0
  26. Podflow/config/get_channelid_id.py +21 -0
  27. Podflow/config/get_config.py +34 -0
  28. Podflow/download/__init__.py +2 -0
  29. Podflow/download/convert_bytes.py +18 -0
  30. Podflow/download/delete_part.py +20 -0
  31. Podflow/download/dl_aideo_video.py +307 -0
  32. Podflow/download/show_progress.py +46 -0
  33. Podflow/download/wait_animation.py +34 -0
  34. Podflow/download/youtube_and_bilibili_download.py +30 -0
  35. Podflow/ffmpeg_judge.py +45 -0
  36. Podflow/httpfs/__init__.py +2 -0
  37. Podflow/httpfs/app_bottle.py +212 -0
  38. Podflow/httpfs/port_judge.py +21 -0
  39. Podflow/main.py +248 -0
  40. Podflow/makeup/__init__.py +2 -0
  41. Podflow/makeup/del_makeup_yt_format_fail.py +19 -0
  42. Podflow/makeup/make_up_file.py +51 -0
  43. Podflow/makeup/make_up_file_format_mod.py +96 -0
  44. Podflow/makeup/make_up_file_mod.py +30 -0
  45. Podflow/message/__init__.py +2 -0
  46. Podflow/message/backup_zip_save.py +45 -0
  47. Podflow/message/create_main_rss.py +44 -0
  48. Podflow/message/display_qrcode_and_url.py +36 -0
  49. Podflow/message/fail_message_initialize.py +165 -0
  50. Podflow/message/format_time.py +27 -0
  51. Podflow/message/get_original_rss.py +65 -0
  52. Podflow/message/get_video_format.py +111 -0
  53. Podflow/message/get_video_format_multithread.py +42 -0
  54. Podflow/message/get_youtube_and_bilibili_video_format.py +87 -0
  55. Podflow/message/media_format.py +195 -0
  56. Podflow/message/original_rss_fail_print.py +15 -0
  57. Podflow/message/rss_create_hash.py +26 -0
  58. Podflow/message/title_correction.py +30 -0
  59. Podflow/message/update_information_display.py +72 -0
  60. Podflow/message/update_youtube_bilibili_rss.py +116 -0
  61. Podflow/message/want_retry.py +21 -0
  62. Podflow/message/xml_item.py +83 -0
  63. Podflow/message/xml_original_item.py +92 -0
  64. Podflow/message/xml_rss.py +46 -0
  65. Podflow/netscape/__init__.py +2 -0
  66. Podflow/netscape/bulid_netscape.py +44 -0
  67. Podflow/netscape/get_cookie_dict.py +21 -0
  68. Podflow/parse_arguments.py +80 -0
  69. Podflow/remove/__init__.py +2 -0
  70. Podflow/remove/remove_dir.py +33 -0
  71. Podflow/remove/remove_file.py +23 -0
  72. Podflow/youtube/__init__.py +2 -0
  73. Podflow/youtube/build.py +287 -0
  74. Podflow/youtube/get.py +376 -0
  75. Podflow/youtube/login.py +39 -0
  76. podflow-2025.1.26.dist-info/METADATA +214 -0
  77. podflow-2025.1.26.dist-info/RECORD +80 -0
  78. podflow-2025.1.26.dist-info/WHEEL +5 -0
  79. podflow-2025.1.26.dist-info/entry_points.txt +6 -0
  80. podflow-2025.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,201 @@
1
+ # Podflow/bilibili/build.py
2
+ # coding: utf-8
3
+
4
+ import re
5
+ import html
6
+ import contextlib
7
+ from datetime import datetime, timezone
8
+ from Podflow import gVar
9
+ from Podflow.message.xml_rss import xml_rss
10
+ from Podflow.basic.file_save import file_save
11
+ from Podflow.message.xml_item import xml_item
12
+ from Podflow.bilibili.get import get_bilibili_cid
13
+ from Podflow.message.format_time import format_time
14
+ from Podflow.basic.get_file_list import get_file_list
15
+ from Podflow.message.xml_original_item import xml_original_item
16
+
17
+
18
+ def get_items_list(
19
+ guid,
20
+ item,
21
+ channelid_title,
22
+ title_change,
23
+ items_counts,
24
+ output_dir,
25
+ items_list,
26
+ ):
27
+ pubDate = datetime.fromtimestamp(item["created"], timezone.utc).strftime(
28
+ "%Y-%m-%dT%H:%M:%S%z"
29
+ )
30
+ if guid in items_counts:
31
+ guid_parts = []
32
+ guid_edgeinfos = []
33
+ if "cid" in item:
34
+ pass
35
+ elif "part" in item:
36
+ guid_parts = item["part"]
37
+ elif "edgeinfo" in item:
38
+ guid_edgeinfos = item["edgeinfo"]
39
+ elif "error" in item:
40
+ pass # 需要添加错误处理
41
+ else:
42
+ guid_cid, guid_type, _ = get_bilibili_cid(
43
+ guid, gVar.channelid_bilibili_ids[output_dir]
44
+ )
45
+ if guid_type == "part":
46
+ guid_parts = guid_cid
47
+ elif guid_type == "edgeinfo":
48
+ guid_edgeinfos = guid_cid
49
+ if guid_parts and items_counts[guid] == len(guid_parts):
50
+ for guid_part in guid_parts:
51
+ guid_part_text = f"{item['title']} Part{guid_part['page']:0{len(str(len(guid_parts)))}}"
52
+ if item["title"] != guid_part["part"]:
53
+ guid_part_text += f" {guid_part['part']}"
54
+ xml_item_text = xml_item(
55
+ f"{item['bvid']}_p{guid_part['page']}",
56
+ output_dir,
57
+ f"https://www.bilibili.com/video/{guid}?p={guid_part['page']}",
58
+ channelid_title,
59
+ html.escape(guid_part_text),
60
+ html.escape(re.sub(r"\n+", "\n", item["description"])),
61
+ format_time(pubDate),
62
+ guid_part["first_frame"],
63
+ title_change,
64
+ )
65
+ items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
66
+ elif guid_edgeinfos and items_counts[guid] == len(guid_edgeinfos):
67
+ cid_edgeinfos = {
68
+ guid_edgeinfo["cid"]: guid_edgeinfo["title"]
69
+ for guid_edgeinfo in guid_edgeinfos
70
+ }
71
+ for guid_edgeinfo in guid_edgeinfos:
72
+ if guid_edgeinfo["options"]:
73
+ description = (
74
+ "〖互动视频〗\n"
75
+ + "\n".join(
76
+ f"{option}\t✪{cid_edgeinfos[option_cid]}"
77
+ for option, option_cid in zip(
78
+ guid_edgeinfo["options"], guid_edgeinfo["options_cid"]
79
+ )
80
+ )
81
+ + "\n------------------------------------------------\n"
82
+ + item["description"]
83
+ )
84
+ else:
85
+ description = (
86
+ "〖互动视频〗\nTHE END."
87
+ + "\n------------------------------------------------\n"
88
+ + item["description"]
89
+ )
90
+ guid_edgeinfo_text = f"{item['title']} Part{guid_edgeinfo['num']:0{len(str(len(guid_edgeinfos)))}} {guid_edgeinfo['title']}"
91
+ xml_item_text = xml_item(
92
+ f"{item['bvid']}_{guid_edgeinfo['cid']}",
93
+ output_dir,
94
+ f"https://www.bilibili.com/video/{guid}",
95
+ channelid_title,
96
+ html.escape(guid_edgeinfo_text),
97
+ html.escape(re.sub(r"\n+", "\n", description)),
98
+ format_time(pubDate),
99
+ guid_edgeinfo["first_frame"],
100
+ title_change,
101
+ )
102
+ items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
103
+ else:
104
+ xml_item_text = xml_item(
105
+ item["bvid"],
106
+ output_dir,
107
+ f"https://www.bilibili.com/video/{guid}",
108
+ channelid_title,
109
+ html.escape(item["title"]),
110
+ html.escape(re.sub(r"\n+", "\n", item["description"])),
111
+ format_time(pubDate),
112
+ item["pic"],
113
+ title_change,
114
+ )
115
+ items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
116
+
117
+
118
+ # 生成哔哩哔哩对应channel的需更新的items模块
119
+ def bilibili_xml_items(output_dir):
120
+ channelid_bilibili_value = gVar.channelid_bilibili[
121
+ gVar.channelid_bilibili_ids[output_dir]
122
+ ]
123
+ content_id, items_counts = get_file_list(
124
+ output_dir, channelid_bilibili_value["media"]
125
+ )
126
+ items_list = [f"<!-- {output_dir} -->"]
127
+ entry_num = 0
128
+ original_judgment = True
129
+ channelid_title = channelid_bilibili_value["title"]
130
+ title_change = channelid_bilibili_value.get("title_change", [])
131
+ output_dir_value = gVar.channelid_bilibili_rss[output_dir]
132
+ # 最新更新
133
+ for guid in output_dir_value["content"]["list"]:
134
+ if guid not in gVar.video_id_failed and guid in content_id:
135
+ item = output_dir_value["content"]["entry"][guid]
136
+ get_items_list(
137
+ guid,
138
+ item,
139
+ channelid_title,
140
+ title_change,
141
+ items_counts,
142
+ output_dir,
143
+ items_list,
144
+ )
145
+ if item["description"] and item["description"][0] == "『":
146
+ original_judgment = False
147
+ entry_num += 1
148
+ if entry_num >= channelid_bilibili_value["update_size"]:
149
+ break
150
+ items_guid = re.findall(r"(?<=<guid>).+?(?=</guid>)", "".join(items_list))
151
+ # 存量接入
152
+ entry_count = channelid_bilibili_value["last_size"] - len(items_guid)
153
+ if gVar.xmls_original and output_dir in gVar.xmls_original and entry_count > 0:
154
+ xml_num = 0
155
+ for xml in gVar.xmls_original[output_dir].split(f"<!-- {output_dir} -->"):
156
+ xml_guid = re.search(r"(?<=<guid>).+(?=</guid>)", xml)
157
+ if (
158
+ xml_guid
159
+ and xml_guid.group() not in items_guid
160
+ and xml_guid.group() not in gVar.video_id_failed
161
+ ):
162
+ items_list.append(
163
+ f"{xml_original_item(xml, channelid_title, original_judgment, title_change)}<!-- {output_dir} -->"
164
+ )
165
+ xml_num += 1
166
+ if xml_num >= entry_count:
167
+ break
168
+ # 向后更新
169
+ with contextlib.suppress(KeyError):
170
+ backward = output_dir_value["backward"]
171
+ for backward_guid in backward["list"]:
172
+ if (
173
+ backward_guid not in gVar.video_id_failed
174
+ and backward_guid in content_id
175
+ ):
176
+ backward_item = backward["entry"][backward_guid]
177
+ get_items_list(
178
+ backward_guid,
179
+ backward_item,
180
+ channelid_title,
181
+ title_change,
182
+ items_counts,
183
+ output_dir,
184
+ items_list,
185
+ )
186
+ # 生成对应xml
187
+ description = html.escape(output_dir_value["content"]["sign"])
188
+ icon = output_dir_value["content"]["face"]
189
+ category = gVar.config["category"]
190
+ title = html.escape(output_dir_value["content"]["name"])
191
+ link = f"https://space.bilibili.com/{output_dir}"
192
+ items = "".join(items_list)
193
+ items = f"""<!-- {{{output_dir}}} -->
194
+ {items}
195
+ <!-- {{{output_dir}}} -->"""
196
+ file_save(
197
+ xml_rss(title, link, description, category, icon, items),
198
+ f"{output_dir}.xml",
199
+ "channel_rss",
200
+ )
201
+ return items
@@ -0,0 +1,477 @@
1
+ # Podflow/bilibili/get.py
2
+ # coding: utf-8
3
+
4
+ import contextlib
5
+ import re
6
+ import json
7
+ import math
8
+ import time
9
+ import urllib
10
+ import threading
11
+ from hashlib import md5
12
+ from functools import reduce
13
+ from Podflow import gVar
14
+ from Podflow.basic.http_client import http_client
15
+ from Podflow.basic.get_file_list import get_file_list
16
+ from Podflow.basic.list_merge_tidy import list_merge_tidy
17
+
18
+
19
+ # WBI签名模块
20
+ def WBI_signature(params={}, img_key="", sub_key=""):
21
+ mixinKeyEncTab = [
22
+ 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
23
+ 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
24
+ 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
25
+ 36, 20, 34, 44, 52,
26
+ ]
27
+
28
+ def getMixinKey(orig: str):
29
+ "对 imgKey 和 subKey 进行字符顺序打乱编码"
30
+ return reduce(lambda s, i: s + orig[i], mixinKeyEncTab, "")[:32]
31
+
32
+ def encWbi(params: dict, img_key: str, sub_key: str):
33
+ "为请求参数进行 wbi 签名"
34
+ mixin_key = getMixinKey(img_key + sub_key)
35
+ curr_time = round(time.time())
36
+ params["wts"] = curr_time # 添加 wts 字段
37
+ params = dict(sorted(params.items())) # 按照 key 重排参数
38
+ # 过滤 value 中的 "!'()*" 字符
39
+ params = {
40
+ k: "".join(filter(lambda chr: chr not in "!'()*", str(v)))
41
+ for k, v in params.items()
42
+ }
43
+ query = urllib.parse.urlencode(params) # 序列化参数
44
+ wbi_sign = md5((query + mixin_key).encode()).hexdigest() # 计算 w_rid
45
+ params["w_rid"] = wbi_sign
46
+ return params
47
+
48
+ return encWbi(params=params, img_key=img_key, sub_key=sub_key)
49
+
50
+
51
+ # 获取bv的cid(包含分P或互动视频)模块
52
+ def get_bilibili_cid(bvid, bilibili_value):
53
+ bvid_part = [] # 用于存储每个分P或互动视频的信息
54
+ bvid_cid = [] # 存储已经获取的cid
55
+ bvid_cid_choices = [] # 存储互动视频的选择
56
+ code_num = {
57
+ 0: "成功",
58
+ -400: "请求错误",
59
+ -403: "权限不足",
60
+ -404: "无视频",
61
+ 62002: "稿件不可见",
62
+ 62004: "稿件审核中",
63
+ 62012: "仅UP主自己可见",
64
+ }
65
+
66
+ # 获取互动视频信息模块
67
+ def get_edge_info(bvid, bilibili_value, graph_version, edge_id):
68
+ if edgeinfo_v2_response := http_client(
69
+ "https://api.bilibili.com/x/stein/edgeinfo_v2",
70
+ f"{bilibili_value}|{bvid}",
71
+ 10,
72
+ 4,
73
+ True,
74
+ None,
75
+ {"bvid": bvid, "graph_version": graph_version, "edge_id": edge_id},
76
+ ):
77
+ edgeinfo_v2 = edgeinfo_v2_response.json()
78
+ return edgeinfo_v2["data"]
79
+
80
+ # 获取选择项信息模块
81
+ def get_choices(data):
82
+ options = []
83
+ options_cid = []
84
+ if "questions" in data["edges"]:
85
+ for question in data["edges"]["questions"]:
86
+ if "choices" in question:
87
+ for choice in question["choices"]:
88
+ if (
89
+ choice["cid"] not in bvid_cid
90
+ and choice["cid"] not in bvid_cid_choices
91
+ ):
92
+ bvid_cid_choices.append(
93
+ {
94
+ "cid": choice["cid"],
95
+ "edge_id": choice["id"],
96
+ "option": choice["option"],
97
+ }
98
+ )
99
+ options.append(choice["option"])
100
+ options_cid.append(choice["cid"])
101
+ return options, options_cid
102
+
103
+ # 获取剧情图id模块
104
+ def get_graph_version(bvid, bilibili_value, cid):
105
+ graph_version = ""
106
+ if playerwbi_response := http_client(
107
+ "https://api.bilibili.com/x/player/wbi/v2",
108
+ f"{bilibili_value}|{bvid}",
109
+ 10,
110
+ 4,
111
+ True,
112
+ None,
113
+ {"cid": cid, "bvid": bvid},
114
+ ):
115
+ playerwbi = playerwbi_response.json()
116
+ playerwbi_data = playerwbi["data"]
117
+ if "interaction" in playerwbi_data:
118
+ graph_version = playerwbi["data"]["interaction"]["graph_version"]
119
+ return graph_version
120
+
121
+ # 判断媒体类型
122
+ if interface_response := http_client(
123
+ "https://api.bilibili.com/x/web-interface/wbi/view",
124
+ f"{bilibili_value}|{bvid}",
125
+ 10,
126
+ 4,
127
+ True,
128
+ gVar.bilibili_data["cookie"],
129
+ {"bvid": bvid},
130
+ ):
131
+ interface_json = interface_response.json()
132
+ code = interface_json["code"]
133
+ if code != 0:
134
+ error = code_num[code]
135
+ return error, "error", None
136
+ data = interface_json["data"]
137
+ upower = data["is_upower_exclusive"]
138
+ pages = data["pages"]
139
+ cid = data["cid"]
140
+ if len(pages) > 1:
141
+ for part in pages:
142
+ bvid_part.append(
143
+ {
144
+ "cid": part["cid"],
145
+ "page": part["page"],
146
+ "part": part["part"],
147
+ "duration": part["duration"],
148
+ "dimension": part["dimension"],
149
+ "first_frame": part["first_frame"],
150
+ }
151
+ )
152
+ bvid_part.sort(key=lambda x: x["page"], reverse=True)
153
+ return bvid_part, "part", upower
154
+ elif data["rights"]["is_stein_gate"]:
155
+ # 获取互动视频信息
156
+ if graph_version := get_graph_version(bvid, bilibili_value, cid):
157
+ data_1 = get_edge_info(bvid, bilibili_value, graph_version, "1")
158
+ for story_list in data_1["story_list"]:
159
+ if story_list["edge_id"] == 1:
160
+ story_list_1 = story_list
161
+ break
162
+ options, options_cid = get_choices(data_1)
163
+ bvid_part.append(
164
+ {
165
+ "cid": story_list_1["cid"],
166
+ "title": data_1["title"],
167
+ "edge_id": story_list_1["edge_id"],
168
+ "first_frame": f"http://i0.hdslb.com/bfs/steins-gate/{story_list_1['cid']}_screenshot.jpg",
169
+ "options": options,
170
+ "options_cid": options_cid,
171
+ "num": 1,
172
+ }
173
+ )
174
+ bvid_cid.append(story_list_1["cid"])
175
+ while bvid_cid_choices:
176
+ if bvid_cid_choices[0]["cid"] not in bvid_cid:
177
+ data = get_edge_info(
178
+ bvid,
179
+ bilibili_value,
180
+ graph_version,
181
+ bvid_cid_choices[0]["edge_id"],
182
+ )
183
+ options, options_cid = get_choices(data)
184
+ bvid_part.append(
185
+ {
186
+ "cid": bvid_cid_choices[0]["cid"],
187
+ "title": data["title"],
188
+ "edge_id": bvid_cid_choices[0]["edge_id"],
189
+ "first_frame": f"http://i0.hdslb.com/bfs/steins-gate/{bvid_cid_choices[0]['cid']}_screenshot.jpg",
190
+ "options": options,
191
+ "options_cid": options_cid,
192
+ "num": len(bvid_part) + 1,
193
+ }
194
+ )
195
+ bvid_cid.append(bvid_cid_choices[0]["cid"])
196
+ del bvid_cid_choices[0]
197
+ bvid_part.sort(key=lambda x: x["num"], reverse=True)
198
+ return bvid_part, "edgeinfo", upower
199
+ else:
200
+ return None, None, None
201
+ else:
202
+ return cid, "cid", upower
203
+ else:
204
+ return None, None, None
205
+
206
+
207
+ # 查询哔哩哔哩用户投稿视频明细模块
208
+ def get_bilibili_vlist(bilibili_key, bilibili_value, num=1, all_part_judgement=False):
209
+ bilibili_list = []
210
+ bilibili_entry = {}
211
+ if bilibili_response := http_client(
212
+ "https://api.bilibili.com/x/space/wbi/arc/search",
213
+ bilibili_value,
214
+ 10,
215
+ 4,
216
+ True,
217
+ gVar.bilibili_data["cookie"],
218
+ WBI_signature(
219
+ {
220
+ "mid": bilibili_key,
221
+ "pn": str(num),
222
+ "ps": "25",
223
+ },
224
+ gVar.bilibili_data["img_key"],
225
+ gVar.bilibili_data["sub_key"],
226
+ ),
227
+ ):
228
+ bilibili_json = bilibili_response.json()
229
+ bilibili_vlists = bilibili_json["data"]["list"]["vlist"]
230
+ for vlist in bilibili_vlists:
231
+ with contextlib.suppress(KeyError, TypeError, IndexError, ValueError):
232
+ bilibili_entry[vlist["bvid"]] = {
233
+ "aid": vlist["aid"],
234
+ "author": vlist["author"],
235
+ "bvid": vlist["bvid"],
236
+ "copyright": vlist["copyright"],
237
+ "created": vlist["created"],
238
+ "description": vlist["description"],
239
+ "is_union_video": vlist["is_union_video"],
240
+ "length": vlist["length"],
241
+ "mid": vlist["mid"],
242
+ "pic": vlist["pic"],
243
+ "title": vlist["title"],
244
+ "typeid": vlist["typeid"],
245
+ }
246
+ bilibili_list.append(vlist["bvid"])
247
+ if all_part_judgement and bilibili_list:
248
+
249
+ def all_part(bvid):
250
+ bvid_cid, bvid_type, power = get_bilibili_cid(bvid, bilibili_value)
251
+ if bvid_type:
252
+ bilibili_entry[bvid][bvid_type] = bvid_cid
253
+ bilibili_entry[bvid]["power"] = power
254
+
255
+ # 创建一个线程列表
256
+ threads = []
257
+ for bvid in bilibili_list:
258
+ thread = threading.Thread(target=all_part, args=(bvid,))
259
+ threads.append(thread)
260
+ thread.start()
261
+ # 等待所有线程完成
262
+ for thread in threads:
263
+ thread.join()
264
+ return bilibili_entry, bilibili_list
265
+
266
+
267
+ # 更新哔哩哔哩频道json模块
268
+ def bilibili_json_update(bilibili_key, bilibili_value):
269
+ bilibili_space = {}
270
+ bilibili_lists = []
271
+ bilibili_entrys = {}
272
+ if not (
273
+ bilibili_card_response := http_client(
274
+ "https://api.bilibili.com/x/web-interface/card",
275
+ bilibili_value,
276
+ 10,
277
+ 4,
278
+ True,
279
+ gVar.bilibili_data["cookie"],
280
+ {
281
+ "mid": bilibili_key,
282
+ "photo": "true",
283
+ },
284
+ )
285
+ ):
286
+ return None
287
+ bilibili_card_json = bilibili_card_response.json()
288
+ with contextlib.suppress(KeyError, TypeError, IndexError, ValueError):
289
+ if bilibili_card_json["code"] == 0:
290
+ bilibili_space = {
291
+ "mid": bilibili_card_json["data"]["card"]["mid"],
292
+ "name": bilibili_card_json["data"]["card"]["name"],
293
+ "sex": bilibili_card_json["data"]["card"]["sex"],
294
+ "face": bilibili_card_json["data"]["card"]["face"],
295
+ "spacesta": bilibili_card_json["data"]["card"]["spacesta"],
296
+ "sign": bilibili_card_json["data"]["card"]["sign"],
297
+ "Official": bilibili_card_json["data"]["card"]["Official"],
298
+ "official_verify": bilibili_card_json["data"]["card"][
299
+ "official_verify"
300
+ ],
301
+ }
302
+ else:
303
+ return bilibili_card_json["code"]
304
+ # 查询哔哩哔哩用户投稿视频明细
305
+ for num in range(math.ceil(gVar.channelid_bilibili[bilibili_value]["update_size"] / 25)):
306
+ num += 1
307
+ bilibili_entry, bilibili_list = get_bilibili_vlist(
308
+ bilibili_key,
309
+ f"{bilibili_value}第{num}页",
310
+ num,
311
+ gVar.channelid_bilibili[bilibili_value]["AllPartGet"],
312
+ )
313
+ bilibili_entrys = bilibili_entrys | bilibili_entry
314
+ bilibili_lists += bilibili_list
315
+ bilibili_space["entry"] = bilibili_entrys
316
+ bilibili_space["list"] = bilibili_lists
317
+ return bilibili_space
318
+
319
+
320
+ # 更新哔哩哔哩频道xml模块
321
+ def bilibili_rss_update(bilibili_key, bilibili_value):
322
+ # 获取已下载文件列表
323
+ bilibili_content_bvid_original = get_file_list(
324
+ bilibili_key, gVar.channelid_bilibili[bilibili_value]["media"]
325
+ )[0]
326
+ # 获取原xml中文件列表
327
+ try:
328
+ original_item = gVar.xmls_original[bilibili_key] # 尝试获取原始的xml内容
329
+ guids = list_merge_tidy(
330
+ re.findall(r"(?<=<guid>).+(?=</guid>)", original_item), [], 12
331
+ ) # 从xml中提取guid
332
+ except KeyError:
333
+ guids = [] # 如果没有找到对应的key,则初始化guids为空列表
334
+ bilibili_space = bilibili_json_update(
335
+ bilibili_key, bilibili_value
336
+ ) # 更新bilibili相关的json内容
337
+ # 读取原哔哩哔哩频道xml文件并判断是否要更新
338
+ try:
339
+ with open(
340
+ f"channel_id/{bilibili_key}.json",
341
+ "r",
342
+ encoding="utf-8", # 打开指定的json文件
343
+ ) as file:
344
+ bilibili_space_original = json.load(file) # 读取文件内容并解析成字典
345
+ except FileNotFoundError: # 捕获文件不存在异常
346
+ bilibili_space_original = {} # 如果文件不存在,初始化为空字典
347
+ except json.decoder.JSONDecodeError: # 捕获json解码错误
348
+ bilibili_space_original = {} # 如果json读取失败,初始化为空字典
349
+ # 根据更新条件更新频道数据
350
+ if bilibili_space == -404: # 检查更新状态
351
+ gVar.channelid_bilibili_rss[bilibili_key] = {
352
+ "content": bilibili_space,
353
+ "type": "int",
354
+ } # 设置为整型内容
355
+ elif bilibili_space is None:
356
+ gVar.channelid_bilibili_rss[bilibili_key] = {
357
+ "content": bilibili_space_original,
358
+ "type": "json",
359
+ } # 使用原始json内容
360
+ else:
361
+ gVar.channelid_bilibili_rss[bilibili_key] = {
362
+ "content": bilibili_space,
363
+ "type": "dict",
364
+ } # 设置为字典类型内容
365
+ # 判断是否需要更新ID列表
366
+ if bilibili_space != bilibili_space_original:
367
+ gVar.channelid_bilibili_ids_update[bilibili_key] = bilibili_value # 更新ID
368
+ # 获取需要更新的内容列表
369
+ bilibili_content_bvid = bilibili_space["list"][
370
+ : gVar.channelid_bilibili[bilibili_value]["update_size"]
371
+ ]
372
+ bilibili_space_new = list_merge_tidy(
373
+ bilibili_content_bvid, guids
374
+ ) # 合并新内容和原内容
375
+ # 检查内容是否有变动
376
+ if bilibili_content_bvid := [
377
+ exclude
378
+ for exclude in bilibili_content_bvid
379
+ if exclude not in bilibili_content_bvid_original # 筛选新增的内容
380
+ ]:
381
+ gVar.channelid_bilibili_ids_update[bilibili_key] = bilibili_value # 需要更新ID
382
+ gVar.bilibili_content_bvid_update[bilibili_key] = (
383
+ bilibili_content_bvid # 更新新增内容
384
+ )
385
+ # 向后更新
386
+ if (
387
+ gVar.channelid_bilibili[bilibili_value]["BackwardUpdate"] and guids
388
+ ): # 如果设置了向后更新
389
+ backward_update_size = gVar.channelid_bilibili[bilibili_value][
390
+ "last_size"
391
+ ] - len(bilibili_space_new) # 计算需要向后更新的数量
392
+ if backward_update_size > 0:
393
+ backward_update_size = min(
394
+ backward_update_size,
395
+ gVar.channelid_bilibili[bilibili_value]["BackwardUpdate_size"],
396
+ ) # 限制更新数量
397
+ backward_update_page_start = math.ceil(
398
+ len(bilibili_space_new) / 25
399
+ ) # 确定开始页面
400
+ backward_update_page_end = math.ceil(
401
+ (len(bilibili_space_new) + backward_update_size) / 25
402
+ ) # 确定结束页面
403
+ backward_entry = {} # 初始化向后更新的条目
404
+ backward_list = [] # 初始化向后更新的列表
405
+ # 循环更新每一页的内容
406
+ for num in range(
407
+ backward_update_page_start, backward_update_page_end + 1
408
+ ):
409
+ backward_entry_part, backward_list_part = get_bilibili_vlist(
410
+ bilibili_key, bilibili_value, num
411
+ ) # 获取具体内容
412
+ backward_entry = backward_entry | backward_entry_part # 合并条目
413
+ backward_list += backward_list_part # 合并列表
414
+ # 检查条目和列表是否有效
415
+ if backward_entry and backward_list and guids[-1] in backward_list:
416
+ try:
417
+ backward_list_start = (
418
+ backward_list.index(guids[-1]) + 1
419
+ ) # 获取guids的起始索引
420
+ backward_list = backward_list[backward_list_start:][
421
+ :backward_update_size
422
+ ] # 更新向后列表
423
+ except ValueError:
424
+ backward_list = [] # 如果没有找到,清空列表
425
+ # 根据条件移除已经存在的元素
426
+ for guid in backward_list.copy():
427
+ if guid in bilibili_space_new:
428
+ backward_list.remove(guid) # 移除已存在的条目
429
+ # 如果有向后条目需要更新
430
+ if backward_list:
431
+ if gVar.channelid_bilibili[bilibili_value][
432
+ "AllPartGet"
433
+ ]: # 如果需要获取所有部分
434
+
435
+ def backward_all_part(guid):
436
+ guid_cid, guid_type, power = get_bilibili_cid(
437
+ guid, bilibili_value
438
+ )
439
+ if guid_type:
440
+ backward_entry[guid][guid_type] = guid_cid
441
+ backward_entry[guid]["power"] = power
442
+
443
+ # 创建一个线程列表
444
+ threads = []
445
+ for guid in backward_list:
446
+ thread = threading.Thread(
447
+ target=backward_all_part, args=(guid,)
448
+ ) # 为每个条目创建线程
449
+ threads.append(thread) # 添加线程到列表
450
+ thread.start() # 启动线程
451
+ # 等待所有线程完成
452
+ for thread in threads:
453
+ thread.join()
454
+ # 更新频道信息
455
+ gVar.channelid_bilibili_rss[bilibili_key].update(
456
+ {
457
+ "backward": {
458
+ "list": backward_list,
459
+ "entry": backward_entry,
460
+ }
461
+ }
462
+ )
463
+ gVar.channelid_bilibili_ids_update[bilibili_key] = (
464
+ bilibili_value # 标记ID更新
465
+ )
466
+ bilibili_content_bvid_backward = [] # 初始化向后更新的内容列表
467
+ for guid in backward_list:
468
+ if (
469
+ guid not in bilibili_content_bvid_original
470
+ ): # 检查新增的内容
471
+ bilibili_content_bvid_backward.append(
472
+ guid
473
+ ) # 添加到向后更新列表
474
+ if bilibili_content_bvid_backward:
475
+ gVar.bilibili_content_bvid_backward_update[bilibili_key] = (
476
+ bilibili_content_bvid_backward # 更新最终的向后更新内容
477
+ )