├── README.md ├── pg.20250529-0750.zip ├── requirements.txt ├── sync-pg.py └── tgsearchpack.20241023-0901.zip /README.md: -------------------------------------------------------------------------------- 1 | # PG本地包(Sync From Telegram) 2 | 3 | ## 同步更新在线接口 4 | ``` 5 | https://www.252035.xyz/p/jsm.json 6 | ``` 7 | - 选择主页可以查看当前PG包版本 8 | - 在线接口已经默认集成了tgsearch的在线服务器,无需任何tg配置 9 | 10 | 备用接口 11 | ``` 12 | https://cnb.cool/fish2018/pg/-/git/raw/master/jsm.json 13 | http://www.fish2018.ip-ddns.com/p/jsm.json 14 | http://www3.fish2018.ip-ddns.com/p/jsm.json 15 | ``` 16 | 17 | 18 | ## TG影视资源频道 19 | [tgsearchers](https://t.me/s/tgsearchers) 实时更新最新影视资源并自动清理失效链接(123、夸克、阿里云、天翼、UC、115、移动、磁力、百度、迅雷),可用于tgsearch/tgsou搜索。 20 | 21 | ## tgsearch服务器 22 | ``` 23 | https://tg.252035.xyz 24 | http://tg.fish2018.ip-ddns.com 25 | http://tg3.fish2018.ip-ddns.com 26 | ``` 27 | 28 | 29 | ## 相关接口 30 | [真心接口](https://github.com/fish2018/ZX) 参考这个项目 31 | 32 | ## TG搜索相关教程 33 | 34 | [centos7.6部署TG搜索服务](https://github.com/fish2018/lib/blob/main/教程/centos7.6部署TG搜索服务.md) 35 | 36 | [TG本地搜索图文教程](https://github.com/fish2018/lib/blob/main/教程/关于TG本地搜索图文教程-PG.pdf) 37 | 38 | 在线获取TG session:https://tgs.252035.xyz/ 39 | 40 | 需要免费代理节点,可以使用另一个项目[ClashForge](https://github.com/fish2018/ClashForge) 41 | 42 | 维护自己的TG资源频道,可以使用另一个项目[TGForwarder](https://github.com/fish2018/TGForwarder) 43 | 44 | 45 | ## PG包下载地址 46 | PG包[README.txt](https://www.252035.xyz/p/README.txt) 47 | ```text 48 | 突破极限,超你所想。阿里不限速网盘资源全秒播 49 | 讨论组: https://t.me/pandagroovechat 50 | 发布频道: https://t.me/PandaGroovePG 51 | 内置订阅推荐:https://pgicloud.github.io 52 | 内置tgsearch下载链接:https://t.me/PandaGroovePG/1202 53 | 本频道只有上述一个讨论组,其他任何讨论组或Q群微群均与本频道无关 54 | 55 | 【 阿里,夸克,123使用本zip包不限速,阿里原画不需要svip也不用三方权益包。可能是地球上唯一一个可以流畅在线播放ISO原盘的zip(注:使用外部播放器播放原盘ISO需要在任务列表中把影视锁定不被杀掉后台才能稳定播放)。注意:不支持仅使用jar,必须zip完整解压使用。网盘原画仅支持原版的影视、OK影视。對本zip内的核心jar的魔改或縫合都會導致網盤原畫及直播不可播放。多个播放器或多次外挂本zip情况下,需要只保留一个播放器或1个外挂运行,其他的要主动杀掉,否则可能出现网盘播放异常。】 56 | 57 | 今日更新内容:(更多内容阅读zip内的README.txt) 58 | 1.iso播放时显示原始文件名,便于kodi动态下载字幕。 59 | ``` 60 | 61 | ```bash 62 | https://slink.ltd/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 63 | https://raw.yzuu.cf/fish2018/PG/main/pg.20250529-0750.zip 64 | https://raw.nuaa.cf/fish2018/PG/main/pg.20250529-0750.zip 65 | https://raw.kkgithub.com/fish2018/PG/main/pg.20250529-0750.zip 66 | https://cors.zme.ink/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 67 | https://git.886.be/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 68 | https://gitdl.cn/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 69 | https://ghfast.top/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 70 | https://gh.con.sh/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 71 | https://ghproxy.net/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 72 | https://github.moeyy.xyz/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 73 | https://gh-proxy.com/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 74 | https://ghproxy.cc/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 75 | https://gh.llkk.cc/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 76 | https://gh.ddlc.top/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 77 | https://gh-proxy.llyke.com/https://raw.githubusercontent.com/fish2018/PG/main/pg.20250529-0750.zip 78 | ``` 79 | 80 | ## tgsearch包下载地址 81 | [README.txt](https://www.252035.xyz/README.txt) 82 | [教程](https://github.com/fish2018/lib) (@奥利给 @jack) 83 | [安装脚本](https://github.com/DDS-Derek/alist-tvbox-script) (@DDS-Derek) 84 | 85 | ```yaml 86 | tgsearch多平台独立运行文件,使用./tgsearch 87 | -h可以看帮助,也支持环境变量赋值(防止被坏人偷窥hash),具体环境变量分别是API_ID,API_HASH,STRINGSESSION,API_PROXY,API_SESSION_V1,CACHE_DIR。 88 | 讨论组: https://t.me/pandagroovechat 89 | 发布频道: https://t.me/PandaGroovePG 90 | 内置订阅推荐:https://pgicloud.github.io 91 | 92 | 今日更新:(更多信息查看包内README) 93 | 1.优化tgsearch域名解析。 94 | 2.优化tgsearch,当使用-1或-2,-s参数登录时,忽略原有session。便于生成新session。v1session容易失效,建议用-1方式多获取几个,每个设备单独使用。 95 | ``` 96 | 97 | ```shell 98 | https://slink.ltd/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 99 | https://cors.zme.ink/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 100 | https://git.886.be/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 101 | https://raw.yzuu.cf/fish2018/PG/main/tgsearchpack.20241023-0901.zip 102 | https://raw.nuaa.cf/fish2018/PG/main/tgsearchpack.20241023-0901.zip 103 | https://raw.kkgithub.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 104 | https://ghp.ci/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 105 | https://gitdl.cn/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 106 | https://gh.con.sh/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 107 | https://ghproxy.net/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 108 | https://github.moeyy.xyz/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 109 | https://gh-proxy.com/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 110 | https://ghproxy.cc/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 111 | https://gh.llkk.cc/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 112 | https://gh.ddlc.top/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 113 | https://gh-proxy.llyke.com/https://raw.githubusercontent.com/fish2018/PG/main/tgsearchpack.20241023-0901.zip 114 | ``` 115 | 116 | ## sync-pg 本地包同步脚本 117 | 118 | ### 功能: 119 | - 监控TG频道,同步更新pg本地包并推送到github,生成README.md 120 | - 监控TG频道,同步更新tgsearch并推送到github,生成README.md 121 | - 支持本地解压zip自动处理jsm.json(设置线路、增删、排序、直播、壁纸、解析、代理规则等),用于提供在线接口 122 | - [支持tdl加速下载](https://docs.iyear.me/tdl/),需要先执行`tdl login -T code`获取配置信息 123 | 124 | #### 配置信息获取 125 | 126 | [github.com中设置token](https://github.com/settings/tokens) 127 | 128 | [api_id/api_hash申请](https://my.telegram.org/ ) 129 | 130 | github上公开的api_id/api_hash 131 | ``` 132 | api_id = 2934000 133 | api_hash = "7407f1e353d48363c48df4c8b3904acb" 134 | 135 | api_id = '27335138' 136 | pi_hash = '2459555ba95421148c682e2dc3031bb6' 137 | 138 | api_id = 6627460 139 | api_hash = '27a53a0965e486a2bc1b1fcde473b1c4' 140 | ``` 141 | -------------------------------------------------------------------------------- /pg.20250529-0750.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fish2018/PG/99506d36ae1ebc56f0d56fdb426e0fc0a08e0b21/pg.20250529-0750.zip -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | GitPython==3.1.43 2 | Telethon==1.37.0 3 | requests==2.32.3 4 | typing_extensions==4.12.2 5 | demoji==1.1.0 6 | tqdm==4.66.5 7 | -------------------------------------------------------------------------------- /sync-pg.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from asyncio import CancelledError 3 | from telethon.errors import FileReferenceExpiredError 4 | from telethon.tl.types import MessageMediaDocument 5 | from telethon import TelegramClient 6 | from typing import Union 7 | import os 8 | import re 9 | import sys 10 | import git 11 | import json 12 | import requests 13 | import subprocess 14 | import platform 15 | import demoji 16 | from tqdm import tqdm 17 | import ssl 18 | ssl._create_default_https_context = ssl._create_unverified_context 19 | 20 | keep = ['TG豆瓣', '网盘及彈幕配置', '荐片', '🐼️┃电视┃直播', '115云盘分享', '南瓜', 'TG频道搜索', 'TG群组搜索', '蜡笔|网盘', '小米UC网盘', '小米|网盘', '玩偶哥哥|网盘', '网盘分享合集', '阿里云盘影视分享', '夸克云盘分享', 'UC云盘分享', 'lf_p2p'] 21 | 22 | class TqdmUpTo(tqdm): 23 | total = None 24 | now_size = 0 25 | bar_format = '{l_bar}{bar}| {n_fmt}/{total_fmt} [已用时:{elapsed}预计剩余:{remaining}, {rate_fmt}{postfix}]' 26 | 27 | def __init__(self, **kwargs): 28 | super().__init__(**kwargs) 29 | self.unit = 'B' 30 | self.unit_scale = True 31 | self.unit_divisor = 1024 32 | self.bar_format = TqdmUpTo.bar_format 33 | 34 | def update_to(self, current, total): 35 | """更新进度条 36 | :param current: 已传输 37 | :param total: 总大小 38 | :return: 39 | """ 40 | self.total = total 41 | if current != 0: 42 | self.update(current - self.now_size) 43 | self.now_size = current 44 | async def GetChatTitle(client: TelegramClient, chat_id: int) -> Union[str, None]: 45 | entity = await client.get_entity(chat_id) 46 | return entity.title 47 | async def getHistoryMessage(client: TelegramClient, chat_id: int, from_user=None, limit=10): 48 | channel_title = await GetChatTitle(client, chat_id) 49 | if from_user is not None and from_user.isdecimal(): 50 | from_user = int(from_user) 51 | # 取最近2条消息 52 | messages = client.iter_messages(chat_id, from_user=from_user, limit=limit) 53 | return channel_title, messages 54 | async def GetChatId(client: TelegramClient, chat_id: str) -> int: 55 | # 检测chat_id是id还是昵称 56 | isId = re.match(r'-?[1-9][0-9]{4,}', chat_id) 57 | if isId is None: 58 | entity = await client.get_entity(chat_id) 59 | chat_id = entity.id 60 | else: 61 | chat_id = int(chat_id) 62 | return chat_id 63 | def shorten_filename(filename, limit=50): 64 | filename = filename.replace('\n', ' ') 65 | """返回合适长度文件名,中间用...显示""" 66 | if len(filename) <= limit: 67 | return filename 68 | else: 69 | return filename[:int(limit / 2) - 3] + '...' + filename[len(filename) - int(limit / 2):] 70 | def GetFileId(message) -> str: 71 | _id = 'unknown' 72 | if hasattr(message.media, 'document'): 73 | _id = message.media.document.id 74 | elif hasattr(message.media, 'photo'): 75 | _id = message.media.photo.id 76 | return str(_id) 77 | def GetFileName(message) -> str: 78 | # 取名优先级,文件名>描述>ID 79 | if message.file.name: 80 | return message.file.name 81 | file_ext = '.jpg' if message.file.ext in ['.jpe','jpeg'] else message.file.ext 82 | if len(message.message) != 0: 83 | sName = shorten_filename(demoji.replace(message.message, '[emoji]')) 84 | return re.sub(r'[\\/:*?"<>|]', '_', sName) + file_ext 85 | return GetFileId(message) + file_ext 86 | # fileExist 检查文件是否存在(文件名和大小都相等),如果不存在重名文件加序号 87 | def fileExist(file_path: str, file_size): 88 | i = 2 89 | ix = file_path.rfind('.', 1) 90 | fileName = file_path[:ix] 91 | fileType = file_path[ix:] 92 | temp = file_path 93 | while os.path.exists(temp): 94 | if os.path.getsize(temp) == file_size: 95 | return True, temp 96 | temp = f'{fileName}({i}){fileType}' 97 | i += 1 98 | return False, temp 99 | def GetFileSuffix(message) -> list: 100 | mime_type = 'unknown/unknown' 101 | if hasattr(message.media, 'document'): 102 | mime_type = message.media.document.mime_type 103 | elif hasattr(message.media, 'photo'): 104 | mime_type = 'image/jpg' 105 | return mime_type.split('/') 106 | async def download_file(client: TelegramClient, channel_title, channel_id, message, old=False, output='PG'): 107 | file_name = GetFileName(message) 108 | file_path = f'{output}/{file_name}' 109 | file_size = message.file.size 110 | ret, file_path = fileExist(file_path, file_size) 111 | if not ret: 112 | # 已经判断文件不存在,并且保证了文件名不重复 113 | download_path = file_path + '.downloading' 114 | print(f"开始下载:{file_name}") 115 | try: 116 | with TqdmUpTo(total=file_size, bar_format=TqdmUpTo.bar_format, desc=file_name[:10]) as bar: 117 | await message.download_media(download_path, progress_callback=bar.update_to) 118 | except CancelledError: 119 | print("取消下载") 120 | os.remove(download_path) 121 | sys.exit() 122 | except FileReferenceExpiredError: 123 | if old: 124 | print('重试失败,退出下载') 125 | exit(1) 126 | print('下载超时,重试中') 127 | channelData = await client.get_entity(int(channel_id)) 128 | newMessages = client.iter_messages(entity=channelData, ids=message.id) 129 | async for newMessage in newMessages: 130 | await download_file(client, channel_title, channel_id, newMessage, old=True) 131 | except Exception as e: 132 | print("下载出错", e.__class__.__name__) 133 | os.remove(download_path) 134 | else: 135 | os.rename(download_path, file_path) 136 | else: 137 | print(f"文件已存在:{file_path}") 138 | 139 | 140 | class TGDown: 141 | def __init__(self,api_id,api_hash,phone,username,repo,token,filter,filter2,local_target=None,channel=None,tdl=False,tip=None): 142 | self.client = TelegramClient('TG', api_id, api_hash) 143 | self.phone = phone 144 | self.registry = 'github.com' 145 | self.username = username 146 | self.repo = repo 147 | self.token = token 148 | self.branch = 'main' 149 | self.local_target = local_target 150 | self.filter = filter 151 | self.filter2 = filter2 152 | self.channel = channel 153 | self.tdl = tdl # 加速下载工具 docs.iyear.me/tdl 先tdl login -T code 154 | self.tip = tip # 替换set_version里的newname 155 | self.gh = [ 156 | 'https://slink.ltd/https://raw.githubusercontent.com', 157 | 'https://raw.yzuu.cf', 158 | 'https://raw.nuaa.cf', 159 | 'https://raw.kkgithub.com', 160 | 'https://cors.zme.ink/https://raw.githubusercontent.com', 161 | 'https://git.886.be/https://raw.githubusercontent.com', 162 | 'https://gitdl.cn/https://raw.githubusercontent.com', 163 | 'https://ghp.ci/https://raw.githubusercontent.com', 164 | 'https://gh.con.sh/https://raw.githubusercontent.com', 165 | 'https://ghproxy.net/https://raw.githubusercontent.com', 166 | 'https://github.moeyy.xyz/https://raw.githubusercontent.com', 167 | 'https://gh-proxy.com/https://raw.githubusercontent.com', 168 | 'https://ghproxy.cc/https://raw.githubusercontent.com', 169 | 'https://gh.llkk.cc/https://raw.githubusercontent.com', 170 | 'https://gh.ddlc.top/https://raw.githubusercontent.com', 171 | 'https://gh-proxy.llyke.com/https://raw.githubusercontent.com', 172 | ] 173 | 174 | def in_git_exist(self,file): 175 | is_exist = False 176 | file_url = f'https://slink.ltd/https://raw.githubusercontent.com/{self.username}/{self.repo}/{self.branch}/{file}' 177 | # 发送 HEAD 请求 178 | response = requests.head(file_url) 179 | # 检查响应状态码 180 | if response.status_code == 200: 181 | is_exist = True 182 | return is_exist 183 | def git_clone(self): 184 | self.domain = f'https://{self.token}@{self.registry}/{self.username}/{self.repo}.git' 185 | if os.path.exists(self.repo): 186 | subprocess.call(['rm', '-rf', self.repo]) 187 | try: 188 | print(f'开始克隆:git clone https://{self.registry}/{self.username}/{self.repo}.git') 189 | git.Repo.clone_from(self.domain, to_path=self.repo, depth=1) 190 | except Exception as e: 191 | try: 192 | self.registry = 'https://slink.ltd/' 193 | self.domain = f'https://{self.token}@{self.registry}/https://github.com/{self.username}/{self.repo}.git' 194 | if os.path.exists(self.repo): 195 | subprocess.call(['rm', '-rf', self.repo]) 196 | repo = git.Repo.clone_from(self.domain, to_path=self.repo, depth=1) 197 | except Exception as e: 198 | print(222222, e) 199 | def get_local_repo(self): 200 | # 打开本地仓库,读取仓库信息 201 | repo = git.Repo(self.repo) 202 | config_writer = repo.config_writer() 203 | config_writer.set_value('user', 'name', self.username) 204 | config_writer.set_value('user', 'email', self.username) 205 | # 设置 http.postBuffer 206 | config_writer.set_value('http', 'postBuffer', '104857600') 207 | config_writer.release() 208 | # 获取远程仓库的引用 209 | remote = repo.remote(name='origin') 210 | # 获取远程分支列表 211 | remote_branches = remote.refs 212 | # 遍历远程分支,查找主分支 213 | for branch in remote_branches: 214 | if branch.name == 'origin/master' or branch.name == 'origin/main': 215 | self.branch = branch.name.split('/')[-1] 216 | break 217 | # print(f"仓库{self.repo} 主分支为: {self.main_branch}") 218 | return repo 219 | def reset_commit(self,repo): 220 | # 重置commit 221 | try: 222 | os.chdir(self.repo) 223 | # print('开始清理git',os.getcwd()) 224 | repo.git.checkout('--orphan', 'tmp_branch') 225 | repo.git.add(A=True) 226 | repo.git.commit(m="update") 227 | repo.git.execute(['git', 'branch', '-D', self.branch]) 228 | repo.git.execute(['git', 'branch', '-m', self.branch]) 229 | repo.git.execute(['git', 'push', '-f', 'origin', self.branch]) 230 | except Exception as e: 231 | print('git清理异常', e) 232 | def git_push(self,repo): 233 | # 推送并重置commit计数 234 | print(f'开始推送:git push https://{self.registry}/{self.username}/{self.repo}.git') 235 | try: 236 | repo.git.add(A=True) 237 | repo.git.commit(m="update") 238 | repo.git.push() 239 | self.reset_commit(repo) 240 | except Exception as e: 241 | try: 242 | repo.git.execute(['git', 'push', '--set-upstream', 'origin', self.branch]) 243 | self.reset_commit(repo) 244 | except Exception as e: 245 | print('git推送异常', e) 246 | def set_version(self,filename,targetjson): 247 | newname = self.tip 248 | if not newname: 249 | # 去掉前缀 'pg.' 和后缀 '-.zip',然后替换中间的 '-' 为 '' 250 | match = re.match(self.filter, filename) 251 | if match: 252 | newname = f"{match.group(1)}{match.group(2)}" 253 | # 载入jsm.json文件 254 | with open(f'{self.local_target}/{targetjson}', 'r', encoding='utf-8') as file: 255 | data = json.load(file) 256 | # logo 257 | data["logo"] = "https://slink.ltd/https://raw.githubusercontent.com/fish2018/lib/refs/heads/main/imgs/pg.gif" 258 | # 配置parses解析器 259 | data["parses"] = [ 260 | { 261 | "name": "聚合", 262 | "type": 3, 263 | "url": "Demo" 264 | }, 265 | { 266 | "name": "web", 267 | "type": 3, 268 | "url": "Web" 269 | }, 270 | { 271 | "name": "看看", 272 | "type": 0, 273 | "url": "https://jx.m3u8.pw/?url=", 274 | "ext": { 275 | "flag": [ 276 | "qq", 277 | "腾讯", 278 | "qiyi", 279 | "爱奇艺", 280 | "奇艺", 281 | "youku", 282 | "优酷", 283 | "mgtv", 284 | "芒果", 285 | "imgo", 286 | "letv", 287 | "乐视", 288 | "pptv", 289 | "PPTV", 290 | "sohu", 291 | "bilibili", 292 | "哔哩哔哩", 293 | "哔哩" 294 | ], 295 | "header": { 296 | "User-Agent": "okhttp/4.1.0" 297 | } 298 | } 299 | }, 300 | { 301 | "name": "FreeOK", 302 | "type": 0, 303 | "url": "https://play.86516.tk/OKPlayer/?url=", 304 | "ext": { 305 | "flag": [ 306 | "qq", 307 | "腾讯", 308 | "qiyi", 309 | "爱奇艺", 310 | "奇艺", 311 | "youku", 312 | "优酷", 313 | "mgtv", 314 | "芒果", 315 | "imgo", 316 | "letv", 317 | "乐视", 318 | "pptv", 319 | "PPTV", 320 | "sohu", 321 | "bilibili", 322 | "哔哩哔哩", 323 | "哔哩" 324 | ], 325 | "header": { 326 | "User-Agent": "okhttp/4.1.0" 327 | } 328 | } 329 | }, 330 | { 331 | "name": "free", 332 | "type": 0, 333 | "url": "https://h5.freejson.xyz/player/?url=", 334 | "ext": { 335 | "flag": [ 336 | "qq", 337 | "腾讯", 338 | "qiyi", 339 | "爱奇艺", 340 | "奇艺", 341 | "youku", 342 | "优酷", 343 | "mgtv", 344 | "芒果", 345 | "imgo", 346 | "letv", 347 | "乐视", 348 | "pptv", 349 | "PPTV", 350 | "sohu", 351 | "bilibili", 352 | "哔哩哔哩", 353 | "哔哩" 354 | ], 355 | "header": { 356 | "User-Agent": "okhttp/4.1.0" 357 | } 358 | } 359 | } 360 | ] 361 | # 配置rules,添加域名 362 | hosts = ["content.stream-link.org"] 363 | data["rules"][0]["hosts"].extend(hosts) 364 | # 配置lives直播 365 | lives_extend = [ 366 | { 367 | "name": "stream直播", 368 | "url": "http://127.0.0.1:10079/p/0/proxy/https://www.stream-link.org/stream-link.m3u", 369 | "type": 0, 370 | "ua": "okhttp/3.15", 371 | "epg": "http://127.0.0.1:10079/p/0/proxy/http://content.stream-link.org/epg/guide.xml/?ch={name}&date={date}", 372 | "logo": "http://127.0.0.1:10079/p/0/proxy/http://content.stream-link.org/epg/guide.xml/logo/{name}.png" 373 | }] 374 | data["lives"] = data["lives"]+lives_extend 375 | # 查找直播转点播 376 | live2vod_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "直播转点播"), None) 377 | if live2vod_index is not None: 378 | data["sites"][live2vod_index]["ext"] = "../feimaolive.json" 379 | # 查找115Share 380 | share115_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "115Share"), None) 381 | if share115_index is not None: 382 | data["sites"][share115_index]["ext"] = "./lib/tokenm.json$$$https://ghp.ci/https://raw.githubusercontent.com/fish2018/lib/refs/heads/main/txt/115share.txt$$$db$$$1" 383 | # 查找 "南瓜" 对象并替换 384 | nangua_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "NanGua"), None) 385 | if nangua_index is not None: 386 | item = { 387 | "key": "nangua", 388 | "name": "南瓜", 389 | "type": 3, 390 | "playerType": "2", 391 | "api": "http://js.xn--z7x900a.com/js/ng_open.js" 392 | } 393 | data["sites"][nangua_index] = item 394 | # 查找 "豆瓣" 对象并追加新的对象 395 | douban_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "豆瓣"), None) 396 | if douban_index is not None: 397 | item = { 398 | "key": "https://github.com/fish2018/PG", 399 | "name": newname, 400 | "type": 3, 401 | "api": "csp_Douban", 402 | "searchable": 1, 403 | "changeable": 1, 404 | "indexs": 1, 405 | "ext": "./lib/douban.json" 406 | } 407 | data["sites"].insert(douban_index + 1, item) 408 | # 查找"TG豆瓣" 对象并更新 "ext" 409 | TGDouban_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "TGDouban"), None) 410 | if TGDouban_index is not None: 411 | data["sites"][TGDouban_index]["ext"] = { 412 | "token":"./lib/tokenm.json", 413 | "json":"./lib/tgsearch.json", 414 | "keywords":"名称,片名,推荐", 415 | "tgsearch_url":"http://127.0.0.1:10199", 416 | "tgsearch_media_url":"http://127.0.0.1:10199", 417 | "channellist":"alypzyhzq|1000,Mbox115|1000,shares_115|1000,Quark_Share_Channel|1000,Aliyundrive_Share_Channel|1000,wanwansubchat|1000,tgsearchers", 418 | "proxy":"noproxy", 419 | "douban":"./lib/douban.json", 420 | "danmu":False 421 | } 422 | # 查找 "TG搜索Local" 对象并更新 "ext" 423 | tg_localsearch_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "TGYunPanLocal"),None) 424 | if tg_localsearch_index is not None: 425 | data["sites"][tg_localsearch_index]["ext"] = { 426 | "token":"./lib/tokenm.json", 427 | "json":"./lib/tgsearch.json", 428 | "keywords":"名称,片名,推荐", 429 | "tgsearch_url":"http://127.0.0.1:10199", 430 | "tgsearch_media_url":"http://127.0.0.1:10199", 431 | "channellist":"guaguale115,dianyingshare,XiangxiuNB,kuakeyun", 432 | "proxy":"proxy", 433 | "danmu": True 434 | } 435 | # 查找 "TG网盘搜索" 对象并更新 "ext" 436 | tg_search_index = next((index for (index, d) in enumerate(data["sites"]) if d["key"] == "TGYunPan"), None) 437 | if tg_search_index is not None: 438 | data["sites"][tg_search_index]["ext"] = { 439 | "token":"./lib/tokenm.json", 440 | "json":"./lib/tgsearch.json", 441 | "keywords":"名称,片名,推荐", 442 | "tgsearch_url":"http://127.0.0.1:10199", 443 | "tgsearch_media_url":"http://127.0.0.1:10199", 444 | "channellist":"XiangxiuNB|1000,Aliyundrive_Share_Channel|1000,Quark_Share_Channel|1000,yunpanshare|1000,Aliyun_4K_Movies|1000,hao115|1000,alyp_4K_Movies|1000", 445 | "proxy":"noproxy", 446 | "danmu": True 447 | } 448 | with open(f'{self.local_target}/{targetjson}', 'w', encoding='utf-8') as file: 449 | json.dump(data, file, indent=4, ensure_ascii=False) 450 | items = [ 451 | { 452 | "key": "lf_js_p2p", 453 | "name": "lf_p2p", 454 | "type": 3, 455 | "searchable": 1, 456 | "changeable": 1, 457 | "quickSearch": 1, 458 | "filterable": 1, 459 | "api": "https://ghp.ci/https://raw.githubusercontent.com/fish2018/lib/refs/heads/main/js/lf_p2p2_min.js", 460 | "ext": "18+" 461 | }, 462 | { 463 | "key": "小米UC", 464 | "name": "小米UC网盘", 465 | "type": 3, 466 | "api": "csp_Wobg", 467 | "quickSearch": 1, 468 | "changeable": 1, 469 | "filterable": 1, 470 | "timeout": 60, 471 | "ext": "./lib/tokenm.json$$$http://www.mucpan.cc/$$$noproxy$$$1$$$./lib/wogg.json$$$" 472 | } 473 | ] 474 | for item in items: 475 | data["sites"].insert(tg_search_index + 1, item) 476 | # 精简排序 477 | # 用于存放筛选后的结果 478 | items = data["sites"] 479 | filtered_items = [] 480 | # 保留第二个元素 481 | second_item = items[1] 482 | # 遍历 keep 列表,并根据其中的元素筛选 items 中的数据 483 | for name in keep: 484 | for item in items: 485 | if item['name'] == name: 486 | filtered_items.append(item) 487 | break 488 | # 将第二个元素始终放在第二个位置 489 | if second_item in filtered_items: 490 | filtered_items.remove(second_item) 491 | # 在第二个位置插入第二个元素 492 | filtered_items.insert(1, second_item) 493 | # 输出最终结果 494 | data["sites"] = filtered_items 495 | # 替换壁纸 496 | data["wallpaper"] = "https://jiduo.serv00.net/image" 497 | # 将更新后的数据写回jsm.json文件 498 | with open(f'{self.local_target}/{targetjson}-custom', 'w', encoding='utf-8') as file: 499 | json.dump(data, file, indent=4, ensure_ascii=False) 500 | def readme(self,pg_zip_name='',tgsearch_zip_name='',pg_message='',tgsearch_message=''): 501 | readme = f'{self.repo}/README.md' 502 | # 读取 README.md 文件内容 503 | with open(readme, 'r') as file: 504 | content = file.read() 505 | 506 | if pg_zip_name: 507 | # 替换PG包下载链接 508 | def replace_urls(match): 509 | new_urls = [f"{gh_base}/{self.username}/{self.repo}/{self.branch}/{pg_zip_name}" for gh_base in self.gh] 510 | return '```bash\n' + '\n'.join(new_urls) + '\n```' 511 | content = re.sub( 512 | r'```bash\s*\n(.*?)\s*```', 513 | replace_urls, 514 | content, 515 | flags=re.DOTALL 516 | ) 517 | # 替换PG包更新说明 518 | def replace_pg_message(match): 519 | return f"{match.group(1)}{pg_message}{match.group(3)}" 520 | content = re.sub( 521 | r'(```text\s*\n)(.*?)(\s*\n```)', 522 | replace_pg_message, 523 | content, 524 | flags=re.DOTALL 525 | ) 526 | 527 | if tgsearch_zip_name: 528 | # 替换tgsearch包 529 | def replace_urls(match): 530 | new_urls = [f"{gh_base}/{self.username}/{self.repo}/{self.branch}/{tgsearch_zip_name}" for gh_base in self.gh] 531 | return '```shell\n' + '\n'.join(new_urls) + '\n```' 532 | content = re.sub( 533 | r'```shell\s*\n(.*?)\s*```', 534 | replace_urls, 535 | content, 536 | flags=re.DOTALL 537 | ) 538 | # 替换tgsearch包更新说明 539 | def replace_tgsearch_message(match): 540 | return f"{match.group(1)}{tgsearch_message}{match.group(3)}" 541 | content = re.sub( 542 | r'(```yaml\s*\n)(.*?)(\s*\n```)', 543 | replace_tgsearch_message, 544 | content, 545 | flags=re.DOTALL 546 | ) 547 | 548 | # 写回新的 README.md 文件内容 549 | with open(readme, 'w') as file: 550 | file.write(content) 551 | 552 | async def down_group(self, client: TelegramClient, chat_id, from_user=None): 553 | chat_id = await GetChatId(client, chat_id) 554 | channel_title, messages = await getHistoryMessage(client, chat_id, from_user=from_user) 555 | # 正则表达式 556 | has_clone = False 557 | pg_hit = False 558 | tgsearch_hit = False 559 | pg_zip_name='' 560 | tgsearch_zip_name='' 561 | pg_message='' 562 | tgsearch_message='' 563 | has_update = False 564 | async for message in messages: 565 | if message is None: 566 | continue 567 | # 判定消息中是否存在媒体内容 MessageMediaDocument:文件 568 | if not isinstance(message.media, (MessageMediaDocument)): 569 | continue 570 | # 匹配zip,如果是pg,如果是tgsearch,下载 571 | for pattern in [self.filter,self.filter2]: 572 | match = re.match(pattern, message.file.name) 573 | if match: 574 | # hit说明已经更新过 575 | if (message.file.name.split(".")[0] == 'pg' and pg_hit) or (message.file.name.split(".")[0] == 'tgsearchpack' and tgsearch_hit): 576 | print(f'忽略老版本包: {message.file.name}') 577 | continue 578 | # 检测github上是否已经存在该包 579 | is_exist = self.in_git_exist(message.file.name) 580 | if is_exist: 581 | print(f'{message.file.name} 已经是最新包') 582 | # 已经更新过的包标记hit 583 | if message.file.name.split(".")[0] == 'pg': 584 | pg_hit = True 585 | elif message.file.name.split(".")[0] == 'tgsearchpack': 586 | tgsearch_hit = True 587 | else: 588 | print(f'发现更新包:{message.file.name}') 589 | has_update = True 590 | if not has_clone: 591 | self.git_clone() 592 | if os.path.exists(self.repo): 593 | has_clone = True 594 | subprocess.call(f'rm -rf {self.repo}/{message.file.name.split(".")[0]}*.zip', shell=True) 595 | if self.tdl: 596 | cmd = f'tdl dl -i zip -u https://t.me/{self.channel.split("/")[-1]}/{message.id} -d {self.repo} --template "{{{{ .FileName }}}}"' 597 | print(cmd) 598 | subprocess.call(f'{cmd}', shell=True) 599 | else: 600 | await download_file(client, channel_title, chat_id, message, self.repo) 601 | print(f'TG群组({channel_title}) - 本地包{message.file.name}下载完成') 602 | # 更新本地目录中的pg包并解压 603 | if message.file.name.split(".")[0] == 'pg': 604 | pg_zip_name = message.file.name 605 | pg_message=message.message 606 | pg_hit = True 607 | if self.local_target: 608 | try: 609 | print(f'开始更新{self.local_target}目录PG在线接口到最新版本') 610 | # 修改配置 611 | sed_command = f'sed -i "" "s@http://127.0.0.1:10199/@http://tg.fish2018.us.kg/@g" lib/tokenm.json' if platform.system() == "Darwin" else f'sed -i "s@http://127.0.0.1:10199/@http://tg.fish2018.us.kg/@g" lib/tokenm.json' 612 | subprocess.call( 613 | f'rm -rf {self.local_target}/* && ' 614 | f'cp -a {self.repo}/{message.file.name} {self.local_target}/ && ' 615 | f'cd {self.local_target} && ' 616 | f'unzip -o -q {message.file.name} && ' 617 | f'cp -a lib/tokentemplate.json lib/tokenm.json && ' 618 | f'rm -rf {message.file.name} && ' 619 | f'{sed_command}', 620 | shell=True 621 | ) 622 | # 在jsm.json中加入版本号 623 | self.set_version(filename=message.file.name, targetjson='jsm.json') 624 | except Exception as e: 625 | print(e) 626 | elif message.file.name.split(".")[0] == 'tgsearchpack': 627 | tgsearch_zip_name = message.file.name 628 | tgsearch_message = message.message 629 | tgsearch_hit = True 630 | # 更新服务器tgsearch二进制包 631 | print(f'更新tgsearch二进制包,重启supervisor') 632 | subprocess.call( 633 | f'supervisorctl stop tg && ' 634 | f'cp -a {self.repo}/{tgsearch_zip_name} ./ && ' 635 | f'unzip -o {tgsearch_zip_name} && ' 636 | f'rm -rf runtgsearch.sh tgsearch.arm32v7 tgsearch.arm64v8 tgsearch.exe && ' 637 | f'chmod +x tgsearch.x86_64 && ' 638 | f'supervisorctl start tg &&' 639 | f'rm -rf {tgsearch_zip_name}', 640 | shell=True 641 | ) 642 | 643 | if has_update: 644 | # 更新README.md 645 | self.readme(pg_zip_name, tgsearch_zip_name, pg_message, tgsearch_message) 646 | # 推送 647 | repo = self.get_local_repo() 648 | self.git_push(repo) 649 | 650 | def run(self): 651 | with self.client.start(phone=self.phone): 652 | self.client.loop.run_until_complete(self.down_group(self.client, self.channel)) 653 | 654 | 655 | if __name__ == '__main__': 656 | api_id = xxx 657 | api_hash = 'xxx' 658 | phone = "86xxxxxxxxx" 659 | channel = 'https://t.me/PandaGroovePG' 660 | username = 'fish2018' # github username 661 | repo = 'PG' # github repo 662 | token = 'xxxxx' # github token 663 | local_target = 'p' # zip解压提供在线接口的目录 664 | filter = r"pg\.(\d{8})-(\d{4})\.zip" 665 | filter2 = r'tgsearchpack\.(\d{8})-(\d{4})\.zip' 666 | tdl = False # 加速TG文件下载的工具 667 | tip = None 668 | TGDown(api_id,api_hash,phone,username,repo,token,filter,filter2,local_target,channel,tdl,tip).run() 669 | -------------------------------------------------------------------------------- /tgsearchpack.20241023-0901.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fish2018/PG/99506d36ae1ebc56f0d56fdb426e0fc0a08e0b21/tgsearchpack.20241023-0901.zip --------------------------------------------------------------------------------