2024-05-10 07:08:16 +00:00
/*/
Type: file
Content-Type: application/javascript
2024-05-10 23:01:03 +00:00
Title: Fediverse script
Location: /fediverse.js
2024-05-10 07:08:16 +00:00
/**/
const SUBSCRIBE_LINK_REL = 'http://ostatus.org/schema/1.0/subscribe'
2024-05-11 06:41:57 +00:00
const AVATAR_LINK_REL = 'http://webfinger.net/rel/avatar'
class FediSocial extends HTMLElement {
constructor() {
// Always call super first in constructor
super();
2024-05-11 02:43:50 +00:00
}
2024-05-11 06:41:57 +00:00
connectedCallback() {
const data = JSON.parse(localStorage.getItem('fedi-social') || '{}')
let img;
if(data.avatar) {
img = document.createElement('img')
img.src = data.avatar || "https://upload.wikimedia.org/wikipedia/commons/9/93/Fediverse_logo_proposal.svg"
}
else {
img = document.createElement('i')
img.classList.add('omg-icon', 'omg-fediverse')
}
const summary = document.createElement('summary')
summary.appendChild(img)
const details = document.createElement('details')
details.appendChild(summary)
// popup
const div = document.createElement('div')
div.classList.add('card', 'popover')
if(data.id) {
//logout
const p = document.createElement('p')
p.innerHTML = `Hey again, ${data.name} 👋`
div.appendChild(p)
const button = document.createElement('button')
button.innerText = "Forget me"
button.addEventListener('click', ev => { localStorage.clear(); window.location.reload() })
div.appendChild(button)
2024-05-11 02:43:50 +00:00
2024-05-10 07:08:16 +00:00
}
else {
2024-05-11 06:41:57 +00:00
const p = document.createElement('p')
p.innerHTML = "Hey 👋, < br / > please enter your fediverse / mastodon handle below. "
const form = document.createElement('form')
form.addEventListener('submit', this.login)
const input = document.createElement('input')
input.type = 'text'
input.name = 'handle'
input.placeholder = '@user@domain.social'
form.appendChild(input)
const button = document.createElement('input')
button.type = 'submit'
button.value = 'Submit'
form.appendChild(button)
div.appendChild(p)
div.appendChild(form)
2024-05-10 07:08:16 +00:00
}
2024-05-11 06:41:57 +00:00
details.appendChild(div)
this.appendChild(details)
2024-05-10 07:08:16 +00:00
}
2024-05-10 23:01:03 +00:00
2024-05-11 06:41:57 +00:00
login(ev) {
ev.preventDefault()
const input = this.elements['handle'].value
let handle = input.trim().replace(/^@/,'')
const split = handle.split('@')
if(split.length == 2) {
const resource = `acct:${handle}`
const domain = split[1]
// look up remote user via webfinger
const url = `https://${domain}/.well-known/webfinger?resource=${resource}`
return fetch(url, {headers: {
'Accept': 'application/json'
}}).then(async result => {
const json = await result.json()
console.log(json)
const template = json.links.find(link => link.rel & & link.rel == SUBSCRIBE_LINK_REL)?.template
const avatar = json.links.find(link => link.rel & & link.rel == AVATAR_LINK_REL)?.href
const id = json.links.find(link => link.rel & & link.rel == "self" & & link.type == "application/activity+json")?.href
2024-05-11 02:43:50 +00:00
2024-05-11 06:41:57 +00:00
const data = { id, template, avatar, name: input }
localStorage.setItem('fedi-social', JSON.stringify(data))
window.location.reload()
})
.catch(e => {
console.error(e)
this.parentElement.querySelector('p').innerHTML = `Sorry, we couldn't find details for ${input}.\n\nTo interact with posts, try searching for their url on ${domain} (or in your fediverse client of choice)`
return null
})
2024-05-11 02:43:50 +00:00
}
else {
2024-05-11 06:41:57 +00:00
this.parentElement.querySelector('p').innerHTML = `Please enter your fediverse address in @user@domain.social format`
2024-05-11 02:43:50 +00:00
}
2024-05-11 06:41:57 +00:00
}
clicked(ev) {
ev.preventDefault()
console.log("Ow! You clicked me!")
}
2024-05-11 02:43:50 +00:00
}
2024-05-11 06:41:57 +00:00
customElements.define('fedi-social', FediSocial)
function fediverse() {
const data = JSON.parse(localStorage.getItem('fedi-social') || '{}')
2024-05-11 11:47:07 +00:00
document.querySelectorAll("a.external_url:not([href='{external_url}'])").forEach(async (el) => {
2024-05-11 06:41:57 +00:00
if(data.template){
2024-05-11 11:47:07 +00:00
const orig_href = el.href
let href = data.template.replace("{uri}", orig_href)
el.href = href
try{
const res = await fetch(`https://monrepos.casa/api/v2/search?type=statuses& q=${orig_href}`, {
headers: {
'Authorization': 'Basic Ym90OjJuUmZhTGJ1c3cyaFhA'
}
})
const json = await res.json()
const status = json?.statuses?.find(s => s.uri == orig_href)
if(status) {
const innerHTML = `
< a href = '${href}' target = "_blank" > < i class = "fa fa-comment" > < / i > ${status?.replies_count}< / a >
< a href = '${href}' target = "_blank" > < i class = "fa fa-star" > < / i > ${status?.favourites_count}< / a >
< a href = '${href}' target = "_blank" > < i class = "fa fa-retweet" > < / i > ${status?.reblogs_count}< / a >
`
const span = document.createElement('span')
span.classList.add('fediverse')
span.innerHTML = innerHTML
el.insertAdjacentElement('afterend', span)
el.remove()
}
}
catch(ex){
console.error(ex)
}
2024-05-11 06:41:57 +00:00
}
else {
el.addEventListener('click', ev =>{
ev.preventDefault()
window.scrollTo({ top: 0, behavior: 'smooth' })
document.querySelector('fedi-social summary').click()
})
}
})
}