now-updater/utils.js

156 lines
5 KiB
JavaScript

import 'dotenv/config'
import { JSDOM } from 'jsdom'
import sanitizeHtml from 'sanitize-html'
export function markdownLinkRegex(url) {
return new RegExp(
`(\\[).*?(\\]\\(https:\\/\\/${url.replaceAll('.', '\\.')}\\))`,
'i',
)
}
export function htmlLinkRegex(url) {
const escapedUrl = url.replaceAll('.', '\\.')
return new RegExp(
`(<a[^>]+href=["']https?:\\/\\/${escapedUrl}[^"']*["'][^>]*>).*?(<\\/a>)`,
'i',
)
}
export function markdownCharEscape(text) {
return text
.replaceAll('`', '\\`')
.replaceAll('*', '\\*')
.replaceAll('_', '\\_')
.replaceAll('{', '\\{')
.replaceAll('}', '\\}')
.replaceAll('[', '\\[')
.replaceAll(']', '\\]')
.replaceAll('(', '\\(')
.replaceAll(')', '\\)')
.replaceAll('#', '\\#')
.replaceAll('+', '\\+')
.replaceAll('-', '\\-')
.replaceAll('.', '\\.')
.replaceAll('!', '\\!')
}
export async function getRSSItemTitle(feedUrl) {
const res = await fetch(feedUrl)
const data = await res.text()
const dom = new JSDOM(data, { contentType: 'text/xml' })
const item = dom.window.document.querySelector('item')
const title = item.querySelector('title').textContent
const link = item.querySelector('link').textContent.trim()
const cleanTitle = markdownCharEscape(
sanitizeHtml(title, {
allowedTags: [],
allowedAttributes: {},
})?.trim(),
)
return { text: cleanTitle, url: link }
}
export async function getJsonFeedItemTitle(feedUrl, showImage = true) {
const res = await fetch(feedUrl)
const data = await res.json()
const post = data.items[0]
const { title, image, url } = post
const cleanTitle = markdownCharEscape(title)
const text = !showImage
? cleanTitle
: image
? `${cleanTitle} ![${cleanTitle}](${image})`
: cleanTitle
return { text, url }
}
export async function getJsonFeedItemContent(feedUrl, showImage = true) {
const res = await fetch(feedUrl)
const data = await res.json()
const post = data.items[0]
const { content_html, image } = post
const title = sanitizeHtml(content_html, {
allowedTags: [],
allowedAttributes: {},
})?.trim()
const cleanTitle = markdownCharEscape(title)
if (!showImage) {
return cleanTitle
}
return image ? `${cleanTitle} ![${cleanTitle}](${image})` : cleanTitle
}
export async function getMalojaScrobble(malojaUrl) {
const res = await fetch(`${malojaUrl}/apis/mlj_1/scrobbles?perpage=1`)
const data = await res.json()
const scrobble = data.list[0]
const {
title,
album: { artists },
} = scrobble.track
const cleanTitle = markdownCharEscape(title)
const cleanArtists = markdownCharEscape(artists.join(', '))
return markdownCharEscape(`${cleanTitle}<br />by ${cleanArtists}`)
}
export async function getLetterboxdActivity(username, showImage = true) {
const res = await fetch(`https://letterboxd.com/${username}/rss/`)
const data = await res.text()
const dom = new JSDOM(data, { contentType: 'text/xml' })
const item = dom.window.document.querySelector('item')
const title = item.querySelector('title').textContent
const link = item.querySelector('link').textContent.trim()
const cleanTitle = markdownCharEscape(title)
const image = item.querySelector('description > img').src
const text = !showImage
? cleanTitle
: `${cleanTitle} ![${cleanTitle}](${image})`
return { text, url: link }
}
export async function getTraktEpisode(username, id, showImage = true) {
const res = await fetch(
`https://trakt.tv/users/${username}/history/episodes/added/asc.atom?slurm=${process.env.TRAKT_SLURM}`,
)
const data = await res.text()
const dom = new JSDOM(data)
const entry = dom.window.document.querySelector('entry')
const title = entry.querySelector('title').textContent
const link = entry.querySelector('link').getAttribute('href')
const cleanTitle = markdownCharEscape(title)
const text = !showImage
? cleanTitle
: `${cleanTitle} ![${cleanTitle}](https://widgets.trakt.tv/users/${id}/watched/thumb@2x.jpg?type=episode&image_only=1)`
return { text, url: link }
}
export async function getTraktMovie(username, showImage = true) {
const res = await fetch(
`https://trakt.tv/users/${username}/history/movies/added/asc.atom?slurm=${process.env.TRAKT_SLURM}`,
)
const data = await res.text()
const dom = new JSDOM(data)
const entry = dom.window.document.querySelector('entry')
const title = entry.querySelector('title').textContent
const link = entry.querySelector('link').getAttribute('href')
return { text: markdownCharEscape(title), url: link }
}
export async function getTraktEpisodeAndMovie(username, id, showImage = true) {
const episode = await getTraktEpisode(username, id, showImage)
const movie = await getTraktMovie(username, showImage)
return {
text: `${episode.text} <br>and<br> ${movie.text}`,
url: `https://trakt.tv/users/${username}`,
}
}
export async function getReadingBooklogr(booklogrUrl, booklogrUser) {
const res = await fetch(`${booklogrUrl}/v1/profiles/${booklogrUser}`)
const data = await res.json()
const books = data.books.filter(
({ reading_status }) => reading_status === 'Currently reading',
)
return books.map(({ title }) => title).join(',<br />')
}