248 lines
9.9 KiB
Python
248 lines
9.9 KiB
Python
import os
|
||
import sys
|
||
import time
|
||
import requests
|
||
import pyfiglet
|
||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||
from colorama import Fore, Style, init as colorama_init
|
||
# Import the checker module (not the function) so we can access attributes on it.
|
||
import check as checker_mod
|
||
|
||
# --- 模拟缺失的辅助模块/函数 (根据全局定义还原结构) ---
|
||
# 注意:原代码中这些函数有具体实现,但字节码中未提供其函数体,
|
||
# 这里根据 main 函数的调用方式进行了补全,以确保代码逻辑通顺。
|
||
import logging
|
||
logging.basicConfig(level=logging.DEBUG)
|
||
# 全局常量
|
||
THREADS_MAX = 3
|
||
DEFAULT_THREADS = 1
|
||
THREADS_MIN = 1
|
||
tg_token = None
|
||
tg_chat_id = None
|
||
|
||
# 初始化 Colorama
|
||
colorama_init(autoreset=True)
|
||
|
||
class LC:
|
||
"""模拟许可证检查类"""
|
||
def __init__(self, label):
|
||
self.label = label
|
||
self.sio = self.MockSocket()
|
||
|
||
class MockSocket:
|
||
def disconnect(self):
|
||
pass
|
||
|
||
def inline(self, fields):
|
||
# 模拟返回许可证信息字符串
|
||
return f"{Fore.GREEN}License Active: {self.label}{Style.RESET_ALL}"
|
||
|
||
# 实例化许可证对象
|
||
DEFAULT_LABEL = os.getenv('LICENSE_LABEL', 'Stripeauth1')
|
||
lic = LC(label=DEFAULT_LABEL)
|
||
|
||
def init_license():
|
||
pass
|
||
|
||
def pick_gradient():
|
||
# 模拟返回一个渐变色配置
|
||
return ['#ff0000', '#00ff00']
|
||
|
||
def color_gradient_text(text, gradient):
|
||
# 模拟渐变色文本处理
|
||
return text
|
||
|
||
def load_proxy_list(proxy_input):
|
||
# 模拟代理加载逻辑
|
||
if not proxy_input:
|
||
return []
|
||
# 简单模拟:如果是文件则读取,否则按逗号分割
|
||
if os.path.exists(proxy_input):
|
||
with open(proxy_input, 'r') as f:
|
||
return [line.strip() for line in f if line.strip()]
|
||
return [p.strip() for p in proxy_input.split(',') if p.strip()]
|
||
|
||
def worker(card, proxy_list):
|
||
# 每个线程使用独立的 Session,避免线程间共享连接导致冲突
|
||
with requests.Session() as sess:
|
||
msg, stat = checker_mod.check(card, sess, proxy_list)
|
||
return card, (msg, stat)
|
||
|
||
# --------------------------------------------------------
|
||
# 核心 Main 函数
|
||
# --------------------------------------------------------
|
||
|
||
def main():
|
||
# 清理屏幕
|
||
os.system('cls' if os.name == 'nt' else 'clear')
|
||
|
||
# 显示初始 Banner
|
||
banner = pyfiglet.figlet_format('CHK-TOOLS', font='ansi_shadow')
|
||
gradient = pick_gradient()
|
||
print(color_gradient_text(banner, gradient))
|
||
|
||
print('- ' * 35)
|
||
print(lic.inline(fields=('Name', 'Status', 'Expire', 'Device')))
|
||
print('- ' * 35)
|
||
|
||
# 打印社交信息
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Github {Fore.RED}: {Fore.YELLOW}github.com/KianSantang777")
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Telegram {Fore.RED}: {Fore.YELLOW}t.me/xqndrs")
|
||
print('- ' * 35)
|
||
|
||
# Telegram 配置输入
|
||
global tg_token, tg_chat_id
|
||
tg_token = input(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Telegram Bot Token {Fore.MAGENTA}[{Fore.YELLOW}Enter to skip{Fore.MAGENTA}]{Fore.WHITE}: ").strip()
|
||
|
||
if tg_token:
|
||
tg_chat_id = input(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Telegram Chat ID: ").strip()
|
||
if not tg_chat_id:
|
||
tg_token = None # 如果没有 ID,则作废 Token
|
||
else:
|
||
tg_token = None
|
||
|
||
# 同步到 checker 模块供内部使用
|
||
checker_mod.tg_token = tg_token
|
||
checker_mod.tg_chat_id = tg_chat_id
|
||
|
||
# 读取卡片文件
|
||
path = input(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Enter card file path (ex: {Fore.YELLOW}card.txt{Style.RESET_ALL}): ").strip()
|
||
if not path:
|
||
path = 'cc.txt'
|
||
|
||
try:
|
||
with open(path, 'r', encoding='utf-8') as f:
|
||
# 读取非空行并去除首尾空格
|
||
lines = [line.strip() for line in f]
|
||
# 这里的逻辑对应字节码 1308-1380
|
||
temp_cards = []
|
||
for line in lines:
|
||
if line.strip():
|
||
temp_cards.append(line.strip())
|
||
|
||
# 去重逻辑 (对应字节码 1388-1446: list(dict.fromkeys(cards)))
|
||
cards = list(dict.fromkeys(temp_cards))
|
||
|
||
except OSError:
|
||
print(f"\n{Fore.RESET}[{Fore.LIGHTRED_EX}ERROR{Fore.RESET}] Unable to read file: {path}\n")
|
||
return
|
||
except UnicodeDecodeError:
|
||
print(f"\n{Fore.RESET}[{Fore.LIGHTRED_EX}ERROR{Fore.RESET}] File must be in {Fore.RESET}UTF-8 {Fore.RESET}encoding.\n")
|
||
return
|
||
except KeyboardInterrupt:
|
||
sys.exit(1)
|
||
|
||
if not cards:
|
||
print(f"\n{Fore.RESET}[{Fore.LIGHTRED_EX}ERROR{Fore.RESET}] No card data found in {Fore.LIGHTRED_EX}{path}\n")
|
||
return
|
||
|
||
# 代理设置
|
||
print(f"{Fore.RED}[!] {Fore.LIGHTRED_EX}Note: {Fore.YELLOW}Comma separated, ex: user:pass@ip:port, ip:port:user:pass{Style.RESET_ALL}")
|
||
proxy_input = input(f"{Fore.RED}[+] {Fore.LIGHTWHITE_EX}Paste ur proxy kredensials {Style.RESET_ALL}{Fore.LIGHTBLACK_EX}[Press Enter to skip]{Style.RESET_ALL}: ").strip()
|
||
proxy_list = load_proxy_list(proxy_input)
|
||
|
||
if proxy_list:
|
||
print(f"{Fore.YELLOW}[✓]{Style.RESET_ALL} Loaded {len(proxy_list)} proxies.")
|
||
else:
|
||
print(f"{Fore.YELLOW}[!] No proxy entered or no valid proxies loaded. Continuing without proxy.{Style.RESET_ALL}")
|
||
|
||
# 线程设置
|
||
try:
|
||
user_threads = input(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Enter number of threads (max {Fore.RED}{THREADS_MAX}{Style.RESET_ALL}, default {Fore.LIGHTRED_EX}{DEFAULT_THREADS}{Style.RESET_ALL}): ").strip()
|
||
if user_threads:
|
||
n = int(user_threads)
|
||
if n < THREADS_MIN:
|
||
print(f"\n{Fore.RESET}[{Fore.LIGHTYELLOW_EX}WARN{Fore.RESET}] Minimum threads is {THREADS_MIN}. Using default {DEFAULT_THREADS}.{Style.RESET_ALL}")
|
||
threads = DEFAULT_THREADS
|
||
elif n > THREADS_MAX:
|
||
print(f"\n{Fore.RESET}[{Fore.LIGHTYELLOW_EX}WARN{Fore.RESET}] Max threads is {THREADS_MAX}. Using {THREADS_MAX} threads.{Style.RESET_ALL}")
|
||
threads = THREADS_MAX
|
||
else:
|
||
threads = n
|
||
else:
|
||
threads = DEFAULT_THREADS
|
||
except ValueError:
|
||
print(f"{Fore.RESET}[{Fore.LIGHTYELLOW_EX}WARN{Fore.RESET}] Invalid input. Using default {DEFAULT_THREADS} threads.{Style.RESET_ALL}")
|
||
threads = DEFAULT_THREADS
|
||
except KeyboardInterrupt:
|
||
sys.exit(1)
|
||
|
||
# 初始化计数器
|
||
cnt_live = 0
|
||
cnt_dead = 0
|
||
cnt_unknown = 0
|
||
res = []
|
||
|
||
start = time.perf_counter()
|
||
|
||
# 再次清理屏幕并显示正式运行 Banner
|
||
os.system('cls' if os.name == 'nt' else 'clear')
|
||
banner = pyfiglet.figlet_format('StripeAuth', font='ansi_shadow')
|
||
gradient = pick_gradient()
|
||
print(color_gradient_text(banner, gradient))
|
||
|
||
print('- ' * 35)
|
||
print(lic.inline(fields=('Name', 'Status', 'Expire', 'Device')))
|
||
print('- ' * 35)
|
||
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Total card {Fore.YELLOW}: {Fore.YELLOW}{len(cards)}{Style.RESET_ALL}")
|
||
if proxy_list:
|
||
print(f"{Fore.YELLOW}[✓]{Fore.LIGHTWHITE_EX} Use {Fore.YELLOW}{len(proxy_list)} {Fore.LIGHTWHITE_EX}proxies.")
|
||
else:
|
||
print(f"{Fore.RED}[x] {Fore.LIGHTWHITE_EX}No proxy entered or no valid proxies loaded. Continuing without proxy.{Style.RESET_ALL}")
|
||
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Total threads {Fore.YELLOW}: {Fore.YELLOW}{threads}{Style.RESET_ALL}")
|
||
# 注意:原代码此处标签写的是 "Max retry",但加载的变量是 THREADS_MAX
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Max retry {Fore.YELLOW}: {Fore.YELLOW}{THREADS_MAX}{Style.RESET_ALL}")
|
||
print(f"{Fore.RED}[▪︎] {Fore.LIGHTWHITE_EX}Live card saved to {Fore.YELLOW}: {Fore.LIGHTGREEN_EX}approvedcard.txt{Style.RESET_ALL}")
|
||
print('- ' * 35)
|
||
|
||
# 开启线程池进行任务
|
||
# 对应字节码: with requests.Session() as sess: (虽然这里sess没被显式用到worker里,但上下文管理器在)
|
||
with requests.Session() as sess:
|
||
with ThreadPoolExecutor(max_workers=threads) as ex:
|
||
# 提交任务: ex.submit(worker, card, proxy_list)
|
||
jobs = [ex.submit(worker, card, proxy_list) for card in cards]
|
||
|
||
for fut in as_completed(jobs):
|
||
# 解包返回值: return card, (r, stat)
|
||
# 字节码 UNPACK_SEQUENCE 2 (card), UNPACK_SEQUENCE 2 (r, stat)
|
||
card, (r, stat) = fut.result()
|
||
|
||
if stat is True:
|
||
cnt_live += 1
|
||
res.append((card, 'LIVE'))
|
||
# 这里可能隐含写入文件的逻辑,或者在 worker 里写,
|
||
# 但根据字节码 4766-4800,这里只做了计数和append到res
|
||
elif stat is False:
|
||
cnt_dead += 1
|
||
res.append((card, 'DEAD'))
|
||
else:
|
||
cnt_unknown += 1
|
||
res.append((card, 'UNKNOWN'))
|
||
|
||
elapsed = time.perf_counter() - start
|
||
|
||
print('\n' + '- ' * 35)
|
||
print(f"{Style.RESET_ALL}DONE. Checked {Fore.YELLOW}{len(cards)}{Style.RESET_ALL} cards in {Fore.YELLOW}{elapsed:.2f} {Style.RESET_ALL}seconds.")
|
||
print(f"RESULTS: {Fore.LIGHTGREEN_EX}LIVE: {Style.RESET_ALL}{cnt_live}, {Fore.RED}DEAD: {Style.RESET_ALL}{cnt_dead}, {Fore.LIGHTYELLOW_EX}UNKNOWN: {Style.RESET_ALL}{cnt_unknown}\n\n")
|
||
|
||
if __name__ == '__main__':
|
||
try:
|
||
init_license()
|
||
main()
|
||
if lic.sio:
|
||
lic.sio.disconnect()
|
||
print('Graceful exit.')
|
||
except ImportError:
|
||
os.system('pip install requests asyncio aiohttp faker colorama pyfiglet pycryptodome &> /dev//null')
|
||
print('\nRun again this tools\n')
|
||
sys.exit()
|
||
except KeyboardInterrupt:
|
||
print('\nExit requested.')
|
||
except Exception:
|
||
# 对应字节码 2516-2596 (License disconnect logic inside exception handler)
|
||
if lic.sio:
|
||
lic.sio.disconnect()
|
||
print('Graceful exit.')
|
||
raise |