From 419731448cc6dea9a2f96bf011e901e6c6cf36dc Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Fri, 15 Nov 2024 14:09:31 +0800
Subject: [PATCH 1/4] chore:run service
---
main.py | 27 +++++++++++++++++----------
tkinter_ui/tkinter_ui.py | 10 ++++++++--
utils/tools.py | 15 +++++++++------
3 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/main.py b/main.py
index 7088327d408..a75188fca14 100644
--- a/main.py
+++ b/main.py
@@ -224,8 +224,6 @@ async def main(self):
True,
url=f"{get_ip_address()}" if open_service else None,
)
- if open_service:
- run_service()
except asyncio.exceptions.CancelledError:
print("Update cancelled!")
@@ -253,14 +251,23 @@ def scheduled_task():
def run_service():
- if not os.environ.get("GITHUB_ACTIONS"):
- ip_address = get_ip_address()
- print(f"📄 Result detail: {ip_address}/result")
- print(f"📄 Log detail: {ip_address}/log")
- print(f"✅ You can use this url to watch IPTV 📺: {ip_address}")
- app.run(host="0.0.0.0", port=8000)
+ try:
+ if not os.environ.get("GITHUB_ACTIONS"):
+ ip_address = get_ip_address()
+ print(f"📄 Result detail: {ip_address}/result")
+ print(f"📄 Log detail: {ip_address}/log")
+ print(f"✅ You can use this url to watch IPTV 📺: {ip_address}")
+ app.run(host="0.0.0.0", port=8000)
+ except Exception as e:
+ print(f"❌ Service start failed: {e}")
if __name__ == "__main__":
- if len(sys.argv) == 1 or (len(sys.argv) > 1 and sys.argv[1] == "scheduled_task"):
- scheduled_task()
+ if len(sys.argv) == 1 and config.open_service:
+ loop = asyncio.new_event_loop()
+
+ async def run_service_async():
+ loop.run_in_executor(None, run_service)
+
+ asyncio.run(run_service_async())
+ scheduled_task()
diff --git a/tkinter_ui/tkinter_ui.py b/tkinter_ui/tkinter_ui.py
index f5388088002..b5905282a0a 100644
--- a/tkinter_ui/tkinter_ui.py
+++ b/tkinter_ui/tkinter_ui.py
@@ -7,7 +7,7 @@
from PIL import Image, ImageTk
from utils.config import config
from utils.tools import resource_path
-from main import UpdateSource
+from main import UpdateSource, run_service
import asyncio
import threading
import webbrowser
@@ -113,11 +113,17 @@ async def run_update(self):
self.progress_label.pack_forget()
def on_run_update(self):
+ loop = asyncio.new_event_loop()
+
+ async def run_service_async():
+ loop.run_in_executor(None, run_service)
+
def run_loop():
- loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.run_update())
+ if config.open_service:
+ asyncio.run(run_service_async())
self.thread = threading.Thread(target=run_loop, daemon=True)
self.thread.start()
diff --git a/utils/tools.py b/utils/tools.py
index f38f2052942..db93397c85d 100644
--- a/utils/tools.py
+++ b/utils/tools.py
@@ -400,12 +400,15 @@ def get_result_file_content(show_result=False):
Get the content of the result file
"""
user_final_file = resource_path(config.final_file)
- if config.open_m3u_result:
- user_final_file = os.path.splitext(user_final_file)[0] + ".m3u"
- if show_result == False:
- return send_file(user_final_file, as_attachment=True)
- with open(user_final_file, "r", encoding="utf-8") as file:
- content = file.read()
+ if os.path.exists(user_final_file):
+ if config.open_m3u_result:
+ user_final_file = os.path.splitext(user_final_file)[0] + ".m3u"
+ if show_result == False:
+ return send_file(user_final_file, as_attachment=True)
+ with open(user_final_file, "r", encoding="utf-8") as file:
+ content = file.read()
+ else:
+ content = "🔍️正在更新,请耐心等待更新完成..."
return render_template_string(
"
{{ content }}
",
content=content,
From 2754b45fbbb072c88e01a79f7aba4a2d29a05116 Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Fri, 15 Nov 2024 15:17:14 +0800
Subject: [PATCH 2/4] remove:domain_blacklist
---
config/config.ini | 3 +--
docs/config.md | 1 -
docs/config_en.md | 1 -
tkinter_ui/default.py | 24 ------------------------
tkinter_ui/tkinter_ui.py | 1 -
utils/config.py | 10 ----------
utils/tools.py | 18 +-----------------
7 files changed, 2 insertions(+), 56 deletions(-)
diff --git a/config/config.ini b/config/config.ini
index e7529ba5955..d63c7a9a360 100644
--- a/config/config.ini
+++ b/config/config.ini
@@ -20,9 +20,8 @@ ipv_type = 全部
ipv_type_prefer = 自动
ipv4_num = 5
ipv6_num = 5
-domain_blacklist = epg.pw,skype.serv00.net,iptv.yjxfz.com,live-hls-web-ajb.getaj.net,live.goodiptv.club,hc73k3dhwo5gfkt.wcetv.com,stream1.freetv.fun,zw9999.cnstream.top
open_m3u_result = True
-url_keywords_blacklist =
+url_keywords_blacklist = epg.pw,skype.serv00.net,iptv.yjxfz.com,live-hls-web-ajb.getaj.net,live.goodiptv.club,hc73k3dhwo5gfkt.wcetv.com,stream1.freetv.fun,zw9999.cnstream.top
open_subscribe = True
subscribe_urls = https://live.fanmingming.com/tv/m3u/ipv6.m3u,https://ghp.ci/https://raw.githubusercontent.com/joevess/IPTV/main/home.m3u8,https://aktv.top/live.txt,http://175.178.251.183:6689/live.txt,https://ghproxy.net/https://raw.githubusercontent.com/kimwang1978/collect-tv-txt/main/merged_output.txt,https://m3u.ibert.me/txt/fmml_dv6.txt,https://m3u.ibert.me/txt/o_cn.txt,https://m3u.ibert.me/txt/j_iptv.txt,https://github.moeyy.xyz/https://raw.githubusercontent.com/PizazzGY/TVBox/main/live.txt,https://ghproxy.net/https://raw.githubusercontent.com/xzw832/cmys/main/S_CCTV.txt,https://ghproxy.net/https://raw.githubusercontent.com/xzw832/cmys/main/S_weishi.txt,http://itv.22m.top/ITVBox/tv/tvonline.txt
open_multicast = True
diff --git a/docs/config.md b/docs/config.md
index a58a429cfd2..06c75118443 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -24,7 +24,6 @@
| ipv_type_prefer | 自动 | 接口协议类型偏好,优先将该类型的接口排在结果前面,可选值:IPv4、IPv6、自动、auto |
| ipv4_num | 5 | 结果中偏好的 IPv4 接口数量 |
| ipv6_num | 5 | 结果中偏好的 IPv6 接口数量 |
-| domain_blacklist | epg.pw | 接口域名黑名单,用于过滤低质量含广告类域名的接口 |
| url_keywords_blacklist | | 接口关键字黑名单,用于过滤含特定字符的接口 |
| open_subscribe | False | 开启订阅源功能 |
| subscribe_urls | | 订阅源,请输入订阅链接(支持 txt 与 m3u 链接),多个链接以逗号分隔 |
diff --git a/docs/config_en.md b/docs/config_en.md
index 5da6e322612..d0dd43b71e3 100644
--- a/docs/config_en.md
+++ b/docs/config_en.md
@@ -24,7 +24,6 @@
| ipv_type_prefer | auto | Interface protocol type preference, prioritize interfaces of this type in the results, optional values: IPv4, IPv6, auto |
| ipv4_num | 5 | The preferred number of IPv4 interfaces in the result |
| ipv6_num | 5 | The preferred number of IPv6 interfaces in the result |
-| domain_blacklist | | 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 | | Subscription source, please enter the subscription link (supports txt and m3u links), multiple links should be separated by commas |
diff --git a/tkinter_ui/default.py b/tkinter_ui/default.py
index f527ce73a10..e2323f58cf9 100644
--- a/tkinter_ui/default.py
+++ b/tkinter_ui/default.py
@@ -372,22 +372,6 @@ def init_ui(self, root):
)
self.open_empty_category_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
- frame_default_domain_blacklist = tk.Frame(root)
- frame_default_domain_blacklist.pack(fill=tk.X)
-
- self.domain_blacklist_label = tk.Label(
- frame_default_domain_blacklist, text="域名黑名单:", width=12
- )
- self.domain_blacklist_label.pack(side=tk.LEFT, padx=4, pady=8)
- self.domain_blacklist_text = scrolledtext.ScrolledText(
- frame_default_domain_blacklist, height=2
- )
- self.domain_blacklist_text.pack(
- side=tk.LEFT, padx=4, pady=8, expand=True, fill=tk.BOTH
- )
- self.domain_blacklist_text.insert(tk.END, ",".join(config.domain_blacklist))
- self.domain_blacklist_text.bind("", self.update_domain_blacklist)
-
frame_default_url_keywords_blacklist = tk.Frame(root)
frame_default_url_keywords_blacklist.pack(fill=tk.X)
@@ -503,13 +487,6 @@ def update_url_keywords_blacklist(self, event):
self.url_keywords_blacklist_text.get(1.0, tk.END),
)
- def update_domain_blacklist(self, event):
- config.set(
- "Settings",
- "domain_blacklist",
- self.domain_blacklist_text.get(1.0, tk.END),
- )
-
def update_url_keywords_blacklist(self, event):
config.set(
"Settings",
@@ -541,7 +518,6 @@ def change_entry_state(self, state):
"open_url_info_checkbutton",
"open_empty_category_checkbutton",
"ipv_type_combo",
- "domain_blacklist_text",
"url_keywords_blacklist_text",
]:
getattr(self, entry).config(state=state)
diff --git a/tkinter_ui/tkinter_ui.py b/tkinter_ui/tkinter_ui.py
index b5905282a0a..f4c80ae8693 100644
--- a/tkinter_ui/tkinter_ui.py
+++ b/tkinter_ui/tkinter_ui.py
@@ -58,7 +58,6 @@ def save_config(self):
"response_time_weight": self.default_ui.response_time_weight_scale.get(),
"resolution_weight": self.default_ui.resolution_weight_scale.get(),
"ipv_type": self.default_ui.ipv_type_combo.get(),
- "domain_blacklist": self.default_ui.domain_blacklist_text.get(1.0, tk.END),
"url_keywords_blacklist": self.default_ui.url_keywords_blacklist_text.get(
1.0, tk.END
),
diff --git a/utils/config.py b/utils/config.py
index 512f657322d..ea434b73180 100644
--- a/utils/config.py
+++ b/utils/config.py
@@ -147,16 +147,6 @@ def open_url_info(self):
def recent_days(self):
return self.config.getint("Settings", "recent_days", fallback=30)
- @property
- def domain_blacklist(self):
- return [
- domain.strip()
- for domain in self.config.get(
- "Settings", "domain_blacklist", fallback=""
- ).split(",")
- if domain.strip()
- ]
-
@property
def url_keywords_blacklist(self):
return [
diff --git a/utils/tools.py b/utils/tools.py
index db93397c85d..8ed74d8f42f 100644
--- a/utils/tools.py
+++ b/utils/tools.py
@@ -274,17 +274,6 @@ def check_url_ipv_type(url):
)
-def check_by_domain_blacklist(url):
- """
- Check by domain blacklist
- """
- domain_blacklist = {
- (urlparse(domain).netloc if urlparse(domain).scheme else domain)
- for domain in config.domain_blacklist
- }
- return urlparse(url).netloc not in domain_blacklist
-
-
def check_by_url_keywords_blacklist(url):
"""
Check by URL blacklist keywords
@@ -296,11 +285,7 @@ def check_url_by_patterns(url):
"""
Check the url by patterns
"""
- return (
- check_url_ipv_type(url)
- and check_by_domain_blacklist(url)
- and check_by_url_keywords_blacklist(url)
- )
+ return check_url_ipv_type(url) and check_by_url_keywords_blacklist(url)
def filter_urls_by_patterns(urls):
@@ -308,7 +293,6 @@ def filter_urls_by_patterns(urls):
Filter urls by patterns
"""
urls = [url for url in urls if check_url_ipv_type(url)]
- urls = [url for url in urls if check_by_domain_blacklist(url)]
urls = [url for url in urls if check_by_url_keywords_blacklist(url)]
return urls
From 9249970a4ef58341b2d35c11cc70df1d793b3cf5 Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Fri, 15 Nov 2024 15:52:01 +0800
Subject: [PATCH 3/4] chore:layout
---
tkinter_ui/default.py | 52 ++++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/tkinter_ui/default.py b/tkinter_ui/default.py
index e2323f58cf9..0da7131523f 100644
--- a/tkinter_ui/default.py
+++ b/tkinter_ui/default.py
@@ -141,7 +141,7 @@ def init_ui(self, root):
frame_default_channel_column1, text="频道接口数量:", width=12
)
self.urls_limit_label.pack(side=tk.LEFT, padx=4, pady=8)
- self.urls_limit_entry = tk.Entry(frame_default_channel_column1)
+ self.urls_limit_entry = tk.Entry(frame_default_channel_column1, width=8)
self.urls_limit_entry.pack(side=tk.LEFT, padx=4, pady=8)
self.urls_limit_entry.insert(0, config.urls_limit)
self.urls_limit_entry.bind("", self.update_urls_limit)
@@ -150,7 +150,7 @@ def init_ui(self, root):
frame_default_channel_column2, text="接口协议类型:", width=12
)
self.ipv_type_label.pack(side=tk.LEFT, padx=4, pady=8)
- self.ipv_type_combo = ttk.Combobox(frame_default_channel_column2)
+ self.ipv_type_combo = ttk.Combobox(frame_default_channel_column2, width=5)
self.ipv_type_combo.pack(side=tk.LEFT, padx=4, pady=8)
self.ipv_type_combo["values"] = ("IPv4", "IPv6", "全部")
if config.ipv_type == "ipv4":
@@ -161,22 +161,16 @@ def init_ui(self, root):
self.ipv_type_combo.current(2)
self.ipv_type_combo.bind("<>", self.update_ipv_type)
- frame_default_sort = tk.Frame(root)
- frame_default_sort.pack(fill=tk.X)
- frame_default_sort_column1 = tk.Frame(frame_default_sort)
- frame_default_sort_column1.pack(side=tk.LEFT, fill=tk.Y)
- frame_default_sort_column2 = tk.Frame(frame_default_sort)
- frame_default_sort_column2.pack(side=tk.LEFT, fill=tk.Y)
- frame_default_sort_column3 = tk.Frame(frame_default_sort)
- frame_default_sort_column3.pack(side=tk.RIGHT, fill=tk.Y)
+ frame_default_open_keep_all = tk.Frame(root)
+ frame_default_open_keep_all.pack(fill=tk.X)
self.open_keep_all_label = tk.Label(
- frame_default_sort_column1, text="保留模式:", width=12
+ frame_default_open_keep_all, 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(
- frame_default_sort_column1,
+ frame_default_open_keep_all,
variable=self.open_keep_all_var,
onvalue=True,
offvalue=False,
@@ -185,13 +179,20 @@ def init_ui(self, root):
)
self.open_keep_all_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
+ frame_default_sort = tk.Frame(root)
+ frame_default_sort.pack(fill=tk.X)
+ frame_default_sort_column1 = tk.Frame(frame_default_sort)
+ frame_default_sort_column1.pack(side=tk.LEFT, fill=tk.Y)
+ frame_default_sort_column2 = tk.Frame(frame_default_sort)
+ frame_default_sort_column2.pack(side=tk.RIGHT, fill=tk.Y)
+
self.open_sort_label = tk.Label(
- frame_default_sort_column2, text="测速排序:", width=12
+ frame_default_sort_column1, 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(
- frame_default_sort_column2,
+ frame_default_sort_column1,
variable=self.open_sort_var,
onvalue=True,
offvalue=False,
@@ -200,10 +201,10 @@ def init_ui(self, root):
self.open_sort_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
self.sort_timeout_label = tk.Label(
- frame_default_sort_column3, text="测速超时:", width=12
+ frame_default_sort_column2, text="测速超时:", width=12
)
self.sort_timeout_label.pack(side=tk.LEFT, padx=4, pady=8)
- self.sort_timeout_entry = tk.Entry(frame_default_sort_column3)
+ self.sort_timeout_entry = tk.Entry(frame_default_sort_column2, width=8)
self.sort_timeout_entry.pack(side=tk.LEFT, padx=4, pady=8)
self.sort_timeout_entry.insert(0, config.sort_timeout)
self.sort_timeout_entry.bind("", self.update_sort_timeout)
@@ -241,7 +242,7 @@ def init_ui(self, root):
onvalue=True,
offvalue=False,
command=self.update_open_m3u_result,
- text="(支持频道图标)",
+ text="(开启频道图标)",
)
self.open_m3u_result_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
@@ -277,7 +278,9 @@ def init_ui(self, root):
frame_default_resolution_params_column2, text="最小分辨率:", width=12
)
self.min_resolution_label.pack(side=tk.LEFT, padx=4, pady=8)
- self.min_resolution_entry = tk.Entry(frame_default_resolution_params_column2)
+ self.min_resolution_entry = tk.Entry(
+ frame_default_resolution_params_column2, width=10
+ )
self.min_resolution_entry.pack(side=tk.LEFT, padx=4, pady=8)
self.min_resolution_entry.insert(0, config.min_resolution)
self.min_resolution_entry.bind("", self.update_min_resolution)
@@ -345,12 +348,12 @@ def init_ui(self, root):
self.open_update_time_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
self.open_url_info_label = tk.Label(
- frame_default_open_update_info_column1, text="显示接口信息:", width=12
+ frame_default_open_update_info_column2, text="显示接口信息:", width=12
)
self.open_url_info_label.pack(side=tk.LEFT, padx=4, pady=8)
self.open_url_info_var = tk.BooleanVar(value=config.open_url_info)
self.open_url_info_checkbutton = ttk.Checkbutton(
- frame_default_open_update_info_column1,
+ frame_default_open_update_info_column2,
variable=self.open_url_info_var,
onvalue=True,
offvalue=False,
@@ -358,13 +361,16 @@ def init_ui(self, root):
)
self.open_url_info_checkbutton.pack(side=tk.LEFT, padx=4, pady=8)
+ frame_default_open_empty_category = tk.Frame(root)
+ frame_default_open_empty_category.pack(fill=tk.X)
+
self.open_empty_category_label = tk.Label(
- frame_default_open_update_info_column2, text="无结果频道分类:", width=12
+ frame_default_open_empty_category, text="显示无结果分类:", width=12
)
self.open_empty_category_label.pack(side=tk.LEFT, padx=4, pady=8)
self.open_empty_category_var = tk.BooleanVar(value=config.open_empty_category)
self.open_empty_category_checkbutton = ttk.Checkbutton(
- frame_default_open_update_info_column2,
+ frame_default_open_empty_category,
variable=self.open_empty_category_var,
onvalue=True,
offvalue=False,
@@ -380,7 +386,7 @@ def init_ui(self, root):
)
self.url_keywords_blacklist_label.pack(side=tk.LEFT, padx=4, pady=8)
self.url_keywords_blacklist_text = scrolledtext.ScrolledText(
- frame_default_url_keywords_blacklist, height=2
+ frame_default_url_keywords_blacklist, height=5
)
self.url_keywords_blacklist_text.pack(
side=tk.LEFT, padx=4, pady=8, expand=True, fill=tk.BOTH
From 288b8d934474317f9d6b9e0dd223b14f44933e32 Mon Sep 17 00:00:00 2001
From: "guorong.zheng" <360996299@qq.com>
Date: Fri, 15 Nov 2024 16:27:23 +0800
Subject: [PATCH 4/4] release:v1.5.2
---
CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++
version.json | 2 +-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98cec04db56..2e12f8f5073 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,38 @@
# 更新日志(Changelog)
+## v1.5.2
+
+### 2024/11/15
+
+- ✨ 新增各省份地方台
+- ✨ 新增控制显示无结果频道分类配置(open_empty_category)(#551)
+- ✨ 调整接口源(#526)
+- 🪄 优化频道数据插入速度
+- 🪄 优化 IPv6 测速逻辑,解决无结果问题
+- 🪄 优化页面服务启动与 docker 定时任务日志输出
+- 🪄 调整默认配置:接口数量 urls_limit=10 等数量配置,增加订阅源
+- 🐛 修复运行停止问题(#527)
+- 🐛 修复 Win7 GUI 启动问题(#536)
+- 🗑️ 移除部分无效订阅源
+- 🗑️ 移除域名黑名单配置(domain_blacklist),请使用接口关键字黑名单(url_keywords_blacklist)替代
+
+
+ English
+
+- ✨ Added local channels for each province.
+- ✨ Added configuration to control the display of the No Results Channel Category (open_empty_category) (#551).
+- ✨ Adjusted interface sources (#526).
+- 🪄 Optimized the speed of channel data insertion.
+- 🪄 Optimized IPv6 speed test logic to resolve no results issues.
+- 🪄 Optimized page service startup and Docker scheduled task log output.
+- 🪄 Adjusted default configurations: number of interfaces urls_limit=10, etc., and added subscription sources.
+- 🐛 Fixed the issue of the program stopping (#527).
+- 🐛 Fixed the issue of Win7 GUI startup (#536).
+- 🗑️ Removed some invalid subscription sources.
+- 🗑️ Removed the domain blacklist configuration (domain_blacklist). Please use the interface keyword blacklist (url_keywords_blacklist) instead.
+
+
+
## v1.5.1
### 2024/11/5
diff --git a/version.json b/version.json
index 89704bb19db..d2d7d6bdc41 100644
--- a/version.json
+++ b/version.json
@@ -1,4 +1,4 @@
{
- "version": "1.5.1",
+ "version": "1.5.2",
"name": "IPTV电视直播源更新工具"
}
\ No newline at end of file