From b1459dfc9973b932a964edb3b126cf3ed586ff2e Mon Sep 17 00:00:00 2001 From: AirportR Date: Sat, 11 May 2024 12:47:37 +0800 Subject: [PATCH] :sparkles: Support for customized UA(User-Agent). --- botmodule/subinfo.py | 50 +++++++++++++---------------------- resources/config.yaml.example | 14 +++++----- utils/__init__.py | 3 ++- utils/backend.py | 4 +-- utils/cleaner.py | 9 +++++++ utils/collector.py | 13 +++++---- utils/ipstack.py | 2 +- utils/myemoji.py | 2 +- 8 files changed, 49 insertions(+), 48 deletions(-) diff --git a/botmodule/subinfo.py b/botmodule/subinfo.py index 58a61070..e365bf93 100644 --- a/botmodule/subinfo.py +++ b/botmodule/subinfo.py @@ -4,17 +4,17 @@ from loguru import logger from pyrogram.enums import ParseMode from pyrogram.errors import RPCError -from utils.cleaner import geturl +from utils.cleaner import geturl, ArgCleaner from utils.collector import SubCollector from utils.check import get_telegram_id_from_message as get_id from utils.check import check_user +from utils import message_delete_queue as mdq from botmodule.init_bot import config, admin -from utils import cleaner async def getSubInfo(_, message): ID = get_id(message) - arg = cleaner.ArgCleaner().getall(str(message.text)) + arg = ArgCleaner.getarg(str(message.text)) call_time = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime()) try: back_message = await message.reply("正在查询流量信息...") # 发送提示 @@ -22,11 +22,11 @@ async def getSubInfo(_, message): url = geturl(text) arglen = len(arg) status = False + subname = arg[1] if not url: if arglen == 1: await back_message.edit_text("使用方法: /traffic & /subinfo & /流量查询 + <订阅链接> & <订阅名>") - await asyncio.sleep(5) - await back_message.delete() + mdq.put(back_message) return else: pwd = arg[2] if len(arg) > 2 else arg[1] @@ -54,38 +54,26 @@ async def getSubInfo(_, message): subcl = SubCollector(url) subcl.cvt_enable = False subinfo = await subcl.getSubTraffic() - if status: - if subinfo: - rs = subinfo[3] - subinfo[2] # 剩余流量 - subname = arg[1] - subinfo_text = f""" - ☁️订阅名称:{subname} + if not subinfo: + await back_message.edit_text("此订阅无法获取流量信息") + return + days_diff = subinfo[5] if len(subinfo) > 5 else "" + if days_diff: + days_diff = f"({days_diff}天)" + rs = subinfo[3] - subinfo[2] # 剩余流量 + subinfo_text = f""" ⬆️已用上行:{round(subinfo[0], 3)} GB ⬇️已用下行:{round(subinfo[1], 3)} GB 🚗总共使用:{round(subinfo[2], 3)} GB ⏳剩余流量:{round(rs, 3)} GB 💧总流量:{round(subinfo[3], 3)} GB -⏱️过期时间:{subinfo[4]} +⏱️过期时间:{subinfo[4]} {days_diff} 🔍查询时间:{call_time} - """ - await back_message.edit_text(subinfo_text, parse_mode=ParseMode.DISABLED) - else: - await back_message.edit_text("此订阅无法获取流量信息") + """ + if status: + subinfo_text = f"☁️订阅名称:{subname}" + subinfo_text else: - if subinfo: - rs = subinfo[3] - subinfo[2] # 剩余流量 - subinfo_text = f""" -☁️订阅链接:{url} -⬆️已用上行:{round(subinfo[0], 3)} GB -⬇️已用下行:{round(subinfo[1], 3)} GB -🚗总共使用:{round(subinfo[2], 3)} GB -⏳剩余流量:{round(rs, 3)} GB -💧总流量:{round(subinfo[3], 3)} GB -⏱️过期时间:{subinfo[4]} -🔍查询时间:{call_time} - """ - await back_message.edit_text(subinfo_text, parse_mode=ParseMode.DISABLED) - else: - await back_message.edit_text("此订阅无法获取流量信息") + subinfo_text = f"☁️订阅链接:{url}" + subinfo_text + await back_message.edit_text(subinfo_text, parse_mode=ParseMode.DISABLED) except RPCError as r: logger.error(str(r)) diff --git a/resources/config.yaml.example b/resources/config.yaml.example index 6c50e123..8bbe0af7 100644 --- a/resources/config.yaml.example +++ b/resources/config.yaml.example @@ -1,11 +1,4 @@ # 注意,yaml配置文件对缩进敏感,请不要强迫症删掉#号之间的空格。 -admin: -- 12345678 #管理员,此处写你的账户id或用户名,必须配置该项,否则程序会自动退出 -clash: - path: './bin/FullTCore' # 代理客户端的路径,默认为 ./bin/ 下。下载地址: https://github.com/AirportR/FullTCore/releases -# allow-caching: false #是否缓存测试过程产生的订阅,若否,则测试完成后会自动删除测试订阅,以免造成空间浪费。(此配置暂不生效) -# core: 4 # 核心数,数量越多测试速度越快,但代价是内存会大量占用(每个核心大概10M),自己的机子多少内存自己平衡。默认值为1. -# branch: origin #clash内核上游分支,仅有两个有效值: [origin, meta], meta分支支持更多协议,比如vless、tuic等,但是使用上较为不可控,默认为origin原生内核。 bot: api_id: 123456 # Telegram的api_id api_hash: ABCDEFG # Telegram的api_hash @@ -21,6 +14,12 @@ bot: # bright: "]" #右括号自定义文本 # bspace: " " #空格自定义文本,默认为2个 # command: ['mycommand1', 'mycommand2'] #自定义指令,用于适配权限回调。高级用法,不会无需配置。 +#admin: +#- 12345678 #管理员,此处写你的账户id或用户名,必须配置该项,否则程序会自动退出 +#clash: +# path: './bin/FullTCore' # 代理客户端的路径,默认为 ./bin/ 下。下载地址: https://github.com/AirportR/FullTCore/releases +# core: 4 # 单批次中同时测试的节点数量,数量越多测试速度越快,但代价是运行内存会相应变大,自己的机子多少内存自己平衡。默认值为4. +# branch: origin #clash内核上游分支,仅有两个有效值: [origin, meta], meta分支支持更多协议,比如vless、tuic等,但是使用上较为不可控,默认为meta原生内核。 #以下是fulltclash的buildtoken,可以用默认的,但是安全性得不到保障,具体原因详见文档 #buildtoken: c7004ded9db897e538405c67e50e0ef0c3dbad717e67a92d02f6ebcfd1022a5ad1d2c4419541f538ff623051759ec000d2f426e03f9709a6608570c5b9141a6b #proxy: "host:端口" # http配置代理(非socks5),括号内可选用于下载获取订阅链接,订阅链接国内打不开可尝试开启(可选配置),本机提供的代理可以这样填: '127.0.0.1:7890' @@ -33,6 +32,7 @@ bot: # host: '127.0.0.1:25500' #域名或者ip加端口 # tls: false #是否启用了tls,决定拼接的转换地址URL前缀是http还是https,默认false # remoteconfig: "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini" #远程配置 +#ua: "ClashMetaForAndroid/2.8.9.Meta Mihomo/0.16 Clash.Meta" #获取订阅时请求UA(user-agent)覆写,此配置仅会影响获取订阅时的UA,默认值如当前所示。 #pingurl: http://www.gstatic.com/generate_204 #自定义延迟测试URL #netflixurl: "https://www.netflix.com/title/80113701" #自定义奈飞非自制剧检测网页,注意在更换此链接时请确保是非自制的链接。 #speedfile: #自定义测速文件,可以添加多个诸如以下格式或者[https://1.com, https://2.com] diff --git a/utils/__init__.py b/utils/__init__.py index 3f00157a..749f14a7 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -7,12 +7,14 @@ __version__ = "3.6.11" # 项目版本号 HOME_DIR = getcwd() +DEFAULT_UA = f"fulltclash/{__version__}" # 默认请求头 __all__ = [ "cron_delete_message", "cron_edit_message", "message_delete_queue", "message_edit_queue", "__version__", + "DEFAULT_UA", "retry", "script_demo", "HOME_DIR", @@ -90,7 +92,6 @@ def async_runtime(loop: Optional[asyncio.AbstractEventLoop] = None): """ 临时的异步运行时,适用于只有一两个异步函数的情况 :param: loop: 事件循环 - :param: break_func: 触发的回调中止函数,参数为调用函数的返回值,返回值为bool, """ if loop is None: loop = asyncio.new_event_loop() diff --git a/utils/backend.py b/utils/backend.py index 2893544f..2e27de45 100644 --- a/utils/backend.py +++ b/utils/backend.py @@ -14,7 +14,7 @@ from loguru import logger from utils.collector import proxies from libs import pynat -from utils import message_edit_queue, cleaner, collector, ipstack, proxy, sorter, geoip +from utils import message_edit_queue, cleaner, collector, ipstack, proxy, sorter, geoip, __version__ # 重写整个测试核心,技术栈分离。 @@ -255,7 +255,7 @@ def nat_type_test(proxyaddr=None, proxyport=None): async def fetch(self: Speedtest, urls: list, host: str, port: int, buffer: int): try: async with aiohttp.ClientSession( - headers={"User-Agent": "FullTClash"}, + headers={"User-Agent": f"fulltclash/{__version__}"}, connector=ProxyConnector(host=host, port=port), ) as session: flag = 0 diff --git a/utils/cleaner.py b/utils/cleaner.py index dddfa60e..4d85d354 100644 --- a/utils/cleaner.py +++ b/utils/cleaner.py @@ -785,6 +785,15 @@ def get_slave_ranking(self, ID: Union[str, int] = None): sorted_ranking = {item: c for item, c in sorted_ranking} return sorted_ranking + def get_ua(self): + """ + 获取自定义ua + """ + try: + return str(self.config['ua']) + except KeyError: + return "" + def getConcurrency(self) -> int: clashconf = self.config.get('clash', {}) max_workers = min(32, (os.cpu_count() or 1) + 14) diff --git a/utils/collector.py b/utils/collector.py index e9c34101..244a381f 100644 --- a/utils/collector.py +++ b/utils/collector.py @@ -291,7 +291,7 @@ def __init__(self, suburl: str, include: str = '', exclude: str = '', force_conv """ super().__init__() self.text = None - self._headers = {'User-Agent': 'clash'} # 这个请求头是获取流量信息的关键 + self._headers = {'user-agent': 'ClashMetaForAndroid/2.8.9.Meta Mihomo/0.16 Clash.Meta'} # 这个请求头是获取流量信息的关键 self.subcvt_conf = config.config.get('subconverter', {}) self.cvt_enable = self.subcvt_conf.get('enable', False) self.url = suburl @@ -340,7 +340,7 @@ async def getSubTraffic(self, proxy=proxies): 获取订阅内的流量 :return: str """ - _headers = {'User-Agent': 'clash'} + _headers = config.get_ua() or {'user-agent': 'ClashMetaForAndroid/2.8.9.Meta Mihomo/0.16 Clash.Meta'} try: async with aiohttp.ClientSession(headers=_headers) as session: async with session.get(self.url, proxy=proxy, timeout=20) as response: @@ -358,10 +358,13 @@ async def getSubTraffic(self, proxy=proxies): traffic_download = info2.get('download', 0) / 1024 / 1024 / 1024 traffic_use = traffic_up + traffic_download traffic_total = info2.get('total', 0) / 1024 / 1024 / 1024 - expire_time = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(info2.get('expire', time.time()))) + expire = info2.get('expire', time.time()) + days_diff = int((expire - time.time()) // (24 * 60 * 60)) + expire_time = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(expire)) if expire_time.startswith('1970') and traffic_total and traffic_use: expire_time = '长期有效' - return [traffic_up, traffic_download, traffic_use, traffic_total, expire_time] + days_diff = 0 + return [traffic_up, traffic_download, traffic_use, traffic_total, expire_time, days_diff] except asyncio.exceptions.TimeoutError: logger.info("获取订阅超时") return [] @@ -377,7 +380,7 @@ async def getSubConfig(self, save_path: str = "./", proxy=proxies, inmemory: boo :param inmemory: 直接返回数据到内存,不保存到本地 :return: 获得一个文件: sub.yaml, bool : True or False """ - _headers = {'User-Agent': 'clash-meta'} + _headers = config.get_ua() or {'user-agent': 'ClashMetaForAndroid/2.8.9.Meta Mihomo/0.16 Clash.Meta'} # suburl = self.url suburl = self.cvt_url if self.cvt_enable else self.url cvt_text = "subconverter状态: {}".format("已启用" if self.cvt_enable else "未启用") diff --git a/utils/ipstack.py b/utils/ipstack.py index 7cf11b73..7ee18741 100644 --- a/utils/ipstack.py +++ b/utils/ipstack.py @@ -30,7 +30,7 @@ async def get_ips(proxyhost: list, proxyport: list): length = min(len(proxyhost), len(proxyport)) for i in range(length): conn = ProxyConnector(host=proxyhost[i], port=proxyport[i], limit=0) - session = aiohttp.ClientSession(connector=conn, headers={'user-agent': 'FullTClash'}) + session = aiohttp.ClientSession(connector=conn, headers={'user-agent': 'fulltclash'}) session_pool.append(session) for j in range(length): tasks.append(asyncio.create_task(get_ip(v4url, session=session_pool[j]))) diff --git a/utils/myemoji.py b/utils/myemoji.py index a3033ad1..e86b4d9a 100644 --- a/utils/myemoji.py +++ b/utils/myemoji.py @@ -199,7 +199,7 @@ async def download_emoji(self, download_url: str = None, savepath='./resources/e _url = self.download_url if download_url is None else download_url # 如果没有提供下载地址则用默认的 print("Download URL:", _url) # 从网络上下载 - async with ClientSession(headers={'user-agent': 'FullTClash'}) as session: + async with ClientSession(headers={'user-agent': 'fulltclash'}) as session: async with session.get(_url, proxy=proxy) as resp: if resp.status == 200: content_leagth = resp.content_length if resp.content_length else 10 * 1024 * 1024