Skip to content

Instantly share code, notes, and snippets.

@OutRite
Last active December 25, 2024 04:31
Show Gist options
  • Select an option

  • Save OutRite/7e05f1f702f623683ed22699803cd6e1 to your computer and use it in GitHub Desktop.

Select an option

Save OutRite/7e05f1f702f623683ed22699803cd6e1 to your computer and use it in GitHub Desktop.
Bluesky Profile Creation Date
// ==UserScript==
// @name Profile Creation Date
// @namespace 534
// @match https://bsky.app/*
// @grant GM_addStyle
// @version 1.2
// @author 534
// @description Adds a creation date to profiles on bluesky.
// ==/UserScript==
GM_addStyle(`
.pcd-date {
color: #777;
}
`)
async function get_profile_elem(set_pcda) {
var divs = document.getElementsByTagName('div');
for (i=0; i<divs.length; i++) {
var elem = divs[i];
if (elem.attributes['data-testid'] && elem.attributes['data-testid'].value == 'profileHeaderAviButton') {
var avatar_elem = elem;
}
}
if (!avatar_elem) {
return false;
}
if (avatar_elem.pcdalready) {
return false;
}
var profile_elem = avatar_elem.parentElement.parentElement.children[1];
if (profile_elem.children.length < 3) { // too early
return false;
}
avatar_elem.pcdalready = set_pcda;
return profile_elem;
}
async function inject_profile_date(datetext) {
var profile_elem = await get_profile_elem(true);
if (!profile_elem) {
return;
}
var timediv = document.createElement("div");
timediv.className = "pcd-date";
timediv.innerText = datetext;
profile_elem.append(timediv);
}
async function did2date(did) {
if (!did) {
return false;
}
var response = await fetch(`https://api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${did}`);
var text = await response.text();
var timestamp = JSON.parse(text)['createdAt'];
if (timestamp=="0001-01-01T00:00:00.000Z") {
await inject_profile_date("This user uses did:web.");
console.log(did);
return false;
}
var date = new Date(timestamp);
var options = {
year: 'numeric',
month: 'long',
day: 'numeric'
};
var datestring = date.toLocaleDateString(undefined, options);
await inject_profile_date(`Created on ${datestring}`);
}
async function load_current_profile() {
if (!await get_profile_elem(false)) {
return;
}
// not the best way to do this, but it works
var handle = document.title.split('@');
if (handle.length == 1) {
return;
}
handle = handle[handle.length-1]
handle = handle.split(')')[0].split(' ')[0];
if (handle == 'handle.invalid') {
var did = location.href.split('/profile/')[1];
await did2date(did);
} else {
// broken by handle confusions like samehandle =(
await did2date(handle);
}
}
setInterval(load_current_profile, 750)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment