Skip to content

Instantly share code, notes, and snippets.

@fdebijl
Last active September 6, 2020 11:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fdebijl/ecf9937a215a8e100d6c4f6ea5d0812f to your computer and use it in GitHub Desktop.
Save fdebijl/ecf9937a215a8e100d6c4f6ea5d0812f to your computer and use it in GitHub Desktop.
Twitter Like Exporter

WARNING: THIS USER SCRIPT NO LONGER WORKS - IT WAS ORIGINALLY MADE FOR THE TWITTER WEBAPP PRE JULY 2019

Download either Tampermonkey for Chrome, or Greasemonkey for Firefox if you want to run this script repeatably:

Tampermonkey: https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo

Greasemonkey: https://addons.mozilla.org/nl/firefox/addon/greasemonkey/

Add the script via the dashboard of Tamper/Greasemonkey, and then simply navigate to https://twitter.com/i/likes to download your own likes, or replace 'i' with any other username to download their likes.

You may alternatively run this script in your console. You can open this in most browsers by pressing F12 on your keyboard, or right clicking anywhere on the page and selecting 'Inspect Element'. Simply paste the script there and press Enter to run it. The easiest way to copy the script is by pressing 'Raw' below on userscript.js and copying all the text.

// ==UserScript==
// @name Twitter Like Exporter
// @namespace https://floris.debijl.xyz/
// @version 1.0
// @description Export all Twitter likes from any account to an CSV file. Warning: really slow with anything over 1000 likes and probably doesn't work with over 8000-ish.
// @author @Fdebijl
// @license GNU Affero General Public License 3.0 https://www.gnu.org/licenses/agpl-3.0.nl.html
// @match https://twitter.com/*/likes
// @match *twitter.com/*/likes
// @match https://twitter.com/i/likes
// @grant none
// ==/UserScript==
(function() {
'use strict';
const $ = window.jQuery;
// Global variables
let totalLikes = 0, currentLikes = 0, interrupt = false, mainTimer, auxTimer, once = false;
// Timing variables
let runningSeconds = 0;
$(document).ready(function() {
totalLikes = $('.ProfileNav-stat[data-nav="favorites"] .ProfileNav-value').data('count');
TaskTimer();
ScrollToEnd();
SetMessageDrawerVisible(true, "Initiating script...");
});
function DoWhenDone() {
SetMessageDrawerVisible(true, "Like retrieval complete, starting download...");
$('.hijacked').off('click');
DownloadCSV(FormulateCSV());
setTimeout(SetMessageDrawerVisible(false), 3000);
}
function SetMessageDrawerVisible(visibility, notificationtext = "") {
if(visibility) {
$('#message-drawer').removeClass('hidden');
$('#message-drawer').addClass('hijacked');
$('.message-text').css('white-space', 'pre-line');
$('#message-drawer').attr('style', 'margin-bottom: -46px !important;');
$('#message-drawer .message-text').text(notificationtext);
// Interrupt when notification is clicked
$('.hijacked').click(function() {
clearTimeout(mainTimer);
clearTimeout(auxTimer);
interrupt = true;
SetMessageDrawerVisible(false);
DoWhenDone();
});
} else if (!visibility) {
$('#message-drawer').addClass('hidden');
$('#message-drawer').removeClass('hijacked');
$('#message-drawer').attr('style', 'margin-bottom: 46px;');
$('#message-drawer .message-text').text(notificationtext);
}
return;
}
function pad(val) {
return val > 9 ? val : "0" + val;
}
function TaskTimer() {
mainTimer = setInterval( function(){
++runningSeconds;
}, 1000);
if (totalLikes > 21) {
auxTimer = setInterval( function(){
SetMessageDrawerVisible(true,
"Retrieving likes: " + currentLikes + "/" + totalLikes + "\n" +
"Estimated time to completion: " + GetTimeToCompletion() + "\n" +
"Click anywhere on this notification to cancel the operation and download the CSV file as-is.");
}, 5000);
}
}
function SecondsToFullTime(seconds) {
let remainingHours = pad(Math.round(seconds / 3600 % 60));
let remainingMinutes = pad(Math.round(seconds / 60 % 60));
let remaingSeconds = pad(Math.round(seconds % 60));
return remainingHours + ":" + remainingMinutes + ":" + remaingSeconds;
}
function GetTimeToCompletion() {
let secondsPerLike = runningSeconds / currentLikes;
let remainingLikes = totalLikes - currentLikes;
return SecondsToFullTime(secondsPerLike * remainingLikes);
}
function ScrollToEnd() {
if (interrupt) {
return;
}
if ($('.timeline-end').hasClass('has-more-items') === false || interrupt) {
DoWhenDone();
console.log("Done loading likes");
return;
}
setTimeout(function() {
$('html, body').animate({
scrollTop: $(document).height()},
2500,
"swing"
);
currentLikes = $('.stream-item > .tweet').length;
ScrollToEnd();
}, 2500);
}
function FormulateCSV() {
let csv = "username,following,follows me,tweetid,userid" + "\n";
$('.stream-item > .tweet').each(function(index) {
csv += $(this).data("screenName") + "," + $(this).data("youFollow") + "," + $(this).data("followsYou") + "," + $(this).data("tweetId") + "," + $(this).data("userId") + "\n";
});
return csv;
}
function DownloadCSV(dlstring) {
if (!once) {
once = true;
let blob = new Blob([dlstring], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, "likes.csv");
} else {
var link = document.createElement("a");
if (link.download !== undefined) {
let url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", "likes.csv");
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment