Last active
April 20, 2025 18:20
-
-
Save abraxas86/ad72ba46b6cdd86dc63058bba0c629c2 to your computer and use it in GitHub Desktop.
Export collecitons on itch.io as csv files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Itch Collection CSV Exporter | |
// @namespace https://github.com/abraxas86/tampermonkey-scripts/blob/main/itch.io/ | |
// @version 4.5 | |
// @description Scroll down to the bottom of your collection, click the button, get CSV of your collection! | |
// @author Abraxas86 | |
// @match https://itch.io/c/* | |
// @match https://itch.io/my-purchases | |
// @match https://itch.io/b/* | |
// @match https://itch.io/bundle/* | |
// @match https://itch.io/s/* | |
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js | |
// @require https://raw.githubusercontent.com/eligrey/FileSaver.js/master/src/FileSaver.js | |
// @grant none | |
// @icon https://itch.io//static/images/itchio-square-144.png | |
// ==/UserScript== | |
/* globals jQuery, $, waitForKeyElements, saveAs */ | |
(function() { | |
'use strict'; | |
const games = []; | |
let mode = "null"; | |
let gameID = ""; | |
let imagePath = ""; | |
let Title = ""; | |
let Synopsis = ""; | |
let Author = ""; | |
let Genre = ""; | |
let URL = ""; | |
let Blurb = ""; | |
let output = "gameid,genre,title,author,synopsis,imagepath,url,blurb\n"; | |
let filename = $('.grid_header > h2:nth-child(1)').text(); | |
if(!filename) { | |
filename = $('.stat_header_widget .text_container h2 .object_title').text(); | |
} | |
waitForKeyElements(".game_link", makeRed); | |
if (document.querySelector('[class*=bundle_download_page]')) { | |
mode = "bundle"; | |
} else if (document.querySelector('[class*=game_list]')) { | |
mode = "list"; | |
} else if (document.querySelector('[id^=game_grid]') || document.querySelector('[class*=bundle]')) { | |
mode = "grid"; | |
} else { | |
mode = "Error"; | |
} | |
//alert(mode); | |
$('.footer').prepend('<span class="csvButton">Export to CSV</span> <input type="text" id="fileName" class="csvText" value=""> <span class="extension">.csv</span><p></p>'); | |
$('#fileName').attr("value", filename); | |
$('.csvButton').css({'color':'white','background-color':'grey','border-radius':'10px','padding':'15px','cursor':'pointer'}); | |
$('.extension').css({'font-size':'14pt'}); | |
$('.csvText').css({'padding':'5px','border':'none','border-radius':'10px','font-size':'13pt','background-color':'#555555','color':'#BCBCBC','text-align':'right'}); | |
function makeRed() { | |
$('.game_link').css("color", "red"); | |
} | |
$('.csvButton').click(function() { | |
// These elements will mess up our data for the CSV. | |
$('.price_value').remove(); | |
$('.gif_label').remove(); | |
console.log("======= Game Package Data ======="); | |
// GRID MODE | |
if (mode == 'grid') { | |
$('.game_cell').each(function() { | |
const cell = $(this); | |
// Itch Game ID | |
gameID = cell.attr('data-game_id'); | |
console.log("gameID: " + gameID); | |
// Path to thumbnail | |
imagePath = cell.find('.lazy_loaded').attr('src'); | |
console.log("imagePath: " + imagePath); | |
// Game Title Note Note: .title is for bundle compatibility | |
Title = cell.find('.game_title, .title').text().replace(/"/g, '""'); | |
console.log("Title: " + Title); | |
// Game URL Note: .title is for bundle compatibility | |
URL = cell.find('.game_title a, .title').attr('href'); | |
console.log("URL: " + URL); | |
// Game Synopsis Note: .short_text is for bundle compatibility | |
Synopsis = cell.find('.game_text, .short_text').text().replace(/"/g, '""'); | |
console.log("Synopsis: " + Synopsis); | |
// Game Author | |
Author = cell.find('.game_author, .user_link').text().replace(/"/g, '""'); | |
console.log("Author: " + Author); | |
// Game Genre | |
Genre = cell.find('.game_genre').text().replace(/"/g, '""'); | |
console.log("Genre: " + Genre); | |
// Game Blurb (user-created comment about library item) | |
Blurb = cell.find('.blurb_drop').text().trim().replace(/"/g, '""'); | |
console.log("Blurb: " + Blurb); | |
// Build Array to push to CSV File, sanitizing data to prevent commas in scraped data from screwing things up | |
games.push(`"${gameID}","${Genre}","${Title}","${Author}","${Synopsis}","${imagePath}","${URL}","${Blurb}"`); | |
}); | |
} else if (mode == 'list') { | |
$('.game_row').each(function() { | |
const row = $(this); | |
// Game Title | |
Title = row.find('.conversion_link_widget .game_title').text().replace(/"/g, '""'); | |
console.log("Title: " + Title); | |
// Itch Game ID | |
gameID = row.find('.game_cell').attr('data-game_id'); | |
console.log("gameID: " + gameID); | |
// Path to thumbnail | |
imagePath = row.find('.game_thumb').attr('src'); | |
console.log("imagePath: " + imagePath); | |
// Game URL | |
URL = row.find('.game_title').attr('href'); | |
console.log("URL: " + URL); | |
// Game Synopsis (not avaiable in list mode) | |
Synopsis = ""; | |
console.log("Synopsis: " + Synopsis); | |
// Game Author | |
Author = row.find('.author_link').text().replace(/"/g, '""'); | |
console.log("Author: " + Author); | |
// Game Genre | |
Genre = row.find('.game_genre').text().replace(/"/g, '""'); | |
console.log("Genre: " + Genre); | |
// Game Blurb | |
Blurb = row.find('.blurb_drop').text().trim().replace(/"/g, '""'); | |
console.log("Blurb: " + Blurb); | |
// Build Array to push to CSV File, sanitizing data to prevent commas in scraped data from screwing things up | |
games.push(`"${gameID}","${Genre}","${Title}","${Author}","${Synopsis}","${imagePath}","${URL}","${Blurb}"`); | |
}); | |
} else if (mode == 'bundle') { | |
$('.game_row').each(function() { | |
const row = $(this); | |
// Path to thumbnail | |
imagePath = row.find('.game_thumb').attr('data-background_image'); | |
console.log("imagePath: " + imagePath); | |
// Game URL | |
URL = row.find('.game_title a').attr('href'); | |
console.log("URL: " + URL); | |
// Game Title | |
Title = row.find('.game_title a').text().replace(/"/g, '""'); | |
console.log("Title: " + Title); | |
// Game Synopsis | |
Synopsis = row.find('.game_short_text').text().trim().replace(/"/g, '""'); | |
console.log("Synopsis: " + Synopsis); | |
// Game Author | |
Author = row.find('.game_author a').text().replace(/"/g, '""'); | |
console.log("Author: " + Author); | |
// GameID (not available in bundle lists) | |
gameID = ""; | |
console.log("gameID: " + gameID); | |
// Game Blurb (not available in bundle lists) | |
Blurb = ""; | |
console.log("Blurb: " + Blurb); | |
// Build Array to push to CSV File | |
games.push(`"${gameID}","${Genre}","${Title}","${Author}","${Synopsis}","${imagePath}","${URL}","${Blurb}"`); | |
}); | |
} else if (mode == 'bundlegrid') { | |
$('.game_cell').each(function() { | |
const cell = $(this); | |
// Itch Game ID | |
gameID = cell.attr('data-game_id'); | |
console.log("gameID: " + gameID); | |
// Path to thumbnail | |
imagePath = cell.find('.lazy_loaded').attr('src'); | |
console.log("imagePath: " + imagePath); | |
// Game Title | |
Title = cell.find('.game_title').text().replace(/"/g, '""'); | |
console.log("Title: " + Title); | |
// Game URL | |
URL = cell.find('.game_title a').attr('href'); | |
console.log("URL: " + URL); | |
// Game Synopsis | |
Synopsis = cell.find('.game_text').text().replace(/"/g, '""'); | |
console.log("Synopsis: " + Synopsis); | |
// Game Author | |
Author = cell.find('.game_author').text().replace(/"/g, '""'); | |
console.log("Author: " + Author); | |
// Game Genre | |
Genre = cell.find('.game_genre').text().replace(/"/g, '""'); | |
console.log("Genre: " + Genre); | |
// Game Blurb (user-created comment about library item) | |
Blurb = cell.find('.blurb_drop').text().trim().replace(/"/g, '""'); | |
console.log("Blurb: " + Blurb); | |
// Build Array to push to CSV File, sanitizing data to prevent commas in scraped data from screwing things up | |
games.push(`"${gameID}","${Genre}","${Title}","${Author}","${Synopsis}","${imagePath}","${URL}","${Blurb}"`); | |
}); | |
} else { | |
alert("Error: Unable to correctly identify code."); | |
} | |
// Format array for CSV output, sanitizing for titles with commas, | |
// and adding a newline at the end of each title | |
for (let i = 0; i < games.length; i++) { | |
output += games[i] + "\n"; | |
} | |
filename = document.getElementById("fileName").value; | |
if (filename === "") { | |
filename = "collection"; | |
} | |
filename = filename + ".csv"; | |
const blob = new Blob([output], { | |
type: "text/plain;charset=utf-8" | |
}); | |
saveAs(blob, filename); | |
}); | |
})(); |
I just realized Doover25 asked me about bundles 100 days ago today... I must have misunderstood what they meant at the time, but it's working.
4.5
Forgot to remove a line of debug code. The functionality it self was also broken and I didn't catch it. It's good now I hope. It passed the tests I threw at it, at least.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
4.1
Minor bug-fixes. In my attempts to fix the logic, I scuffed up the list-view logic. I also have no idea what I was thinking when I prefixed a bunch of variables with "$" but it was probably due to my brain being on PowerShell at the time 🙃
Anyway, this should be good to go now. My bad for the whoopsies in 4.0. Thanks again for the suggestion and the challenge Glaubits!