embeds your most recent kibun post on your website (instructions at top! no dependencies required)
kibun-embed.js
160 lines 5.0 kB view raw
1/* INSTRUCTIONS: 2add this code snippet somewhere on the page: 3<div id="kibun" data-username="your.username"></div> 4optionally, add the attribute `data-styles="none"` if you just want to theme it yourself 5also optionally, add `data-kibun="hide"` if you don't want to put a link to kibun.social in the bottom corner 6*/ 7 8function timeAgo (dateString) { 9 const date = Date.parse(dateString); 10 const curDate = new Date(date); 11 const now = Date.now(); 12 const yest = new Date(Date.parse(dateString)); 13 const today = new Date(date); 14 yest.setDate(today - 1); 15 const diff = (now - date) / 1000; // difference in seconds 16 if (diff < 5) { 17 return "just now"; 18 } else if (diff < 60) { 19 return `${diff} seconds ago`; 20 } else if (diff < 60*60) { 21 const min = Math.floor(diff / 60); 22 return `${min} minute${min > 1 ? 's' : ''} ago`; 23 } else if (diff < 60*60*24) { 24 const hr = Math.floor(diff / (60*60)); 25 return `${hr} hour${hr > 1 ? 's' : ''} ago`; 26 } else if (date.getDate() === yest.getDate() && date.getMonth() === yest.getMonth() && date.getYear() === yest.getYear()) { 27 return "yesterday"; 28 } 29 return `${curDate.toLocaleDateString(undefined, { 30 weekday: 'short', 31 year: 'numeric', 32 month: 'short', 33 day: 'numeric' 34 }).toLowerCase()}`; 35} 36 37async function getLatest() { 38 const kibunBase = document.getElementById('kibun'); 39 const username = kibunBase.getAttribute('data-username'); 40 const userDidData = await fetch(`https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${username}`); 41 const userDidDoc = await userDidData.json(); 42 const userDid = userDidDoc.did; 43 const userPds = userDidDoc.pds; 44 const userInfoReq = await fetch(` 45 ${userPds}/xrpc/com.atproto.repo.getRecord?repo=${userDid}&collection=app.bsky.actor.profile&rkey=self`); 46 const userInfoData = await userInfoReq.json(); 47 const displayName = userInfoData.value.displayName; 48 console.log(userInfoData); 49 const statusData = await fetch(`${userPds}/xrpc/com.atproto.repo.listRecords?repo=${userDid}&collection=social.kibun.status&limit=1`); 50 const statuses = await statusData.json(); 51 if (statuses.records.length === 0) return; 52 const status = statuses.records[0]; 53 const container = document.createElement('div'); 54 container.id = 'kibun-container'; 55 56 const header = document.createElement('div'); 57 header.id = 'kibun-header'; 58 59 const userLink = document.createElement('a'); 60 userLink.href = `https://www.kibun.social/users/${username}`; 61 userLink.textContent = displayName; 62 userLink.id = 'kibun-displayname'; 63 64 console.log(status.value.createdAt); 65 const parsedDate = Date.parse(status.value.createdAt); 66 const postTime = document.createElement('span'); 67 postTime.textContent = timeAgo(status.value.createdAt); 68 postTime.id = 'kibun-datetime'; 69 70 const emoji = status.value.emoji; 71 const emojiSign = document.createElement('span') 72 emojiSign.textContent = emoji; 73 emojiSign.id = 'kibun-emoji'; 74 75 const userHandle = document.createElement('a'); 76 userHandle.href = `https://kibun.social/users/${username}`; 77 userHandle.textContent = '@'+username; 78 userHandle.id = 'kibun-handle'; 79 80 header.append(userLink); 81 header.append(emojiSign); 82 header.append(userHandle); 83 header.append(postTime); 84 container.append(header); 85 86 const statusText = document.createElement('div'); 87 statusText.textContent = status.value.text; 88 statusText.id = 'kibun-status'; 89 container.append(statusText); 90 91 if (kibunBase.getAttribute('data-kibun') !== 'hide') { 92 const kibunLink = document.createElement('a'); 93 kibunLink.id = 'kibun-link'; 94 kibunLink.href = 'https://www.kibun.social/'; 95 kibunLink.setAttribute('target', '_blank'); 96 kibunLink.setAttribute('rel', 'external'); 97 kibunLink.textContent = 'kibun.social'; 98 container.append(kibunLink); 99 } 100 101 if (kibunBase.getAttribute('data-styles') !== 'none') { 102 const styles = document.createElement('style'); 103 styles.setAttribute('type', 'text/css'); 104 styles.innerHTML = ` 105 #kibun-container { 106 border: 1px #7dd3fc solid; 107 box-shadow: 4px 4px 0 #7dd3fc; 108 padding: 20px; 109 max-width: 400px; 110 background-color: #FFFFFF; 111 font-family: 'Inter', 'San Francisco', 'Lucida Grande', Arial, sans-serif; 112 font-size: 14px; 113 position: relative; 114 } 115 116 #kibun-header { 117 display: flex; 118 gap: 10px; 119 align-items: center; 120 flex-wrap: wrap; 121 } 122 123 #kibun-displayname { 124 color: black; 125 font-weight: bold; 126 } 127 128 #kibun-handle { 129 color: #666666; 130 font-size: .8em; 131 } 132 133 #kibun-datetime { 134 color: #666666; 135 font-size: .8em; 136 } 137 138 #kibun-datetime:before { 139 content: "•"; 140 margin-right: 10px; 141 } 142 143 #kibun-status { 144 margin-top: 10px; 145 } 146 147 #kibun-link { 148 position: absolute; 149 bottom: 5px; 150 right: 5px; 151 font-size: .6em; 152 color: #666666; 153 } 154 `; 155 document.body.append(styles); 156 } 157 document.body.append(container); 158} 159 160getLatest();