Skip to content

Instantly share code, notes, and snippets.

@aequabit
Last active August 28, 2020 17:54
Show Gist options
  • Save aequabit/f3fb70a5d4a94d86ce30c6ed3bd2d235 to your computer and use it in GitHub Desktop.
Save aequabit/f3fb70a5d4a94d86ce30c6ed3bd2d235 to your computer and use it in GitHub Desktop.
Twitter Following Dumper
/**
* twitter-following-dumper
*
* output format is json { uid: string <user id>, handle: string <handle> }
*
* usage:
* - open chrome devtools
* - go to networking tab
* - go to https://twitter.com/following
* - scroll to the bottom of the page
* - right click any request -> "save all as har with content"
* - place in ./twitter.com.har
* - run script
*/
const fs = require("fs");
const path = require("path");
const harDump = (() => {
if (!fs.existsSync(path.join(__dirname, "twitter.com.har"))) {
console.error("input file ./twitter.com.har not found")
process.exit(1);
}
const harDumpRaw = fs.readFileSync(path.join(__dirname, "twitter.com.har"));
let harDump = null;
try {
harDump = JSON.parse(harDumpRaw);
} catch (e) {
console.error("failed to parse har dump")
process.exit(2);
}
return harDump;
})();
const results = [];
for (const harEntry of harDump.log.entries) {
if (!harEntry.request.url.includes("Following?variables=")) continue;
if (harEntry.response.content.size === 0) continue;
const dataSet = JSON.parse(harEntry.response.content.text);
if (dataSet.data === undefined) continue;
// iterate over timeline data
for (const instruction of dataSet.data.user.following_timeline.timeline.instructions) {
if (instruction.entries === undefined) continue;
// iterate over entries
for (const entry of instruction.entries) {
if (entry.content.itemContent === undefined) continue;
// extract user id and handle
const uid = entry.content.itemContent.user.rest_id;
const handle = entry.content.itemContent.user.legacy.screen_name;
// entry was already logged
if (results.find(e => e.uid === uid)) continue;
results.push({ uid, handle });
console.log(`found ${handle} (${uid})`);
}
}
}
console.log(`dumped ${results.length} entries`)
// create results directory if neccessary
if (!fs.existsSync(path.join(__dirname, "results"))) fs.mkdirSync(path.join(__dirname, "results"))
// write the results
fs.writeFileSync(path.join(__dirname, "results", `twitter-following-${Date.now()}.json`), JSON.stringify(results));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment