now-updater/index.js

174 lines
4.4 KiB
JavaScript
Raw Normal View History

import 'dotenv/config'
2025-12-18 01:57:14 +00:00
import { items, linkFormat } from './config.js'
import {
getAtomFeed,
getHardcoverActivity,
getJsonFeedItemTitle,
getLetterboxdActivity,
getListenBrainzScrobble,
getMalojaScrobble,
getMastodonPost,
getRSSItemTitle,
2025-12-28 20:51:19 +00:00
getSomePicsPost,
getSourceTubeActivity,
getSteamRecentlyPlayed,
getTraktEpisode,
getTraktMovie,
htmlServiceLinkRegex,
markdownCharEscape,
markdownServiceLinkRegex,
} from './utils.js'
const feedHandlers = {
rss: getRSSItemTitle,
atom: getAtomFeed,
json: getJsonFeedItemTitle,
2025-12-28 20:51:19 +00:00
'some.pics': getSomePicsPost,
'source.tube': getSourceTubeActivity,
mastodon: getMastodonPost,
letterboxd: getLetterboxdActivity,
'trakt-episode': getTraktEpisode,
'trakt-movie': getTraktMovie,
steam: getSteamRecentlyPlayed,
listenbrainz: getListenBrainzScrobble,
maloja: getMalojaScrobble,
hardcover: getHardcoverActivity,
}
2025-12-18 01:57:14 +00:00
const OMGLOL_API = `https://api.omg.lol/address/${process.env.OMGLOL_USERNAME}/now`
2025-12-18 01:57:14 +00:00
export async function getNow() {
const res = await fetch(OMGLOL_API)
const data = await res.json()
return data.response.now.content
2025-12-18 01:57:14 +00:00
}
export async function setNow(newNow) {
const res = await fetch(OMGLOL_API, {
method: 'POST',
2025-12-18 01:57:14 +00:00
headers: {
'Content-Type': 'application/json',
2025-12-18 01:57:14 +00:00
Authorization: `Bearer ${process.env.OMGLOL_KEY}`,
},
body: JSON.stringify({
content: newNow,
listed: 1,
}),
})
const data = await res.json()
console.log(`\n${data.response.message}`)
2025-12-18 01:57:14 +00:00
}
export default async function now() {
const now = await getNow()
let newNow = now
2025-12-18 01:57:14 +00:00
await Promise.all(
items.map(async (item) => {
try {
const handler = feedHandlers[item.feedType]
if (!handler) {
throw new Error(`Unknown feedType: ${item.feedType}`)
}
// build feedUrl from template if provided
let feedUrl = item.feedUrl
if (item.feedUrlTemplate) {
feedUrl = item.feedUrlTemplate
.replace('{userId}', item.userId || '')
.replace('{instance}', item.instance || '')
}
// generic handlers expect just feedUrl string, special handlers expect config object
2025-12-28 20:51:19 +00:00
const handlerParam = [
'rss',
'atom',
'json',
'maloja',
'some.pics',
].includes(item.feedType)
? feedUrl
: { ...item, feedUrl }
const latest = await handler(handlerParam)
console.log(`${item.id}: ${latest.text}`)
console.log(`${item.id} URL: ${latest.url}`)
// Apply markdown escaping only for markdown links
const displayText =
linkFormat === 'html'
? latest.text
: markdownCharEscape(latest.text)
if (latest && latest.text && latest.url) {
// generate regex based on id and linkFormat
const regex =
linkFormat === 'html'
? htmlServiceLinkRegex(item.id)
: markdownServiceLinkRegex(item.id)
newNow = newNow.replace(regex, (match, openTag, closeTag) => {
// Replace href in opening tag
const updatedOpenTag = openTag.replace(
/href=["'][^"']*["']/,
`href="${latest.url}"`,
)
return `${updatedOpenTag}${displayText}${closeTag}`
})
// replace image/video placeholders if available, otherwise remove tags
const imageId = `${item.id}-image`
const videoId = `${item.id}-video`
if (latest.image) {
// html image replacement
newNow = newNow.replace(
new RegExp(`(<img[^>]+src=["'])${imageId}(["'][^>]*>)`, 'gi'),
`$1${latest.image}$2`,
)
// markdown image replacement
newNow = newNow.replace(
new RegExp(`(!\\[[^\\]]*\\]\\()${imageId}(\\))`, 'gi'),
`$1${latest.image}$2`,
)
} else {
// remove img tags if no image available
newNow = newNow.replace(
new RegExp(`<img[^>]+src=["']${imageId}["'][^>]*>`, 'gi'),
'',
)
// remove markdown image
newNow = newNow.replace(
new RegExp(`!\\[[^\\]]*\\]\\(${imageId}\\)`, 'gi'),
'',
)
}
if (latest.video) {
// html video replacement
newNow = newNow.replace(
new RegExp(`(<video[^>]+src=["'])${videoId}(["'][^>]*>)`, 'gi'),
`$1${latest.video}$2`,
)
} else {
// remove video tags if no video available
newNow = newNow.replace(
new RegExp(`<video[^>]*src=["']${videoId}["'][^>]*>[\\s\\S]*?</video>`, 'gi'),
'',
)
}
}
} catch (e) {
2025-12-28 17:29:09 +00:00
console.warn(`⚠️ Failed to fetch ${item.id}`, e)
2025-12-18 01:57:14 +00:00
}
}),
)
2025-12-18 01:57:14 +00:00
if (now === newNow) {
console.log('\nNow page has no changes')
2025-12-18 01:57:14 +00:00
} else {
await setNow(newNow)
2025-12-18 01:57:14 +00:00
}
}
await now()