Skip to content

Commit 2c4847c

Browse files
authored
Merge pull request #1332 from Guovin/dev
Update
2 parents 45bd908 + 5cc4c67 commit 2c4847c

10 files changed

Lines changed: 395 additions & 293 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@
3030
- 新增 HTTP 代理配置(`http_proxy`),增强在受限网络环境下的获取能力。
3131
- 支持识别并过滤过期/无效的 EPG 数据,提高 EPG 质量。
3232
- 支持语言切换(`language`),可选 `zh_CN` / `en`,界面与实时日志可切换语言输出。
33+
- 新增M3U`tvg-id`以适配更多播放器合并频道源。
3334

3435
### 🐛 优化与修复
3536

37+
- 优化降低程序运行时的内存占用。
3638
- 优化 CCTV 类频道别名匹配与 4K 频道识别(匹配规则改进)。
3739
- 优化推流首播体验、转码兼容性与 Docker 推流监控。
3840
- 优化接口冻结流程,智能管理与解冻判断。
3941
- 更新 IP 归属库与运营商数据,提高归属地过滤准确性。
4042
- 若干测速与过滤逻辑优化,减少误判与提升效率。
43+
- 调整Docker日志实时无缓冲输出。
4144

4245
### ⚙️ 配置项说明(新增 / 重点变更)
4346

@@ -97,14 +100,17 @@
97100
- Added HTTP proxy configuration (`http_proxy`) to improve fetching in restricted network environments.
98101
- Support identification and filtering of expired/invalid EPG data to improve EPG quality.
99102
- Support language switching (`language`), optional `zh_CN` / `en`, enabling UI and real-time log language switching.
103+
- Added M3U `tvg-id` to support merging channel sources in more players.
100104

101105
### 🐛 Optimizations & fixes
102106

107+
- Optimized to reduce the memory usage during program runtime.
103108
- Improved alias matching for CCTV-type channels and 4K channel recognition (matching rules refined).
104109
- Improved first-play streaming experience, transcoding compatibility, and Docker streaming monitoring.
105110
- Optimized interface freezing process with smarter management and unfreeze judgment.
106111
- Updated IP attribution and carrier data to improve accuracy of location-based filtering.
107112
- Several speed test and filtering logic optimizations to reduce false positives and improve efficiency.
113+
- Adjust Docker logs to output in real-time without buffering.
108114

109115
### ⚙️ Configuration items (new / important changes)
110116

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ ENV NGINX_HTTP_PORT=8080
3838
ENV NGINX_RTMP_PORT=1935
3939
ENV PUBLIC_PORT=80
4040
ENV PATH="$APP_WORKDIR/.venv/bin:/usr/local/nginx/sbin:$PATH"
41+
ENV PYTHONUNBUFFERED=1
4142

4243
WORKDIR $APP_WORKDIR
4344

Pipfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ bs4 = "==0.0.2"
2020
tqdm = "==4.67.1"
2121
async-timeout = "==5.0.1"
2222
aiohttp = "==3.13.3"
23-
flask = "==3.1.2"
2423
opencc-python-reimplemented = "==0.1.7"
2524
gunicorn = "==23.0.0"
26-
pillow = "==11.1.0"
2725
m3u8 = "==6.0.0"
2826
pytz = "==2025.1"
2927
pystray = "==0.19.5"
3028
ipip-ipdb = "==1.6.1"
29+
urllib3 = "==2.6.3"
30+
pillow = "==12.1.1"
31+
flask = "==3.1.3"
3132

3233
[requires]
3334
python_version = "3.13"

Pipfile.lock

Lines changed: 269 additions & 248 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/alias.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
# Format: Main name (corresponds to channel name in demo.txt template), alias1, alias2, alias3
66
# Aliases support regex matching. Aliases starting with re: are recognized as regular expressions, e\.g\. CCTV-1,re:(?i)^\s*CCTV[-\s_]*0?1(?![0-9Kk+])[\s\S]*$
77

8-
CCTV-1,re:(?i)^\s*CCTV[-\s_]*0?1(?![0-9Kk+])[\s\S]*$,CCTV1,CCTV-01,CCTV-01_ITV,CCTV-01北联,CCTV-01电信,CCTV-01东联,CCTV-01高码,CCTV-01高清,CCTV-01广西,CCTV-01梅州,CCTV-01咪咕,CCTV-01汝阳,CCTV-01山东,CCTV-01上海,CCTV-01斯特,CCTV-01四川,CCTV-01太原,CCTV-01天津,CCTV-01影视,CCTV-01浙江,CCTV-01重庆,CCTV1综合,CCTV-1综合,CCTV1(B),CCTV1[1920*1080],CCTV1「IPV6」,CCTV1HD,CCTV-1HD,CCTV1-标清,CCTV1港澳牿,CCTV-1高清,CCTV1-综合,CCTV-1综合ᴴᴰ
9-
CCTV-2,re:re:(?i)^\s*CCTV[-\s_]*0?2(?![0-9Kk+])[\s\S]*$,CCTV-02北联,CCTV-02电信,CCTV-02东联,CCTV-02高码,CCTV-02高清,CCTV-02广西,CCTV-02梅州,CCTV-02咪咕,CCTV-02汝阳,CCTV-02山东,CCTV-02上海,CCTV-02斯特,CCTV-02四川,CCTV-02太原,CCTV-02天津,CCTV-02影视,CCTV-02浙江,CCTV-02重庆,CCTV2财经,CCTV-2财经,CCTV2[1280*720],CCTV2「IPV6」,CCTV20241,CCTV22,CCTV250,CCTV2HD,CCTV-2HD,CCTV2-标清,CCTV2-财经,CCTV-2财经ᴴᴰ,CCTV-2高清
8+
CCTV-1,re:(?i)^\s*CCTV[-\s_]*0?1(?![0-9Kk+])[\s\S]*$,CCTV1,CCTV-01,CCTV-01_ITV,CCTV-01北联,CCTV-01电信,CCTV-01东联,CCTV-01高码,CCTV-01高清,CCTV-01广西,CCTV-01梅州,CCTV-01咪咕,CCTV-01汝阳,CCTV-01山东,CCTV-01上海,CCTV-01斯特,CCTV-01四川,CCTV-01太原,CCTV-01天津,CCTV-01影视,CCTV-01浙江,CCTV-01重庆,CCTV1综合,CCTV-1综合,CCTV1(B),CCTV1[1920*1080],CCTV1「IPV6」,CCTV1HD,CCTV-1HD,CCTV1-标清,CCTV-1高清,CCTV1-综合,CCTV-1综合ᴴᴰ
9+
CCTV-2,re:(?i)^\s*CCTV[-\s_]*0?2(?![0-9Kk+])[\s\S]*$,CCTV2,CCTV-02北联,CCTV-02电信,CCTV-02东联,CCTV-02高码,CCTV-02高清,CCTV-02广西,CCTV-02梅州,CCTV-02咪咕,CCTV-02汝阳,CCTV-02山东,CCTV-02上海,CCTV-02斯特,CCTV-02四川,CCTV-02太原,CCTV-02天津,CCTV-02影视,CCTV-02浙江,CCTV-02重庆,CCTV2财经,CCTV-2财经,CCTV2[1280*720],CCTV2「IPV6」,CCTV20241,CCTV22,CCTV250,CCTV2HD,CCTV-2HD,CCTV2-标清,CCTV2-财经,CCTV-2财经ᴴᴰ,CCTV-2高清
1010
CCTV-3,re:(?i)^\s*CCTV[-\s_]*0?3(?![0-9Kk+])[\s\S]*$,CCTV3,CCTV-03,CCTV-03_ITV,CCTV-03北联,CCTV-03电信,CCTV-03东联,CCTV-03高码,CCTV-03高清,CCTV-03广西,CCTV-03梅州,CCTV-03咪咕,CCTV-03汝阳,CCTV-03山东,CCTV-03上海,CCTV-03斯特,CCTV-03四川,CCTV-03太原,CCTV-03天津,CCTV-03影视,CCTV-03浙江,CCTV-03重庆,CCTV3综艺,CCTV-3综艺,CCTV3[1920*1080],CCTV3「IPV6」,CCTV3HD,CCTV-3HD,CCTV3-标清,CCTV-3高清,CCTV-3-高清,CCTV3-综艺,CCTV-3综艺ᴴᴰ
11-
CCTV-4,re:(?i)^\s*CCTV[-\s_]*0?4(?![0-9Kk+])(?!.*(?:欧洲|美洲|Europe|America|Americas))[\s\S]*$,CCTV4,CCTV-04,CCTV-04_ITV,CCTV-04北联,CCTV-04电信,CCTV-04东联,CCTV-04高码,CCTV-04高清,CCTV-04广西,CCTV-04梅州,CCTV-04咪咕,CCTV-04汝阳,CCTV-04山东,CCTV-04上海,CCTV-04斯特,CCTV-04四川,CCTV-04太原,CCTV-04天津,CCTV-04影视,CCTV-04浙江,CCTV-04重庆,CCTV4中文国际,CCTV-4 中文国际,CCTV-4 中文国际 美洲,CCTV-4 中文国际欧洲,CCTV4(美洲),CCTV4(欧洲),CCTV4[1280*720],CCTV4[1920*1080],CCTV4「IPV6」,CCTV42,CCTV450,CCTV4HD,CCTV-4HD,CCTV-4K超高渿,CCTV-4标清,CCTV-4高清,CCTV4国际,CCTV4-国际,CCTV4美洲,CCTV-4美洲,CCTV4欧洲,CCTV-4欧洲,CCTV4-中文国际,CCTV-4中文国际,CCTV-4中文国际ᴴᴰ,CCTV4中文国际美洲,CCTV-4中文国际美洲,CCTV4中文国际欧洲,CCTV-4中文国际欧洲
11+
CCTV-4,re:(?i)^\s*CCTV[-\s_]*0?4(?![0-9Kk+])(?!.*(?:欧洲|美洲|Europe|America|Americas))[\s\S]*$,CCTV4,CCTV-04,CCTV-04_ITV,CCTV-04北联,CCTV-04电信,CCTV-04东联,CCTV-04高码,CCTV-04高清,CCTV-04广西,CCTV-04梅州,CCTV-04咪咕,CCTV-04汝阳,CCTV-04山东,CCTV-04上海,CCTV-04斯特,CCTV-04四川,CCTV-04太原,CCTV-04天津,CCTV-04影视,CCTV-04浙江,CCTV-04重庆,CCTV4[1280*720],CCTV4[1920*1080],CCTV4「IPV6」,CCTV42,CCTV450,CCTV4HD,CCTV-4HD,CCTV-4标清,CCTV-4高清
1212
CCTV-5,re:(?i)^\s*CCTV[-\s_]*0?5(?![0-9Kk+])[\s\S]*$,CCTV5,CCTV-05,CCTV-05_ITV,CCTV-05北联,CCTV-05电信,CCTV-05东联,CCTV-05高码,CCTV-05高清,CCTV-05广西,CCTV-05梅州,CCTV-05咪咕,CCTV-05汝阳,CCTV-05山东,CCTV-05上海,CCTV-05斯特,CCTV-05四川,CCTV-05太原,CCTV-05天津,CCTV-05影视,CCTV-05浙江,CCTV-05重庆,CCTV5体育,CCTV-5 体育,CCTV-5体育(高码率),CCTV5[1920*1080],CCTV5「IPV6」,CCTV5HD,CCTV-5HD,CCTV5-标清,CCTV-5高清,CCTV-5-高清,CCTV-5高清测试,CCTV5-体育,CCTV-5体育,CCTV-5体育ᴴᴰ
1313
CCTV-5+,re:(?i)^\s*CCTV[-\s_]*0?5\s*(?:\+|+)[\s\S]*$,CCTV5+,CCTV5+,CCTV5+ 体育赛事,CCTV-5+体育赛事,CCTV5+[1920*1080],CCTV-5+_ITV,CCTV5+「IPV6」,CCTV5+HD,CCTV-5+HD,CCTV-5+北联,CCTV-5+电信,CCTV-5+高码,CCTV-5+高清,CCTV-5+广西,CCTV-5+梅州,CCTV-5+咪咕,CCTV-5+汝阳,CCTV-5+四川,CCTV-5+太原,CCTV5+体育赛事,CCTV5+-体育赛事,CCTV-5+体育赛事ᴴᴰ,CCTV-5+天津,CCTV-5+影视,CCTV-5+浙江,CCTV-5+重庆,CCTV5+斯特,CCTV5+体育
1414
CCTV-6,re:(?i)^\s*CCTV[-\s_]*0?6(?![0-9Kk+])[\s\S]*$,CCTV6,CCTV-06,CCTV-06_ITV,CCTV-06北联,CCTV-06电信,CCTV-06东联,CCTV-06高码,CCTV-06高清,CCTV-06广西,CCTV-06梅州,CCTV-06咪咕,CCTV-06汝阳,CCTV-06山东,CCTV-06上海,CCTV-06斯特,CCTV-06四川,CCTV-06太原,CCTV-06天津,CCTV-06影视,CCTV-06浙江,CCTV-06重庆,CCTV6电影,CCTV-6电影,CCTV6[1920*1080],CCTV6「IPV6」,CCTV650,CCTV6HD,CCTV-6HD,CCTV6-标清,CCTV6-电影,CCTV-6电影ᴴᴰ,CCTV-6高清,CCTV-6-高清,CCTV-6高清测试

entrypoint.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ sed -e "s/\${APP_PORT}/${APP_PORT}/g" \
2222

2323
nginx -g 'daemon off;' &
2424

25-
python $APP_WORKDIR/main.py &
25+
python -u $APP_WORKDIR/main.py &
2626

27-
python -m gunicorn service.app:app -b 127.0.0.1:$APP_PORT --timeout=1000
27+
exec python -m gunicorn service.app:app -b 127.0.0.1:$APP_PORT --timeout=1000

main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ async def main(self):
310310
clear_cache()
311311
await self._run_speed_test()
312312
else:
313+
self.aggregator.test_results = self.channel_data
313314
self.aggregator.is_last = True
314315
await self.aggregator.flush_once(force=True)
315316

utils/aggregator.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import copy
33
from collections import defaultdict
44
from logging import INFO
5-
from typing import Any, Dict, Optional, Set, Tuple
5+
from typing import Any, Dict, Optional, Set, Tuple, Callable, cast
66

77
import utils.constants as constants
88
from utils.channel import sort_channel_result, generate_channel_statistic, write_channel_to_file, retain_origin
@@ -62,7 +62,8 @@ def _ensure_debounce_task_in_loop(self, loop: asyncio.AbstractEventLoop) -> None
6262
self._debounce_task = loop.create_task(self._debounce_loop())
6363
except Exception:
6464
try:
65-
loop.call_soon_threadsafe(self._create_debounce_task_threadsafe)
65+
cast(Any, loop).call_soon_threadsafe(
66+
cast(Callable[[], None], self._create_debounce_task_threadsafe), *())
6667
except Exception:
6768
pass
6869

@@ -73,13 +74,12 @@ def _create_debounce_task_threadsafe(self) -> None:
7374
"""
7475
self._debounce_task = asyncio.create_task(self._debounce_loop())
7576

76-
def add_item(self, cate: str, name: str, item: dict, is_channel_last: bool = False, is_last: bool = False):
77+
def add_item(self, cate: str, name: str, item: dict, is_channel_last: bool = False, is_last: bool = False,
78+
is_valid: bool = True):
7779
"""
7880
Add a test result item for a specific category and name.
7981
"""
8082
self.test_results[cate][name].append(item)
81-
self._dirty = True
82-
self._dirty_count += 1
8383
self.is_last = is_last
8484
self._pending_channels.add((cate, name))
8585

@@ -92,20 +92,22 @@ def add_item(self, cate: str, name: str, item: dict, is_channel_last: bool = Fal
9292
except Exception:
9393
pass
9494

95-
if self.realtime_write:
95+
if is_valid and self.realtime_write:
9696
try:
97+
self._dirty = True
98+
self._dirty_count += 1
9799
loop = asyncio.get_running_loop()
98100
self._ensure_debounce_task_in_loop(loop)
99101
if self._dirty_count >= self._min_items_before_flush:
100102
self._dirty_count = 0
101-
loop.call_soon(self._flush_event.set)
103+
cast(Any, loop).call_soon(cast(Callable[[], None], self._flush_event.set), *())
102104
except RuntimeError:
103105
try:
104106
loop = asyncio.get_event_loop()
105107
self._ensure_debounce_task_in_loop(loop)
106108
if self._dirty_count >= self._min_items_before_flush:
107109
self._dirty_count = 0
108-
loop.call_soon_threadsafe(self._flush_event.set)
110+
cast(Any, loop).call_soon_threadsafe(cast(Callable[[], None], self._flush_event.set), *())
109111
except Exception:
110112
pass
111113

@@ -223,14 +225,22 @@ async def flush_once(self, force: bool = False) -> None:
223225
async with self._lock:
224226
if not self._dirty and not force:
225227
return
226-
test_copy = copy.deepcopy(self.test_results)
228+
227229
pending = set(self._pending_channels)
228230
self._pending_channels.clear()
229231

230232
if force:
233+
test_copy = copy.deepcopy(self.test_results)
231234
finished_for_flush = set(self._finished_channels)
232235
self._finished_channels.clear()
233236
else:
237+
test_copy = defaultdict(lambda: defaultdict(list))
238+
for cate, name in pending:
239+
items = self.test_results.get(cate, {}).get(name, [])
240+
copied_items = [it.copy() if isinstance(it, dict) else it for it in items]
241+
if copied_items:
242+
test_copy[cate][name] = copied_items
243+
234244
finished_for_flush = set(self._finished_channels & pending)
235245
self._finished_channels.difference_update(finished_for_flush)
236246

utils/channel.py

Lines changed: 73 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import re
88
import tempfile
99
from collections import defaultdict
10+
from itertools import chain
1011
from logging import INFO
12+
from typing import cast
1113

1214
import utils.constants as constants
1315
from utils.alias import Alias
@@ -72,7 +74,7 @@ def format_channel_data(url: str, origin: OriginType) -> ChannelData:
7274
"id": hash(url),
7375
"url": url,
7476
"host": get_url_host(url),
75-
"origin": origin,
77+
"origin": cast(OriginType, origin),
7678
"ipv_type": None,
7779
"extra_info": info
7880
}
@@ -315,13 +317,13 @@ def append_data_to_info_data(
315317
init_info_data(info_data, category, name)
316318

317319
channel_list = info_data[category][name]
318-
existing_urls = {info["url"] for info in channel_list if "url" in info}
320+
existing_map = {info["url"]: idx for idx, info in enumerate(channel_list) if "url" in info}
319321

320322
for item in data:
321323
try:
322324
channel_id = item.get("id") or hash(item["url"])
323-
url = item["url"]
324-
host = item.get("host") or get_url_host(url)
325+
raw_url = item.get("url")
326+
host = item.get("host") or (get_url_host(raw_url) if raw_url else None)
325327
date = item.get("date")
326328
delay = item.get("delay")
327329
speed = item.get("speed")
@@ -334,20 +336,50 @@ def append_data_to_info_data(
334336
catchup = item.get("catchup")
335337
extra_info = item.get("extra_info", "")
336338

337-
if not url or url in existing_urls:
339+
if not raw_url:
338340
continue
339341

340-
if url_origin != "whitelist" and whitelist_maps and is_url_whitelisted(whitelist_maps, url, name):
341-
url_origin = "whitelist"
342+
normalized_url = raw_url
343+
if url_origin not in retain_origin:
344+
normalized_url = get_channel_url(raw_url)
345+
if not normalized_url:
346+
continue
347+
if is_url_frozen(normalized_url):
348+
continue
349+
if blacklist and check_url_by_keywords(normalized_url, blacklist):
350+
continue
342351

343-
if not url_origin:
344-
continue
352+
if url_origin != "whitelist" and whitelist_maps and is_url_whitelisted(whitelist_maps, normalized_url,
353+
name):
354+
url_origin = "whitelist"
345355

346-
if url_origin not in retain_origin:
347-
url = get_channel_url(url)
348-
if not url or is_url_frozen(url) or blacklist and check_url_by_keywords(url, blacklist):
356+
if normalized_url in existing_map:
357+
existing_idx = existing_map[normalized_url]
358+
existing_origin = channel_list[existing_idx].get("origin")
359+
if existing_origin != "whitelist" and url_origin == "whitelist":
360+
channel_list[existing_idx] = {
361+
"id": channel_id,
362+
"url": normalized_url,
363+
"host": host or get_url_host(normalized_url),
364+
"date": date,
365+
"delay": delay,
366+
"speed": speed,
367+
"resolution": resolution,
368+
"origin": url_origin,
369+
"ipv_type": ipv_type,
370+
"location": location,
371+
"isp": isp,
372+
"headers": headers,
373+
"catchup": catchup,
374+
"extra_info": extra_info
375+
}
376+
continue
377+
else:
349378
continue
350379

380+
url = normalized_url
381+
382+
if url_origin not in retain_origin:
351383
if not ipv_type:
352384
if ipv_type_data and host in ipv_type_data:
353385
ipv_type = ipv_type_data[host]
@@ -369,10 +401,11 @@ def append_data_to_info_data(
369401

370402
if isp and isp_list and not any(item in isp for item in isp_list):
371403
continue
404+
372405
channel_list.append({
373406
"id": channel_id,
374407
"url": url,
375-
"host": host,
408+
"host": host or get_url_host(url),
376409
"date": date,
377410
"delay": delay,
378411
"speed": speed,
@@ -385,7 +418,7 @@ def append_data_to_info_data(
385418
"catchup": catchup,
386419
"extra_info": extra_info
387420
})
388-
existing_urls.add(url)
421+
existing_map[url] = len(channel_list) - 1
389422

390423
except Exception as e:
391424
print(t("msg.error_append_channel_data").format(info=e))
@@ -583,7 +616,8 @@ def _on_task_done(task):
583616
else:
584617
mark_url_good(merged.get("url"))
585618

586-
if is_valid_speed_result(merged):
619+
is_valid = is_valid_speed_result(merged)
620+
if is_valid:
587621
valid_count_by_channel[(cate, name)] += 1
588622
if not open_full_speed_test and valid_count_by_channel[(cate, name)] >= urls_limit:
589623
_cancel_remaining_channel_tasks(cate, name)
@@ -596,7 +630,7 @@ def _on_task_done(task):
596630

597631
if on_task_complete:
598632
try:
599-
on_task_complete(cate, name, merged, is_channel_last, is_last)
633+
on_task_complete(cate, name, merged, is_channel_last, is_last, is_valid)
600634
except Exception:
601635
pass
602636

@@ -638,18 +672,29 @@ def sort_channel_result(channel_data, result=None, filter_host=False, ipv6_suppo
638672
for n in names:
639673
values = obj.get(n) or []
640674
whitelist_result = []
641-
test_result = (result.get(c, {}).get(n, []) if result else []).copy()
642-
643-
for value in values:
644-
origin = value.get("origin")
645-
if origin in retain or (not ipv6_support and result and value.get("ipv_type") == "ipv6"):
646-
whitelist_result.append(value)
647-
elif filter_host:
648-
host = value.get("host")
649-
merged = {**value, **(speed_lookup(host) or {})}
650-
test_result.append(merged)
651-
652-
total_result = whitelist_result + sorter(test_result, ipv6_support=ipv6_support)
675+
result_list = (result.get(c, {}).get(n, []) if result else [])
676+
677+
if filter_host:
678+
merged_items = []
679+
for value in values:
680+
origin = value.get("origin")
681+
if origin in retain or (not ipv6_support and result and value.get("ipv_type") == "ipv6"):
682+
whitelist_result.append(value)
683+
else:
684+
host = value.get("host")
685+
merged = {**value, **(speed_lookup(host) or {})}
686+
merged_items.append(merged)
687+
688+
sorter_input = chain(result_list, merged_items) if merged_items else result_list
689+
total_result = whitelist_result + sorter(sorter_input, ipv6_support=ipv6_support)
690+
else:
691+
for value in values:
692+
origin = value.get("origin")
693+
if origin in retain or (not ipv6_support and result and value.get("ipv_type") == "ipv6"):
694+
whitelist_result.append(value)
695+
696+
total_result = whitelist_result + sorter(result_list, ipv6_support=ipv6_support)
697+
653698
seen_urls = set()
654699
for item in total_result:
655700
url = item.get("url")

0 commit comments

Comments
 (0)