File size: 4,154 Bytes
49beea7
 
 
6ea77b7
 
49beea7
 
6ea77b7
 
49beea7
 
6ea77b7
49beea7
 
 
6ea77b7
49beea7
 
 
 
 
 
 
 
 
6ea77b7
49beea7
 
 
 
6ea77b7
 
 
49beea7
 
 
 
6ea77b7
 
 
49beea7
 
 
 
6ea77b7
 
49beea7
6ea77b7
49beea7
 
6ea77b7
fdc2595
49beea7
6ea77b7
 
 
fdc2595
 
 
 
 
 
6ea77b7
49beea7
fdc2595
 
 
 
49beea7
 
6ea77b7
 
fdc2595
 
 
 
 
6ea77b7
49beea7
 
 
fdc2595
6ea77b7
 
 
 
 
 
 
 
7863770
 
 
6ea77b7
 
 
 
 
7863770
 
fdc2595
 
 
 
 
 
 
 
 
6ea77b7
 
fdc2595
 
6ea77b7
 
fdc2595
 
 
 
6ea77b7
fdc2595
 
 
6ea77b7
fdc2595
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import requests
import time
import json
import os
import gradio as gr

BASE_URL = "https://codeforces.com/api/"
DATA_FILE = "all_users_data.json"


def fetch_all_users():
    """Fetch all rated users."""
    print("Fetching all rated users...")
    response = requests.get(f"{BASE_URL}user.ratedList?activeOnly=false")
    if response.status_code != 200:
        print(f"Failed to fetch rated users. Status Code: {response.status_code}, Response: {response.text}")
        return []
    users = response.json().get("result", [])
    return [user["handle"] for user in users]


def fetch_user_data(handle):
    """Fetch all available data for a single user."""
    print(f"Fetching data for user: {handle}")
    data = {}

    # Fetch basic user info
    user_info = requests.get(f"{BASE_URL}user.info?handles={handle}")
    if user_info.status_code == 200:
        data["info"] = user_info.json().get("result", [])
    else:
        print(f"Warning: Failed to fetch user info for {handle}. Status Code: {user_info.status_code}, Response: {user_info.text}")

    # Fetch user submissions
    user_status = requests.get(f"{BASE_URL}user.status?handle={handle}")
    if user_status.status_code == 200:
        data["submissions"] = user_status.json().get("result", [])
    else:
        print(f"Warning: Failed to fetch submissions for {handle}. Status Code: {user_status.status_code}, Response: {user_status.text}")

    # Fetch user rating changes
    user_rating = requests.get(f"{BASE_URL}user.rating?handle={handle}")
    if user_rating.status_code == 200:
        data["ratings"] = user_rating.json().get("result", [])
    else:
        print(f"Warning: Failed to fetch rating changes for {handle}. Status Code: {user_rating.status_code}, Response: {user_rating.text}")

    return data


def fetch_and_save_data():
    """Fetch all kinds of data for every user and save it to a file."""
    users = fetch_all_users()
    if not users:
        return "Failed to fetch users. Check logs for errors."

    if os.path.exists(DATA_FILE):
        # Load existing data to resume
        with open(DATA_FILE, "r", encoding="utf-8") as f:
            all_data = json.load(f)
    else:
        all_data = {}

    for i, user in enumerate(users):
        if user in all_data:
            print(f"Skipping already fetched user: {user}")
            continue

        try:
            user_data = fetch_user_data(user)
            if user_data:
                all_data[user] = user_data

            # Save progress to file after each user
            with open(DATA_FILE, "w", encoding="utf-8") as f:
                json.dump(all_data, f, indent=4)

            time.sleep(0.5)  # Respect API rate limit
        except Exception as e:
            print(f"Error fetching data for user {user}: {e}")

    return "Data fetching complete."


def serve_file():
    """Provide the saved file for download."""
    if os.path.exists(DATA_FILE):
        return DATA_FILE
    else:
        return None


# Gradio Interface
def fetch_and_download():
    """Fetch the data and provide a download link."""
    message = fetch_and_save_data()
    file_path = serve_file()
    return message, file_path


def get_file_for_download():
    """Allow the user to download the current work anytime."""
    file_path = serve_file()
    if file_path:
        return file_path
    else:
        return "No data file available."


with gr.Blocks() as interface:
    gr.Markdown("# Codeforces User Data Fetcher")
    gr.Markdown("This tool fetches data for all users from Codeforces and provides a downloadable file. You can fetch data and download progress anytime.")

    with gr.Row():
        fetch_button = gr.Button("Fetch Data")
        output_message = gr.Textbox(label="Status", lines=2)
    
    download_file_button = gr.Button("Download Current Data")
    download_file_output = gr.File(label="Download Data", visible=False)

    # Bind actions to buttons
    fetch_button.click(fetch_and_download, inputs=[], outputs=[output_message, download_file_output])
    download_file_button.click(get_file_for_download, inputs=[], outputs=download_file_output)

interface.launch()