diff --git a/playerLookup.html b/playerLookup.html new file mode 100644 index 0000000..9ff176c --- /dev/null +++ b/playerLookup.html @@ -0,0 +1,36 @@ + + + + + + Chess.com PGN Downloader + + + +

Chess.com PGN Downloader

+ + + + +

+ + + + + + diff --git a/player_games.js b/player_games.js new file mode 100644 index 0000000..44a0b44 --- /dev/null +++ b/player_games.js @@ -0,0 +1,91 @@ +// mainScript.js + +import userAgents from './userAgents.js'; + +// Declare the script variable +// +let script; + +window.downloadPGN = function() { + const username = document.getElementById('usernameInput').value; + + if (!username) { + alert('Please enter a username.'); + return; + } + + // Create a callback function to handle the JSONP response for archives + const archivesCallback = 'handleArchivesResponse'; + window[archivesCallback] = function(data) { + document.head.removeChild(script); // Remove the script element after execution + threddGames(data); // Pass the list of archive URLs to the threaded function + }; + + // Fetch player archives using JSONP + playerArchives(username, archivesCallback); +}; + +function getRandomUserAgent() { + return userAgents[Math.floor(Math.random() * userAgents.length)]; +} + +async function playerArchives(username, callback) { + // Replace 'YOUR_API_KEY' with your Chess.com API key + const url = `https://api.chess.com/pub/player/${username}/games/archives`; + const response = await fetch(url); + const data = await response.json(); + window[callback](data.archives); +} + +async function playerMonthly(url, callback) { + const user_agent = getRandomUserAgent(); + const headers = { + 'User-Agent': user_agent, + }; + + const response = await fetch(url + '/pgn', { headers }); + const games = await response.text(); + window[callback](games); // Execute the callback function with the PGN data +} + +async function threddGames(archiveURLs) { + const gamesList = []; + + // Using Promise.all to wait for all threads to complete + await Promise.all(archiveURLs.map(async (url) => { + return new Promise(async (resolve) => { + const monthlyGamesCallback = 'handleMonthlyGamesResponse'; + window[monthlyGamesCallback] = function(data) { + handleDownload(data, gamesList, resolve); + }; + + // Fetch monthly games using JSONP + await playerMonthly(url, monthlyGamesCallback); + }); + })); + + // Combine and save the games to a file + const pgnDb = gamesList.join('\n\n'); + const username = document.getElementById('usernameInput').value; + createDownloadLink(pgnDb, `${username}.pgn`); +} + +function handleDownload(data, gamesList, resolve) { + gamesList.push(data); + resolve(); // Resolve the promise to indicate completion of this thread +} + +function createDownloadLink(data, filename) { + const blob = new Blob([data], { type: 'application/octet-stream' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = url; + a.download = filename; + + document.body.appendChild(a); + a.click(); + + document.body.removeChild(a); + URL.revokeObjectURL(url); +} diff --git a/player_games.py b/player_games.py deleted file mode 100644 index b584a68..0000000 --- a/player_games.py +++ /dev/null @@ -1,73 +0,0 @@ -import user_agents -import random -import requests -import re -import os -import json -import concurrent.futures - - -def playerArchives(username): - # Create archive list. This is a list of pages containing lists of games used for futher downloading - - user_agent = random.choice(user_agents.user_agents) # load up random user agent from list - headers = { - 'User-Agent':user_agent - } - url = f"https://api.chess.com/pub/player/{username}/games/archives" - archive = requests.get(url, headers=headers).json()['archives'] - - try: - cwd = os.getcwd() - path = os.path.join(cwd, 'archives') - os.makedirs(path) - except OSError: - pass - - file_name = os.path.join(path, username+'_archive.txt') - with open(file_name, 'w') as f: - json.dump(archive, f) - - return archive - - -def playerMonthly(url=None): - - user_agent = random.choice(user_agents.user_agents) # load up random user agent from list - headers = { - 'User-Agent':user_agent - } - - if url: - url=url+'/pgn' # connect to multi-game pgn download endpoint by appending a "pgn" to the url provided by url in archive list - else: - username=input("username: ") - YYYY=input("year in YYYY: ") - MM=input("month in MM: ") - url = f"https://api.chess.com/pub/player/{username}/games/{YYYY}/{MM}/pgn" - - # get and save games list in .pgn format - games = requests.get(url, headers=headers).content.decode("utf-8") - - return games - -# Multithreaded games download -def threddGames(username=None, archive=None): - - if archive: - with open(archive) as f: - archive = json.load(f) - else: - archive = playerArchives(username) - - # async download games - games_list = [] - with concurrent.futures.ThreadPoolExecutor() as executor: - for future in executor.map(playerMonthly, archive): - games_list.extend(future) - pgn_db = "\n\n".join(games_list) - with open(username+'.pgn', 'w') as f: - f.write(pgn_db) - - return pgn_db - diff --git a/test.html b/test.html new file mode 100644 index 0000000..934080e --- /dev/null +++ b/test.html @@ -0,0 +1,39 @@ + + + + + + File Download App + + + + + + + + + diff --git a/user_agents.py b/userAgents.js similarity index 73% rename from user_agents.py rename to userAgents.js index b3b779c..b1008ff 100644 --- a/user_agents.py +++ b/userAgents.js @@ -1,8 +1,14 @@ -user_agents = [ + +// userAgents.js + +const userAgents = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35", "Mozilla/5.0 (Windows NT 6.1; rv:109.0) Gecko/20100101 Firefox/113.0", "Mozilla/5.0 (Android 12; Mobile; rv:109.0) Gecko/113.0 Firefox/113.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0", -] + "mozilla/5.0 (macintosh; intel mac os x 10.15; rv:109.0) gecko/20100101 firefox/113.0", + // Add more user agents as needed +]; + +export default userAgents;