Last active
August 9, 2024 18:32
-
-
Save tadwohlrapp/73864c03734a14a9d27cc15e4fa142ba to your computer and use it in GitHub Desktop.
Revisions
-
tadwohlrapp renamed this gist
Apr 12, 2024 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
tadwohlrapp created this gist
Apr 12, 2024 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,133 @@ // Get necessary data from the WIZ_global_data window object const sid = window.WIZ_global_data.FdrFJe const bl = window.WIZ_global_data.cfb2h const at = encodeURIComponent(window.WIZ_global_data.SNlM0e) // Get document language and generate random request ID const hl = document.documentElement.lang const reqid = Math.round((Math.random() * 100000) + 300000) // Define the RPC IDs for subscriptions and feed (endpoints for batchexecute calls) const rpcids = { "subscriptions": "Saeaed", "feed": "ncqJEe", } // Define the options for the fetch requests const fetchOptions = body => { return { "headers": { "accept": "*/*", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded;charset=UTF-8", "pragma": "no-cache", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "sec-gpc": "1", "x-same-domain": "1" }, "referrer": "https://podcasts.google.com/", "referrerPolicy": "origin", "body": body, "method": "POST", "mode": "cors", "credentials": "include" } } // Array to store all played episodes const allPlayedEpisodes = [] // Function to get all podcast IDs from the subscriptions async function getAllPodcastIds() { try { // Fetch data from the "subscriptions" endpoint const response = await fetch(`https://podcasts.google.com/_/PodcastsUi/data/batchexecute?rpcids=${rpcids.subscriptions}&source-path=%2Fsubscriptions&f.sid=${sid}&bl=${bl}&hl=${hl}&_reqid=${reqid}`, fetchOptions(`f.req=%5B%5B%5B%22${rpcids.subscriptions}%22%2C%22%5B%5D%22%2Cnull%2C%223%22%5D%5D%5D&at=${at}&`)); const data = await response.text(); // Parse the response data to get the individual podcast IDs const subscriptionsRaw = JSON.parse(JSON.parse(data.replace(")]}'", "").trim())[0][2])[0] const allPodcastIds = [] subscriptionsRaw.forEach((subscription) => { const podcastId = subscription[10] allPodcastIds.push(podcastId) }); // Return the array of podcast IDs return allPodcastIds } catch (err) { console.log(err); } } // Function to get played episodes for a given podcast ID async function getEpisodesPlayed(podcastId) { try { // Fetch data from the "feed" endpoint const response = await fetch(`https://podcasts.google.com/_/PodcastsUi/data/batchexecute?rpcids=${rpcids.feed}&source-path=%2Ffeed%2F${podcastId}&f.sid=${sid}&bl=${bl}&hl=${hl}&_reqid=${reqid + 1000}`, fetchOptions(`f.req=%5B%5B%5B%22${rpcids.feed}%22%2C%22%5B%5C%22${podcastId}%5C%22%5D%22%2Cnull%2C%221%22%5D%5D%5D&at=${at}&`)); const data = await response.text(); // Parse the response data to get the individual episodes const episodesRaw = JSON.parse(JSON.parse(data.replace(")]}'", "").trim())[0][2])[1][0]; const episodesPlayed = []; episodesRaw.forEach((episode) => { // Ignore unplayed episodes if (null != episode[3]) { const podcastName = episode[1]; const episodeName = episode[8]; // Generate row of data containing podcast name, date, episode name and progress const episodeData = [ podcastName.includes(',') ? `"${podcastName}"` : podcastName, new Date(episode[11] * 1000).toISOString().split('T')[0], episodeName.includes(',') ? `"${episodeName}"` : episodeName, episode[3] > 0.95 ? "✅" : Math.round(episode[3] * 100).toString() + "%" ]; episodesPlayed.push(episodeData); } }); // Return the array of played episodes for the podcast return episodesPlayed; } catch (err) { console.log(err); } } // Function to log all played episodes and generate the CSV file async function logAllPlayedEpisodes() { // Get all podcast IDs const allMyIds = await getAllPodcastIds(); // Get played episodes for each podcast ID const allPlayedEpisodes = (await Promise.all(allMyIds.map(async podcastId => { const playedEpisodesInThisPodcast = await getEpisodesPlayed(podcastId); return playedEpisodesInThisPodcast; }))).flatMap(episodes => episodes); // Sort the played episodes: first ASC by podcast name and then DESC by date allPlayedEpisodes.sort((a, b) => { const podcastComparison = a[0].toLowerCase().localeCompare(b[0].toLowerCase()); if (podcastComparison !== 0) { return podcastComparison; } return b[1].localeCompare(a[1]); }); // Generate the CSV content let csvContent = "podcast,date,episode,played\n" + allPlayedEpisodes.map(episode => episode.join(",")).join("\n"); // Download the CSV file const csvBlob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const csvUrl = URL.createObjectURL(csvBlob); const link = document.createElement('a'); link.setAttribute('href', csvUrl); link.setAttribute('download', 'google_podcasts_listening_history.csv'); link.click(); } // Call the function to log all played episodes and generate the CSV file logAllPlayedEpisodes() 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,37 @@ # How to Export your Google Podcasts listening history Since Google doesn't provide any method to export or download your listening history, I wanted to find a way to preserve that data for later reference when setting up a new podcast app. I came up with the following script that can be run in your browser console to retrieve and export your Google Podcasts listening history as a CSV file. ### NEVER RUN CODE YOU DON'T UNDERSTAND. ### Running untrusted code in your browser console can potentially be harmful, so it's important to understand what the code does before executing it. I've included comments in the code to explain its functionality. ## Instructions: 1. Open Google Podcasts (https://podcasts.google.com) in your browser and make sure you're logged in to your account. 2. Right-click anywhere on the page and select "Inspect" or "Inspect Element" to open the browser's developer tools. 3. Navigate to the "Console" tab. 4. Copy and paste the code below into the console and press Enter. 5. The code will fetch your listening history and generate a CSV file named `google_podcasts_listening_history.csv`. Your browser will prompt you to download the file. The generated CSV File has the following format: | podcast | date | episode | played | |:-----------------|:-----------|:-----------------------|-------:| | Some Podcast | 2022-07-04 | #3 Our last episode | ✅| | Some Podcast | 2022-06-01 | #2 JavaScript is weird | ✅| | Some Podcast | 2022-05-02 | #1 Welcome | ✅| | The Best Podcast | 2023-09-16 | 3. Episode three | 56%| | The Best Podcast | 2023-08-29 | 2. Electric Boogaloo | ✅| | The Best Podcast | 2023-08-13 | 1. First Episode | ✅| Columns explained: - **podcast**: Podcast Name (sorted ascending) - **date**: Episode Date (sorted descending for each podcast) - **episode**: Episode Name - **played**: Your listening progress. Either a percentage or if it's anything over 95% then the episode is marked as played fully with a "✅" ## Resources: If you're having trouble understanding or running the code, you can refer to these resources: - [JavaScript Basics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide) - [Using the Browser Console](https://developers.google.com/web/tools/chrome-devtools/console)