每日签到奶昔超市点数市场奶昔访达
返回列表 发布新帖
查看: 669|回复: 1

relingo也重现江湖吧

发表于 2025-4-13 14:33:38 | 查看全部 |阅读模式

欢迎注册论坛,享受更多奶昔会员权益!

您需要 登录 才可以下载或查看,没有账号?注册

×
邀请码不会找自己问其他人。刷满 10 年,自动升级为永久会员
  1. import concurrent.futures
  2. import random
  3. import re
  4. import threading
  5. import time

  6. import requests
  7. from fake_useragent import UserAgent
  8. from loguru import logger

  9. referrer = "你的邀请码"


  10. class WordGenerator:
  11.     def __init__(self):
  12.         # 常用辅音字母
  13.         self.consonants = "bcdfghjklmnpqrstvwxyz"
  14.         # 元音字母
  15.         self.vowels = "aeiou"
  16.         # 常用的字母组合
  17.         self.common_pairs = [
  18.             "th",
  19.             "ch",
  20.             "sh",
  21.             "ph",
  22.             "wh",
  23.             "br",
  24.             "cr",
  25.             "dr",
  26.             "fr",
  27.             "gr",
  28.             "pr",
  29.             "tr",
  30.         ]
  31.         # 常用的词尾
  32.         self.common_endings = ["ing", "ed", "er", "est", "ly", "tion", "ment"]
  33.         # 常用的用户名后缀
  34.         self.username_suffixes = [
  35.             "123",
  36.             "888",
  37.             "666",
  38.             "777",
  39.             "999",
  40.             "pro",
  41.             "cool",
  42.             "good",
  43.             "best",
  44.         ]

  45.     def generate_syllable(self):
  46.         """生成一个音节"""
  47.         if random.random() < 0.3 and self.common_pairs:  # 30% 概率使用常用字母组合
  48.             return random.choice(self.common_pairs) + random.choice(self.vowels)
  49.         else:
  50.             return random.choice(self.consonants) + random.choice(self.vowels)

  51.     def generate_word(self, min_length=4, max_length=8):
  52.         """生成一个随机单词"""
  53.         word = ""
  54.         target_length = random.randint(min_length, max_length)

  55.         # 添加音节直到达到目标长度附近
  56.         while len(word) < target_length - 2:
  57.             word += self.generate_syllable()

  58.         # 可能添加常用词尾
  59.         if random.random() < 0.3 and len(word) < max_length - 2:
  60.             word += random.choice(self.common_endings)
  61.         elif len(word) < target_length:
  62.             word += random.choice(self.consonants)

  63.         return word.lower()

  64.     def generate_random_username(self, min_length=3, max_length=8):
  65.         """生成随机用户名"""
  66.         username = self.generate_word(min_length, max_length)

  67.         # 50% 的概率添加数字或特殊后缀
  68.         if random.random() < 0.5:
  69.             if random.random() < 0.7:  # 70% 概率添加数字
  70.                 username += str(random.randint(0, 999)).zfill(random.randint(2, 3))
  71.             else:  # 30% 概率添加特殊后缀
  72.                 username += random.choice(self.username_suffixes)

  73.         return username

  74.     def generate_combined_username(self, num_words=1, separator="_"):
  75.         """生成完整的组合用户名"""
  76.         # 首先生成基础用户名
  77.         base_username = self.generate_random_username()

  78.         # 生成额外的随机单词
  79.         words = [self.generate_word() for _ in range(num_words)]

  80.         # 随机决定用户名放在前面还是后面
  81.         if random.random() < 0.5:
  82.             words.append(base_username)
  83.         else:
  84.             words.insert(0, base_username)

  85.         return separator.join(words)


  86. class MailTmClient:
  87.     baseurl = "https://api.mail.tm"

  88.     def __init__(self, user=None):
  89.         # 初始化token为None,防止未设置时引发属性错误
  90.         self.token = None
  91.         self.acount = None

  92.         if user is None:
  93.             generator = WordGenerator()
  94.             user = generator.generate_combined_username(1)

  95.         # 重试机制
  96.         for attempt in range(3):
  97.             try:
  98.                 domain = self.get_domains()
  99.                 if not domain:
  100.                     logger.warning(f"尝试 {attempt + 1}/3: 获取域名失败,重试中...")
  101.                     time.sleep(2)
  102.                     continue

  103.                 logger.info("Get domain:" + domain)
  104.                 self.acount = user + "@" + domain
  105.                 logger.info("Get acount:" + self.acount)

  106.                 account_result = self.acounts(self.acount)
  107.                 if not account_result:
  108.                     logger.warning(f"尝试 {attempt + 1}/3: 创建账户失败,重试中...")
  109.                     time.sleep(2)
  110.                     continue

  111.                 token_result = self.get_token(self.acount)
  112.                 if not token_result:
  113.                     logger.warning(f"尝试 {attempt + 1}/3: 获取令牌失败,重试中...")
  114.                     time.sleep(2)
  115.                     continue

  116.                 # 成功初始化
  117.                 break
  118.             except Exception as e:
  119.                 logger.error(f"初始化邮箱客户端出错 (尝试 {attempt + 1}/3): {str(e)}")
  120.                 if attempt < 2:  # 如果不是最后一次尝试,则等待后重试
  121.                     time.sleep(3)
  122.                 else:
  123.                     raise Exception(f"初始化邮箱客户端失败,已重试3次: {str(e)}")

  124.         # 检查是否成功初始化
  125.         if not self.token or not self.acount:
  126.             raise Exception("邮箱客户端初始化失败: token或账户未成功创建")

  127.     def get_email(self):
  128.         return self.acount

  129.     def get_domains(self):
  130.         try:
  131.             response = requests.get(f"{self.baseurl}/domains", timeout=10)
  132.             if response.status_code != 200:
  133.                 logger.error(f"获取域名失败: 状态码 {response.status_code}")
  134.                 return None

  135.             response_data = response.json()
  136.             if (
  137.                 "hydra:member" not in response_data
  138.                 or len(response_data["hydra:member"]) == 0
  139.             ):
  140.                 logger.error("获取域名失败: 返回数据结构异常")
  141.                 return None

  142.             return response_data["hydra:member"][0]["domain"]
  143.         except Exception as e:
  144.             logger.error(f"获取域名时出错: {str(e)}")
  145.             return None

  146.     def acounts(self, acount):
  147.         try:
  148.             json_data = {
  149.                 "address": acount,
  150.                 "password": "thisispassword",
  151.             }
  152.             response = requests.post(
  153.                 "https://api.mail.tm/accounts", json=json_data, timeout=10
  154.             )

  155.             if response.status_code != 201 and response.status_code != 200:
  156.                 logger.error(f"创建账户失败: 状态码 {response.status_code}")
  157.                 if response.text:
  158.                     logger.info("acounts:" + response.text)
  159.                 return None

  160.             if not response.text:
  161.                 logger.error("创建账户失败: 空响应")
  162.                 return None

  163.             logger.info("acounts:" + response.text)
  164.             return response.json()
  165.         except requests.exceptions.RequestException as e:
  166.             logger.error(f"创建账户请求出错: {str(e)}")
  167.             return None
  168.         except ValueError as e:
  169.             logger.error(f"解析账户响应出错: {str(e)}")
  170.             return None

  171.     def get_token(self, acount):
  172.         try:
  173.             json_data = {
  174.                 "address": acount,
  175.                 "password": "thisispassword",
  176.             }

  177.             response = requests.post(
  178.                 "https://api.mail.tm/token", json=json_data, timeout=10
  179.             )

  180.             if response.status_code != 200:
  181.                 logger.error(f"获取令牌失败: 状态码 {response.status_code}")
  182.                 if response.text:
  183.                     logger.info("get_token:" + response.text)
  184.                 return None

  185.             if not response.text:
  186.                 logger.error("获取令牌失败: 空响应")
  187.                 return None

  188.             logger.info("get_token:" + response.text)
  189.             response_data = response.json()

  190.             if "token" not in response_data:
  191.                 logger.error("获取令牌失败: 返回数据中无token字段")
  192.                 return None

  193.             self.token = response_data["token"]
  194.             return self.token
  195.         except requests.exceptions.RequestException as e:
  196.             logger.error(f"获取令牌请求出错: {str(e)}")
  197.             return None
  198.         except ValueError as e:
  199.             logger.error(f"解析令牌响应出错: {str(e)}")
  200.             return None

  201.     def getmessage(self):
  202.         try:
  203.             # 先检查token是否存在
  204.             if not hasattr(self, "token") or self.token is None:
  205.                 logger.error("获取消息失败: token未初始化")
  206.                 return None

  207.             headers = {
  208.                 "accept": "*/*",
  209.                 "accept-language": "zh-CN,zh;q=0.9",
  210.                 "authorization": "Bearer " + self.token,
  211.                 "cache-control": "no-cache",
  212.                 "origin": "https://mail.tm",
  213.                 "pragma": "no-cache",
  214.                 "priority": "u=1, i",
  215.                 "referer": "https://mail.tm/",
  216.                 "sec-ch-ua": '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
  217.                 "sec-ch-ua-mobile": "?0",
  218.                 "sec-ch-ua-platform": '"Windows"',
  219.                 "sec-fetch-dest": "empty",
  220.                 "sec-fetch-mode": "cors",
  221.                 "sec-fetch-site": "same-site",
  222.                 "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
  223.             }
  224.             response = requests.get(
  225.                 "https://api.mail.tm/messages", headers=headers, timeout=10
  226.             )

  227.             if response.status_code != 200:
  228.                 logger.error(f"获取消息失败: 状态码 {response.status_code}")
  229.                 return None

  230.             response_data = response.json()

  231.             if (
  232.                 "hydra:totalItems" in response_data
  233.                 and response_data["hydra:totalItems"] > 0
  234.             ):
  235.                 return response_data["hydra:member"][0]["intro"]
  236.             else:
  237.                 return None
  238.         except Exception as e:
  239.             logger.error(f"获取消息时出错: {str(e)}")
  240.             return None

  241.     def wait_getmessage(self, max_wait_time=60):  # 缩短默认等待时间为60秒
  242.         # 先检查token是否初始化
  243.         if not hasattr(self, "token") or self.token is None:
  244.             logger.error("等待消息失败: token未初始化")
  245.             return None

  246.         start_time = time.time()
  247.         check_count = 0

  248.         while True:
  249.             try:
  250.                 message = self.getmessage()
  251.                 if message is not None:
  252.                     return message

  253.                 # 检查是否超时
  254.                 if time.time() - start_time > max_wait_time:
  255.                     logger.error(f"等待消息超时,已等待{max_wait_time}秒")
  256.                     return None

  257.                 check_count += 1
  258.                 if check_count > 15:  # 如果检查超过15次仍未收到邮件,认为邮箱有问题
  259.                     logger.warning(f"多次检查未收到邮件,邮箱可能有问题: {self.acount}")
  260.                     return None

  261.                 logger.info(f"等待邮件中... ({check_count}/15)")
  262.                 time.sleep(2)  # 增加等待时间,减轻请求频率
  263.             except Exception as e:
  264.                 logger.error(f"等待消息时出错: {str(e)}")
  265.                 # 如果是token相关错误,直接返回None
  266.                 if "token" in str(e).lower():
  267.                     logger.error("token错误,放弃当前邮箱")
  268.                     return None
  269.                 time.sleep(2)


  270. class RelingoReg:
  271.     def __init__(self):
  272.         self.mm = MailTmClient()
  273.         self.email = self.mm.get_email()

  274.         ua = UserAgent(platforms="desktop")

  275.         self.headers = {
  276.             "authority": "api.relingo.net",
  277.             "accept": "*/*",
  278.             "content-type": "application/json",
  279.             "origin": "chrome-extension://dpphkcfmnbkdpmgneljgdhfnccnhmfig",
  280.             "sec-fetch-dest": "empty",
  281.             "sec-fetch-mode": "cors",
  282.             "sec-fetch-site": "none",
  283.             "user-agent": ua.random,
  284.             "x-relingo-dest-lang": "en",
  285.             "x-relingo-lang": "zh",
  286.             "x-relingo-platform": "extension",
  287.             "x-relingo-referrer": "https://relingo.net/en/try?relingo-drawer=account",
  288.             "x-relingo-version": "3.16.6",
  289.         }
  290.         self.cookies = {"referrer": referrer}

  291.     def sendcode(self):
  292.         try:
  293.             json_data = {
  294.                 "email": self.email,
  295.                 "type": "LOGIN",
  296.             }

  297.             response = requests.post(
  298.                 "https://api.relingo.net/api/sendPasscode",
  299.                 cookies=self.cookies,
  300.                 headers=self.headers,
  301.                 json=json_data,
  302.                 timeout=10,
  303.             )

  304.             if response.status_code != 200:
  305.                 logger.error(f"发送验证码失败: 状态码 {response.status_code}")
  306.                 return False

  307.             logger.info("Relingo_SendCode:" + response.text)
  308.             return True
  309.         except Exception as e:
  310.             logger.error(f"发送验证码时出错: {str(e)}")
  311.             return False

  312.     def reg(self, code):
  313.         try:
  314.             json_data = {
  315.                 "type": "PASSCODE",
  316.                 "email": self.email,
  317.                 "code": code,
  318.                 "referrer": referrer,
  319.             }

  320.             response = requests.post(
  321.                 "https://api.relingo.net/api/login",
  322.                 cookies=self.cookies,
  323.                 headers=self.headers,
  324.                 json=json_data,
  325.                 timeout=10,
  326.             )

  327.             if response.status_code != 200:
  328.                 logger.error(f"注册失败: 状态码 {response.status_code}")
  329.                 return False

  330.             logger.info("Relingo_Reg:" + response.text)
  331.             return True
  332.         except Exception as e:
  333.             logger.error(f"注册时出错: {str(e)}")
  334.             return False

  335.     def start(self):
  336.         try:
  337.             if not self.sendcode():
  338.                 logger.error("发送验证码失败")
  339.                 return False

  340.             # 等待并获取验证码
  341.             message = self.mm.wait_getmessage(180)  # 最多等待3分钟

  342.             if not message:
  343.                 logger.error("未收到验证码邮件")
  344.                 return False

  345.             logger.info("Get message:" + message)
  346.             result = re.search(r"\d+", message)

  347.             if result:
  348.                 code = result.group(0)
  349.                 return self.reg(code)
  350.             else:
  351.                 logger.error("无法从邮件中提取验证码")
  352.                 return False
  353.         except Exception as e:
  354.             logger.error(f"注册出错: {str(e)}")
  355.             return False


  356. def register_task(task_id, success_counter):
  357.     try:
  358.         logger.info(f"任务 {task_id} 开始注册")

  359.         # 添加重试机制
  360.         for attempt in range(5):  # 增加到5次尝试
  361.             try:
  362.                 # 创建RelingoReg对象,可能会失败
  363.                 try:
  364.                     relingoreg = RelingoReg()
  365.                 except Exception as e:
  366.                     logger.error(f"创建RelingoReg对象失败: {str(e)}")
  367.                     # 如果是最后一次尝试,则抛出异常,否则重试
  368.                     if attempt >= 4:
  369.                         raise
  370.                     continue

  371.                 # 开始注册过程
  372.                 result = relingoreg.start()

  373.                 if result:
  374.                     with success_counter_lock:
  375.                         success_counter[0] += 1
  376.                     logger.success(
  377.                         f"任务 {task_id} 注册成功! 总成功次数: {success_counter[0]}"
  378.                     )
  379.                     return True
  380.                 else:
  381.                     logger.warning(f"任务 {task_id} 注册失败 (尝试 {attempt + 1}/5)")
  382.                     # 不等待,直接尝试新邮箱
  383.                     logger.info(f"任务 {task_id} 跳过当前邮箱,尝试新邮箱")
  384.             except Exception as e:
  385.                 logger.error(
  386.                     f"任务 {task_id} 发生错误 (尝试 {attempt + 1}/5): {str(e)}"
  387.                 )
  388.                 if attempt < 4:  # 如果不是最后一次尝试,则继续
  389.                     time.sleep(1)

  390.         logger.error(f"任务 {task_id} 失败,已重试5次")
  391.         return False
  392.     except Exception as e:
  393.         logger.error(f"任务 {task_id} 发生严重错误: {str(e)}")
  394.         return False


  395. if __name__ == "__main__":
  396.     success_counter = [0]  # 使用列表存储计数器,方便在线程间共享
  397.     success_counter_lock = threading.Lock()  # 线程锁,防止计数冲突

  398.     fail_counter = [0]  # 失败计数器
  399.     fail_counter_lock = threading.Lock()  # 线程锁

  400.     # 配置日志
  401.     logger.remove()
  402.     logger.add(
  403.         "relingo_reg_{time}.log",
  404.         rotation="100 MB",
  405.         level="INFO",
  406.         format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level}</level> | <cyan>{message}</cyan>",
  407.     )
  408.     logger.add(
  409.         lambda msg: print(msg, end=""),
  410.         level="INFO",
  411.         format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level}</level> | <cyan>{message}</cyan>",
  412.     )

  413.     logger.info("Relingo自动注册程序开始运行...")
  414.     logger.info("按 Ctrl+C 停止程序")

  415.     task_id = 0
  416.     max_workers = 3  # 减少并发数,避免API限制

  417.     # 添加任务间延迟,避免同时发起大量请求
  418.     task_delay = 1  # 减少任务延迟到1秒

  419.     try:
  420.         with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
  421.             while True:
  422.                 # 提交任务到线程池
  423.                 futures = []
  424.                 for i in range(max_workers):
  425.                     task_id += 1
  426.                     # 添加任务间延迟
  427.                     time.sleep(task_delay)
  428.                     futures.append(
  429.                         executor.submit(register_task, task_id, success_counter)
  430.                     )

  431.                 # 等待所有任务完成
  432.                 complete_count = 0
  433.                 for future in concurrent.futures.as_completed(futures):
  434.                     result = future.result()
  435.                     if not result:
  436.                         with fail_counter_lock:
  437.                             fail_counter[0] += 1
  438.                     complete_count += 1
  439.                     # 显示进度
  440.                     logger.info(f"当前批次完成: {complete_count}/{len(futures)}")

  441.                 logger.info(
  442.                     f"当前总成功次数: {success_counter[0]} | 失败次数: {fail_counter[0]}"
  443.                 )
  444.                 time.sleep(3)  # 批次间间隔时间缩短到3秒
  445.     except KeyboardInterrupt:
  446.         logger.info("程序被用户中断")
  447.         logger.info(
  448.             f"总共成功注册 {success_counter[0]} 个账号 | 失败 {fail_counter[0]} 次"
  449.         )
  450.     except Exception as e:
  451.         logger.error(f"程序发生错误: {str(e)}")
  452.     finally:
  453.         logger.info(
  454.             f"程序结束,总成功次数: {success_counter[0]} | 失败次数: {fail_counter[0]}"
  455.         )
复制代码
爱生活,爱奶昔~
回复

使用道具 举报

发表于 2025-4-13 15:27:09 | 查看全部
Relingo_SendCode:{"code":2219,"message":"Email cannot be send"}
爱生活,爱奶昔~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

© 2025 Nyarime 沪ICP备13020230号-1|沪公网安备 31010702007642号手机版小黑屋RSS
返回顶部 关灯 在本版发帖
快速回复 返回顶部 返回列表