From 7de46151811a07bc2eef4631fc2312cb9ab8337b Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Wed, 31 Jul 2024 17:31:51 +0800
Subject: [PATCH 1/3] feat:open_use_old_result and open_keep_all
---
config.py | 2 +
docs/config.md | 2 +
docs/config_en.md | 48 +++++++++++----------
main.py | 4 +-
tkinter_ui.py | 66 ++++++++++++++++++++++++++---
utils/channel.py | 106 ++++++++++++++++++++++++++++------------------
6 files changed, 155 insertions(+), 73 deletions(-)
diff --git a/config.py b/config.py
index faf14de26c..51f3b7bdbb 100644
--- a/config.py
+++ b/config.py
@@ -1,4 +1,5 @@
open_update = True
+open_use_old_result = True
source_file = "demo.txt"
final_file = "result.txt"
favorite_list = [
@@ -18,6 +19,7 @@
favorite_page_num = 5
default_page_num = 3
urls_limit = 15
+open_keep_all = False
open_sort = True
response_time_weight = 0.5
resolution_weight = 0.5
diff --git a/docs/config.md b/docs/config.md
index 27277658b5..36d0f470d1 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -1,6 +1,7 @@
| 配置项 | 默认值 | 描述 |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| open_update | True | 开启更新,若关闭则只运行结果页面服务 |
+| open_use_old_result | True | 开启使用历史更新结果,合并至本次更新中 |
| open_driver | False | 开启浏览器运行,若更新无数据可开启此模式,较消耗性能 |
| open_proxy | True | 开启代理,自动获取免费可用代理,若更新无数据可开启此模式 |
| source_file | "demo.txt" | 模板文件名称 |
@@ -10,6 +11,7 @@
| favorite_page_num | 5 | 关注频道获取分页数量 |
| default_page_num | 3 | 常规频道获取分页数量 |
| urls_limit | 10 | 单个频道接口数量 |
+| open_keep_all | False | 保留所有检索结果,会保留非模板频道名称的结果,推荐手动维护时开启 |
| open_sort | True | 开启排序功能(响应速度、日期、分辨率) |
| response_time_weight | 0.5 | 响应时间权重值(所有权重值总和应为 1) |
| resolution_weight | 0.5 | 分辨率权重值 (所有权重值总和应为 1) |
diff --git a/docs/config_en.md b/docs/config_en.md
index fd5c591f54..b1cf8f5d33 100644
--- a/docs/config_en.md
+++ b/docs/config_en.md
@@ -1,23 +1,25 @@
-| Configuration Item | Default Value | Description |
-| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
-| open_update | True | Enable updates, if disabled then only the result page service is run |
-| open_driver | False | Enable browser execution, If there are no updates, this mode can be enabled, which consumes more performance |
-| open_proxy | True | Enable proxy, automatically obtains free available proxies, If there are no updates, this mode can be enabled |
-| source_file | "demo.txt" | Template file name |
-| final_file | "result.txt" | Generated file name |
-| favorite_list | ["广东珠江","CCTV-1","CCTV-5","CCTV-5+","CCTV-13","广东体育","广东卫视","大湾区卫视","浙江卫视","湖南卫视","翡翠台"] | List of favorite channel names (used only to distinguish from regular channels, custom page retrieval quantity) |
-| open_online_search | False | Enable online search source feature |
-| favorite_page_num | 5 | Page retrieval quantity for favorite channels |
-| default_page_num | 3 | Page retrieval quantity for regular channels |
-| urls_limit | 10 | Number of interfaces per channel |
-| open_sort | True | Enable the sorting function (response speed, date, resolution) |
-| response_time_weight | 0.5 | Response time weight value (the sum of all weight values should be 1) |
-| resolution_weight | 0.5 | Resolution weight value (the sum of all weight values should be 1) |
-| recent_days | 30 | Retrieve interfaces updated within a recent time range (in days), reducing appropriately can avoid matching issues |
-| ipv_type | "ipv4" | The type of interface in the generated result, optional values: "ipv4", "ipv6", "all" |
-| domain_blacklist | ["epg.pw"] | Interface domain blacklist, used to filter out interfaces with low-quality, ad-inclusive domains |
-| url_keywords_blacklist | [] | Interface keyword blacklist, used to filter out interfaces containing specific characters |
-| open_subscribe | True | Enable subscription source feature |
-| subscribe_urls | ["https://m3u.ibert.me/txt/fmml_dv6.txt",
"https://m3u.ibert.me/txt/o_cn.txt",
"https://m3u.ibert.me/txt/j_iptv.txt"] | Subscription source list |
-| open_multicast | True | Enable multicast source function |
-| region_list | ["all"] | Multicast source region list, [more regions](./fofa_map.py, "all" means all regions) |
+| Configuration Item | Default Value | Description |
+| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
+| open_update | True | Enable updates, if disabled then only the result page service is run |
+| open_use_old_result | True | Enable the use of historical update results and merge them into the current update |
+| open_driver | False | Enable browser execution, If there are no updates, this mode can be enabled, which consumes more performance |
+| open_proxy | True | Enable proxy, automatically obtains free available proxies, If there are no updates, this mode can be enabled |
+| source_file | "demo.txt" | Template file name |
+| final_file | "result.txt" | Generated file name |
+| favorite_list | ["广东珠江","CCTV-1","CCTV-5","CCTV-5+","CCTV-13","广东体育","广东卫视","大湾区卫视","浙江卫视","湖南卫视","翡翠台"] | List of favorite channel names (used only to distinguish from regular channels, custom page retrieval quantity) |
+| open_online_search | False | Enable online search source feature |
+| favorite_page_num | 5 | Page retrieval quantity for favorite channels |
+| default_page_num | 3 | Page retrieval quantity for regular channels |
+| urls_limit | 10 | Number of interfaces per channel |
+| open_keep_all | False | Retain all search results, retain results with non-template channel names, recommended to be turned on when manually maintaining |
+| open_sort | True | Enable the sorting function (response speed, date, resolution) |
+| response_time_weight | 0.5 | Response time weight value (the sum of all weight values should be 1) |
+| resolution_weight | 0.5 | Resolution weight value (the sum of all weight values should be 1) |
+| recent_days | 30 | Retrieve interfaces updated within a recent time range (in days), reducing appropriately can avoid matching issues |
+| ipv_type | "ipv4" | The type of interface in the generated result, optional values: "ipv4", "ipv6", "all" |
+| domain_blacklist | ["epg.pw"] | Interface domain blacklist, used to filter out interfaces with low-quality, ad-inclusive domains |
+| url_keywords_blacklist | [] | Interface keyword blacklist, used to filter out interfaces containing specific characters |
+| open_subscribe | True | Enable subscription source feature |
+| subscribe_urls | ["https://m3u.ibert.me/txt/fmml_dv6.txt",
"https://m3u.ibert.me/txt/o_cn.txt",
"https://m3u.ibert.me/txt/j_iptv.txt"] | Subscription source list |
+| open_multicast | True | Enable multicast source function |
+| region_list | ["all"] | Multicast source region list, [more regions](./fofa_map.py, "all" means all regions) |
diff --git a/main.py b/main.py
index 81e62cf32d..3eeed5ab21 100644
--- a/main.py
+++ b/main.py
@@ -3,7 +3,7 @@
from utils.channel import (
get_channel_items,
append_data_to_info_data,
- append_all_method_data,
+ append_total_data,
sort_channel_list,
write_channel_to_file,
)
@@ -86,7 +86,7 @@ async def main(self):
self.total = len(channel_names)
await self.visit_page(channel_names)
self.tasks = []
- self.channel_data = append_all_method_data(
+ self.channel_data = append_total_data(
self.channel_items.items(),
self.channel_data,
self.subscribe_result,
diff --git a/tkinter_ui.py b/tkinter_ui.py
index 91665872bb..f5c206d37b 100644
--- a/tkinter_ui.py
+++ b/tkinter_ui.py
@@ -24,11 +24,12 @@ class TkinterUI:
def __init__(self, root):
self.root = root
self.root.title("直播源接口更新工具")
- self.version = "v1.3.3"
+ self.version = "v1.3.4"
self.update_source = UpdateSource()
self.update_running = False
self.config_entrys = [
"open_update_checkbutton",
+ "open_use_old_result_checkbutton",
"open_driver_checkbutton",
"open_proxy_checkbutton",
"source_file_entry",
@@ -38,6 +39,7 @@ def __init__(self, root):
"open_subscribe_checkbutton",
"open_multicast_checkbutton",
"open_online_search_checkbutton",
+ "open_keep_all_checkbutton",
"open_sort_checkbutton",
"favorite_list_text",
"favorite_page_num_entry",
@@ -60,6 +62,9 @@ def format_list(self, text):
def update_open_update(self):
config.open_update = self.open_update_var.get()
+ def update_open_use_old_result(self):
+ config.open_use_old_result = self.open_use_old_result_var.get()
+
def select_source_file(self):
filepath = filedialog.askopenfilename(
initialdir=os.getcwd(), title="选择模板文件", filetypes=[("txt", "*.txt")]
@@ -93,6 +98,9 @@ def update_open_driver(self):
def update_open_proxy(self):
config.open_proxy = self.open_proxy_var.get()
+ def update_open_keep_all(self):
+ config.open_keep_all = self.open_keep_all_var.get()
+
def update_open_sort(self):
config.open_sort = self.open_sort_var.get()
@@ -151,6 +159,7 @@ def view_result_link_callback(self, event):
def save_config(self):
config_values = {
"open_update": self.open_update_var.get(),
+ "open_use_old_result": self.open_use_old_result_var.get(),
"source_file": f'"{self.source_file_entry.get()}"',
"final_file": f'"{self.final_file_entry.get()}"',
"favorite_list": self.format_list(self.favorite_list_text.get(1.0, tk.END)),
@@ -160,6 +169,7 @@ def save_config(self):
"urls_limit": self.urls_limit_entry.get(),
"open_driver": self.open_driver_var.get(),
"open_proxy": self.open_proxy_var.get(),
+ "open_keep_all": self.open_keep_all_var.get(),
"open_sort": self.open_sort_var.get(),
"response_time_weight": self.response_time_weight_entry.get(),
"resolution_weight": self.resolution_weight_entry.get(),
@@ -255,12 +265,18 @@ def init_UI(self):
frame1_open_update = tk.Frame(frame1)
frame1_open_update.pack(fill=tk.X)
+ frame1_open_update_column1 = tk.Frame(frame1_open_update)
+ frame1_open_update_column1.pack(side=tk.LEFT, fill=tk.Y)
+ frame1_open_update_column2 = tk.Frame(frame1_open_update)
+ frame1_open_update_column2.pack(side=tk.RIGHT, fill=tk.Y)
- self.open_update_label = tk.Label(frame1_open_update, text="开启更新:", width=8)
+ self.open_update_label = tk.Label(
+ frame1_open_update_column1, text="开启更新:", width=8
+ )
self.open_update_label.pack(side=tk.LEFT, padx=4, pady=8)
self.open_update_var = tk.BooleanVar(value=config.open_update)
self.open_update_checkbutton = ttk.Checkbutton(
- frame1_open_update,
+ frame1_open_update_column1,
variable=self.open_update_var,
onvalue=True,
offvalue=False,
@@ -269,6 +285,21 @@ def init_UI(self):
)
self.open_update_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
+ self.open_use_old_result_label = tk.Label(
+ frame1_open_update_column2, text="使用历史结果:", width=12
+ )
+ self.open_use_old_result_label.pack(side=tk.LEFT, padx=4, pady=8)
+ self.open_use_old_result_var = tk.BooleanVar(value=config.open_use_old_result)
+ self.open_use_old_result_checkbutton = ttk.Checkbutton(
+ frame1_open_update_column2,
+ variable=self.open_use_old_result_var,
+ onvalue=True,
+ offvalue=False,
+ command=self.update_open_use_old_result,
+ text="(保留上次更新可用结果)",
+ )
+ self.open_use_old_result_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
+
frame1_source_file = tk.Frame(frame1)
frame1_source_file.pack(fill=tk.X)
@@ -336,7 +367,7 @@ def init_UI(self):
onvalue=True,
offvalue=False,
command=self.update_open_proxy,
- text="(自动获取免费代理)",
+ text="(通过代理获取更新结果)",
)
self.open_proxy_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
@@ -368,12 +399,33 @@ def init_UI(self):
frame1_sort = tk.Frame(frame1)
frame1_sort.pack(fill=tk.X)
+ frame1_sort_column1 = tk.Frame(frame1_sort)
+ frame1_sort_column1.pack(side=tk.LEFT, fill=tk.Y)
+ frame1_sort_column2 = tk.Frame(frame1_sort)
+ frame1_sort_column2.pack(side=tk.RIGHT, fill=tk.Y)
+
+ self.open_keep_all_label = tk.Label(
+ frame1_sort_column1, text="保留模式:", width=12
+ )
+ self.open_keep_all_label.pack(side=tk.LEFT, padx=4, pady=8)
+ self.open_keep_all_var = tk.BooleanVar(value=config.open_keep_all)
+ self.open_keep_all_checkbutton = ttk.Checkbutton(
+ frame1_sort_column1,
+ variable=self.open_keep_all_var,
+ onvalue=True,
+ offvalue=False,
+ command=self.update_open_keep_all,
+ text="(保留所有检索结果,建议手动维护时开启)",
+ )
+ self.open_keep_all_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
- self.open_sort_label = tk.Label(frame1_sort, text="开启测速排序:", width=12)
+ self.open_sort_label = tk.Label(
+ frame1_sort_column2, text="开启测速排序:", width=12
+ )
self.open_sort_label.pack(side=tk.LEFT, padx=4, pady=8)
self.open_sort_var = tk.BooleanVar(value=config.open_sort)
self.open_sort_checkbutton = ttk.Checkbutton(
- frame1_sort,
+ frame1_sort_column2,
variable=self.open_sort_var,
onvalue=True,
offvalue=False,
@@ -642,7 +694,7 @@ def init_UI(self):
tkinter_ui.init_UI()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
- width = 500
+ width = 550
height = 700
x = (screen_width / 2) - (width / 2)
y = (screen_height / 2) - (height / 2)
diff --git a/utils/channel.py b/utils/channel.py
index 7f01fc2228..020155c73b 100644
--- a/utils/channel.py
+++ b/utils/channel.py
@@ -63,12 +63,13 @@ def get_channel_items():
# Create a dictionary to store the channels.
channels = defaultdict(lambda: defaultdict(list))
- with open(resource_path(user_source_file), "r", encoding="utf-8") as file:
- get_channel_data_from_file(channels, file)
+ if os.path.exists(resource_path(user_source_file)):
+ with open(resource_path(user_source_file), "r", encoding="utf-8") as file:
+ channels = get_channel_data_from_file(channels, file)
- if config.open_use_old_result:
+ if config.open_use_old_result and os.path.exists(resource_path(user_final_file)):
with open(resource_path(user_final_file), "r", encoding="utf-8") as file:
- get_channel_data_from_file(channels, file)
+ channels = get_channel_data_from_file(channels, file)
return channels
@@ -77,6 +78,8 @@ def format_channel_name(name):
"""
Format the channel name with sub and replace and lower
"""
+ if config.open_keep_all:
+ return name
sub_pattern = (
r"-|_|\((.*?)\)|\[(.*?)\]| |频道|标清|高清|HD|hd|超清|超高|超高清|中央|央视|台"
)
@@ -119,6 +122,8 @@ def channel_name_is_equal(name1, name2):
"""
Check if the channel name is equal
"""
+ if config.open_keep_all:
+ return True
cc = OpenCC("t2s")
name1_converted = cc.convert(format_channel_name(name1))
name2_converted = cc.convert(format_channel_name(name2))
@@ -278,6 +283,16 @@ def append_data_to_info_data(info_data, cate, name, data, check=True):
return info_data
+def append_total_data(*args, **kwargs):
+ """
+ Append total channel data
+ """
+ if config.open_keep_all:
+ return append_all_method_data_keep_all(*args, **kwargs)
+ else:
+ return append_all_method_data(*args, **kwargs)
+
+
def append_all_method_data(
items, data, subscribe_result=None, multicast_result=None, online_search_result=None
):
@@ -286,44 +301,25 @@ def append_all_method_data(
"""
for cate, channel_obj in items:
for name, old_urls in channel_obj.items():
- if config.open_subscribe:
- data = append_data_to_info_data(
- data,
- cate,
- name,
- get_channel_results_by_name(name, subscribe_result),
- )
- print(
- name,
- "subscribe num:",
- len(get_channel_results_by_name(name, subscribe_result)),
- )
- if config.open_multicast:
- data = append_data_to_info_data(
- data,
- cate,
- name,
- get_channel_results_by_name(name, multicast_result),
- )
- print(
- name,
- "multicast num:",
- len(get_channel_results_by_name(name, multicast_result)),
- )
- if config.open_online_search:
- data = append_data_to_info_data(
- data,
- cate,
- name,
- get_channel_results_by_name(name, online_search_result),
- )
- print(
- name,
- "online search num:",
- len(get_channel_results_by_name(name, online_search_result)),
- )
+ for method, result in [
+ ("subscribe", subscribe_result),
+ ("multicast", multicast_result),
+ ("online_search", online_search_result),
+ ]:
+ if getattr(config, f"open_{method}"):
+ data = append_data_to_info_data(
+ data,
+ cate,
+ name,
+ get_channel_results_by_name(name, result),
+ )
+ print(
+ name,
+ f"{method.capitalize()} num:",
+ len(get_channel_results_by_name(name, result)),
+ )
total_channel_data_len = len(data.get(cate, {}).get(name, []))
- if total_channel_data_len == 0:
+ if total_channel_data_len == 0 or config.open_use_old_result:
data = append_data_to_info_data(
data,
cate,
@@ -338,6 +334,34 @@ def append_all_method_data(
return data
+def append_all_method_data_keep_all(
+ items, data, subscribe_result=None, multicast_result=None, online_search_result=None
+):
+ """
+ Append all method data to total info data, keep all channel name and urls
+ """
+ for cate, channel_obj in items:
+ for result_name, result in [
+ ("subscribe", subscribe_result),
+ ("multicast", multicast_result),
+ ("online_search", online_search_result),
+ ]:
+ if result and getattr(config, f"open_{result_name}"):
+ for name, urls in result.items():
+ data = append_data_to_info_data(data, cate, name, urls)
+ print(name, f"{result_name.capitalize()} num:", len(urls))
+ if config.open_use_old_result:
+ old_urls = channel_obj.get(name, [])
+ data = append_data_to_info_data(
+ data,
+ cate,
+ name,
+ [(url, None, None) for url in old_urls],
+ )
+
+ return data
+
+
async def sort_channel_list(semaphore, cate, name, info_list, callback):
"""
Sort the channel list
From a5d3e5d8dafe2bac4a2f3a6f7dce1ea15c56f417 Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Wed, 31 Jul 2024 17:32:05 +0800
Subject: [PATCH 2/3] release:v1.3.4
---
CHANGELOG.md | 7 +++++++
version.json | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ad2a11ea6..3b2bb9d2d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# 更新日志(Changelog)
+## v1.3.4
+
+### 2024/7/31
+
+- 新增配置 open_use_old_result:保留使用历史更新结果,合并至本次更新中(Add configuration open_use_old_result: Keep using the previous update results and merge them into the current update)
+- 新增配置 open_keep_all:保留所有检索结果,推荐手动维护时开启(#121)(Add configuration open_keep_all: Keep all search results, recommend enabling it for manual maintenance (#121))
+
## v1.3.3
### 2024/7/19
diff --git a/version.json b/version.json
index 96649c928e..7c32fcf6b2 100644
--- a/version.json
+++ b/version.json
@@ -1,3 +1,3 @@
{
- "version": "1.3.3"
+ "version": "1.3.4"
}
\ No newline at end of file
From c8dc786e1f6a4533f1c13b6cfc3e9bcbb5537890 Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Wed, 31 Jul 2024 17:46:22 +0800
Subject: [PATCH 3/3] chore:title
---
tkinter_ui.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tkinter_ui.py b/tkinter_ui.py
index f5c206d37b..e5f8deae1b 100644
--- a/tkinter_ui.py
+++ b/tkinter_ui.py
@@ -352,7 +352,7 @@ def init_UI(self):
onvalue=True,
offvalue=False,
command=self.update_open_driver,
- text="(较消耗性能)",
+ text="(若获取更新异常请开启)",
)
self.open_driver_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
@@ -367,7 +367,7 @@ def init_UI(self):
onvalue=True,
offvalue=False,
command=self.update_open_proxy,
- text="(通过代理获取更新结果)",
+ text="(通过代理进行更新)",
)
self.open_proxy_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)