Something went wrong. Try again.
Remember when you made an A+ post last year and everyone clapped bailey.tngl.io/remember-when
Something went wrong. Try again.
remember-when index.html
18 kB · 461 lines
HTML
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462<!doctype html><html> <head> <meta charset="utf-8" /> <title>Remember When</title> <meta name="description" content="Remember what you were posting this day last year." /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bluesky-post-embed/dist/core.css" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bluesky-post-embed/themes/dim.css" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bluesky-post-embed/themes/dark.css" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bluesky-post-embed/themes/light.css" /> </head>
<body> <div> <form id="lookupForm"> <h1>Remember when?</h1> <span >Remember what you were posting this day last year and share with others if you log in</span > <br /> <br />
<label>Check someone else's remember when?</label> <input required id="handle" /> <button type="submit">Remember</button> </form> <br /> <button id="signInButton" type="button">Check yours</button> <button id="signOutButton" style="display: none" type="button"> Sign out </button>
<div id="postView"></div> <br />
<button id="remindOthers" style="display: none" type="button"> Remind others (reposts) </button>
<br />
<span >View the source code on <a href="https://tangled.org/pds.dad/remember-when" >tangled</a ></span > </div>
<script type="module"> const production = window.location.host !== "127.0.0.1"; let agent = null; let atClient = null; let loggedInDid = null; let loggedInHandle = null; let rememberWhenPost = null;
import { configureOAuth, createAuthorizationUrl, finalizeAuthorization, OAuthUserAgent, getSession, deleteStoredSession, } from "https://cdn.jsdelivr.net/npm/@atcute/oauth-browser-client/+esm"; import { LocalActorResolver, XrpcHandleResolver, CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver, CompositeHandleResolver, DohJsonHandleResolver, WellKnownHandleResolver, } from "https://cdn.jsdelivr.net/npm/@atcute/identity-resolver/+esm"; import { getPdsEndpoint } from "https://cdn.jsdelivr.net/npm/@atcute/identity/+esm"; import * as TID from "https://cdn.jsdelivr.net/npm/@atcute/tid/+esm"; import { Client, simpleFetchHandler, } from "https://cdn.jsdelivr.net/npm/@atcute/client/+esm"; import blueskyPostEmbed from "https://cdn.jsdelivr.net/npm/bluesky-post-embed/+esm"; import RichtextBuilder from "https://cdn.jsdelivr.net/npm/@atcute/bluesky-richtext-builder/+esm";
const handleResolver = new CompositeHandleResolver({ methods: { dns: new DohJsonHandleResolver({ dohUrl: "https://cloudflare-dns.com/dns-query", }), http: new WellKnownHandleResolver(), }, });
const didResolver = new CompositeDidDocumentResolver({ methods: { plc: new PlcDidDocumentResolver(), web: new WebDidDocumentResolver(), }, });
const constellationClient = new Client({ handler: simpleFetchHandler({ service: "https://constellation.microcosm.blue/", }), });
// ---- OAuth setup ---- const redirectUri = window.location.origin + window.location.pathname;
const oauthScope = "atproto repo:app.bsky.feed.post?action=create"; let clientId; if (production) { clientId = `${window.location.origin}/remember-when/oauth-client-metadata.json`; } else { clientId = `http://localhost?redirect_uri=${encodeURIComponent(redirectUri)}` + `&scope=${encodeURIComponent(oauthScope)}`; } configureOAuth({ metadata: { client_id: clientId, redirect_uri: redirectUri }, identityResolver: new LocalActorResolver({ handleResolver, didDocumentResolver: new CompositeDidDocumentResolver({ methods: { plc: new PlcDidDocumentResolver(), web: new WebDidDocumentResolver(), }, }), }), });
// ---- OAuth callback / session resume on load ---- async function initAuth() { // Check for OAuth callback in hash if (location.hash && location.hash.length > 1) { try { const params = new URLSearchParams( location.hash.slice(1), ); history.replaceState( null, "", location.pathname + location.search, ); const { session } = await finalizeAuthorization(params); setAuthSession(session); console.log(`Signed in as ${loggedInDid}`, "success"); updateAuthUI(); doWork(loggedInDid); return; } catch (err) { // Hash might not be OAuth params, ignore console.warn("OAuth finalize failed:", err); } }
// Try to resume existing session const storedDid = localStorage.getItem("atproto_did"); if (storedDid) { try { const session = await getSession(storedDid, { allowStale: true, }); setAuthSession(session); console.log( `Session resumed for ${loggedInDid}`, "success", ); //todo load in page here updateAuthUI(); doWork(loggedInDid); } catch (err) { localStorage.removeItem("atproto_did"); console.warn("Session resume failed:", err); } } }
function setAuthSession(session) { agent = new OAuthUserAgent(session); atClient = new Client({ handler: agent }); loggedInDid = session.info.sub; localStorage.setItem("atproto_did", loggedInDid); // Resolve handle from DID // resolveOwnHandle(); }
async function lookupIdentifier(event) { try { event.preventDefault(); const identifier = document.getElementById("handle").value; let did; if (identifier.startsWith("did:")) { did = identifier; } else { did = await handleResolver.resolve(identifier); } await doWork(did); } catch (e) { console.error(e); alert("Failed to resolve PDS endpoint: " + e.message); } }
async function doWork(did) { try { const didDoc = await didResolver.resolve(did); const pds = getPdsEndpoint(didDoc); // #atproto_pds await findPostsFromThatDay(did, pds); } catch (e) { console.error(e); alert("Failed to resolve PDS endpoint: " + e.message); } }
async function signIn() { const handle = window.prompt( "Enter your atmosphere handle (e.g. jcsalterego.bsky.social):", ); if (!handle) return; try { const authUrl = await createAuthorizationUrl({ target: { type: "account", identifier: handle.trim() }, scope: oauthScope, });
await new Promise((r) => setTimeout(r, 200)); window.location.assign(authUrl); } catch (err) { console.error(`Auth error: ${err.message}`, "error"); console.error(err); } }
async function signOut() { try { if (agent) await agent.signOut(); } catch { if (loggedInDid) deleteStoredSession(loggedInDid); } localStorage.removeItem("atproto_did"); atClient = null; agent = null; loggedInDid = null; loggedInHandle = null; updateAuthUI(); console.log("Signed out"); }
function updateAuthUI() { const signInButton = document.getElementById("signInButton"); const signOutButton = document.getElementById("signOutButton"); const remindOthersButton = document.getElementById("remindOthers"); if (loggedInDid) { signInButton.style.display = "none"; signOutButton.style.display = "block"; remindOthersButton.style.display = "block"; } else { signInButton.style.display = "block"; signOutButton.style.display = "none"; remindOthersButton.style.display = "none"; } }
async function findPostsFromThatDay(did, pds) { try { const thisDayLastYear = new Date(); thisDayLastYear.setFullYear( thisDayLastYear.getFullYear() - 1, ); thisDayLastYear.setHours(0, 0, 0, 0); console.log(thisDayLastYear); const lastYearTimestamp = thisDayLastYear.getTime() * 1_000; const lastYearTid = TID.create(lastYearTimestamp, 23); console.log(lastYearTid);
const rpc = new Client({ handler: simpleFetchHandler({ service: pds, }), });
const response = await rpc.get( "com.atproto.repo.listRecords", { params: { repo: did, collection: "app.bsky.feed.post", limit: 100, reverse: true, cursor: lastYearTid, }, }, );
const posts = response.data.records; const postsFromThatDay = posts.filter((post) => { let postedDate = new Date(post.value.createdAt); // console.log( // postedDate.getDate(), // thisDayLastYear.getDate(), // );
// console.log( // postedDate.getMonth(), // thisDayLastYear.getMonth(), // );
return ( postedDate.getDate() === thisDayLastYear.getDate() && postedDate.getMonth() === thisDayLastYear.getMonth() && post.value.reply == null ); });
const postsWithReactions = await Promise.all( postsFromThatDay.map(async (post) => { const reactions = await getReactionCounts(post.uri); console.log(reactions); return { ...post, totalReactions: reactions.likes, }; }), );
if (postsWithReactions.length > 0) { const post = postsWithReactions .sort((a, b) => b.totalReactions - a.totalReactions) .slice(0, 1)[0]; rememberWhenPost = post; let bskyPost = document.createElement("bluesky-post"); bskyPost.setAttribute("src", post.uri); document .getElementById("postView") .appendChild(bskyPost); } else { alert("No posts found from that day :("); } } catch (e) { console.error(e); alert("Failed to find posts from that day: " + e.message); } }
async function getReactionCounts(atUri) { const getLikes = await constellationClient.get( "blue.microcosm.links.getBacklinkDids", { params: { subject: atUri, source: "app.bsky.feed.like:subject.uri", }, }, );
const likes = getLikes.data.total;
const getReposts = await constellationClient.get( "blue.microcosm.links.getBacklinkDids", { params: { subject: atUri, source: "app.bsky.feed.repost:subject.uri", }, }, );
const reposts = getReposts.data.total;
return { likes, reposts, total: likes + reposts, }; }
async function remindOthers() { try { const rt = new RichtextBuilder() .addText("Remember when? Get yours here: ") .addLink( "https://bailey.tngl.io/remember-when", "https://bailey.tngl.io/remember-when", ) .addText("\nCreated by: ") .addMention( "@pds.dad", "did:plc:rnpkyqnmsw4ipey6eotbdnnf", );
await atClient.post("com.atproto.repo.createRecord", { input: { repo: loggedInDid, collection: "app.bsky.feed.post", record: { $type: "app.bsky.feed.post", text: rt.text, embed: { $type: "app.bsky.embed.record", record: { cid: rememberWhenPost.cid, uri: rememberWhenPost.uri, }, }, langs: ["en"], facets: rt.facets, createdAt: new Date().toISOString(), }, }, });
alert("Remember when post sent!"); } catch (err) { console.log(`Send failed: ${err.message}`, "error"); alert(`Send failed: ${err.message}`); console.error(err); } }
//Start up code on dom loaded document.addEventListener("DOMContentLoaded", function () { const lookUpForm = document.getElementById("lookupForm"); lookUpForm.addEventListener("submit", lookupIdentifier);
const signInButton = document.getElementById("signInButton"); signInButton.addEventListener("click", signIn);
const signOutButton = document.getElementById("signOutButton"); signOutButton.addEventListener("click", signOut);
const remindOthersButton = document.getElementById("remindOthers"); remindOthersButton.addEventListener("click", remindOthers);
initAuth(); }); </script> </body></html>