From 911d851fb1f8316195a7104bb62d493e87150a71 Mon Sep 17 00:00:00 2001
From: Melanie Kat <318003+ZicklePop@users.noreply.github.com>
Date: Wed, 17 Dec 2025 21:53:32 -0800
Subject: [PATCH] trakt support
---
.env.example | 1 +
.forgejo/workflows/update.yml | 1 +
biome.json | 3 +-
config.js | 41 ++++++++++++---------
utils.js | 69 ++++++++++++++++++++---------------
5 files changed, 68 insertions(+), 47 deletions(-)
diff --git a/.env.example b/.env.example
index e52e942..622360c 100644
--- a/.env.example
+++ b/.env.example
@@ -1,2 +1,3 @@
OMGLOL_KEY=
OMGLOL_USERNAME=melanie
+TRAKT_SLURM=
diff --git a/.forgejo/workflows/update.yml b/.forgejo/workflows/update.yml
index 71bc65e..55be46b 100644
--- a/.forgejo/workflows/update.yml
+++ b/.forgejo/workflows/update.yml
@@ -23,3 +23,4 @@ jobs:
env:
OMGLOL_KEY: ${{ secrets.OMGLOL_KEY }}
OMGLOL_USERNAME: ${{ vars.OMGLOL_USERNAME }}
+ TRAKT_SLURM: ${{ secrets.TRAKT_SLURM }}
diff --git a/biome.json b/biome.json
index 8ffc35c..720c7db 100644
--- a/biome.json
+++ b/biome.json
@@ -21,7 +21,8 @@
},
"javascript": {
"formatter": {
- "quoteStyle": "double"
+ "quoteStyle": "single",
+ "semicolons": "asNeeded"
}
},
"assist": {
diff --git a/config.js b/config.js
index f79fcbf..4d2c653 100644
--- a/config.js
+++ b/config.js
@@ -3,36 +3,43 @@ import {
getJsonFeedItemTitle,
getLetterboxdActivity,
getMalojaScrobble,
+ getTraktEpisode,
markdownLinkRegex,
-} from "./utils.js";
+} from './utils.js'
export const items = [
{
- id: "blog",
- regex: markdownLinkRegex("melkat.blog"),
+ id: 'blog',
+ regex: markdownLinkRegex('melkat.blog'),
getLatest: async () =>
- getJsonFeedItemTitle("https://melkat.blog/feed.json"),
+ getJsonFeedItemTitle('https://melkat.blog/feed.json'),
},
{
- id: "pics",
- regex: markdownLinkRegex("melkat.pics"),
+ id: 'pics',
+ regex: markdownLinkRegex('melkat.pics'),
getLatest: async () =>
- getJsonFeedItemTitle("https://melkat.pics/feed.json"),
+ getJsonFeedItemTitle('https://melkat.pics/feed.json'),
},
{
- id: "lol",
- regex: markdownLinkRegex("melkat.lol"),
+ id: 'lol',
+ regex: markdownLinkRegex('melkat.lol'),
getLatest: async () =>
- getJsonFeedItemContent("https://melkat.lol/feed.json"),
+ getJsonFeedItemContent('https://melkat.lol/feed.json'),
},
{
- id: "maloja",
- regex: markdownLinkRegex("scrobbles.melkat.dev"),
- getLatest: async () => getMalojaScrobble("https://scrobbles.melkat.dev"),
+ id: 'maloja',
+ regex: markdownLinkRegex('scrobbles.melkat.dev'),
+ getLatest: async () => getMalojaScrobble('https://scrobbles.melkat.dev'),
},
{
- id: "letterboxd",
- regex: markdownLinkRegex("letterboxd.com/zicklepop"),
- getLatest: async () => getLetterboxdActivity("zicklepop"),
+ id: 'letterboxd',
+ regex: markdownLinkRegex('letterboxd.com/zicklepop'),
+ getLatest: async () => getLetterboxdActivity('zicklepop'),
},
-];
+ {
+ id: 'trakt',
+ regex: markdownLinkRegex('trakt.tv/users/zicklepop'),
+ getLatest: async () =>
+ getTraktEpisode('zicklepop', 'd0a982626d7793b5cf1857a2128277cc'),
+ },
+]
diff --git a/utils.js b/utils.js
index 0d2e92e..c6b314a 100644
--- a/utils.js
+++ b/utils.js
@@ -1,51 +1,62 @@
-import { JSDOM } from "jsdom";
-import sanitizeHtml from "sanitize-html";
+import 'dotenv/config'
+import { JSDOM } from 'jsdom'
+import sanitizeHtml from 'sanitize-html'
export function markdownLinkRegex(url) {
return new RegExp(
- `(\\[).*?(\\]\\(https:\\/\\/${url.replaceAll(".", "\\.")}\\))`,
- "i",
- );
+ `(\\[).*?(\\]\\(https:\\/\\/${url.replaceAll('.', '\\.')}\\))`,
+ 'i',
+ )
}
export async function getJsonFeedItemTitle(feedUrl) {
- const res = await fetch(feedUrl);
- const data = await res.json();
- const post = data.items[0];
- const { title, image } = post;
- return image ? `${title} ` : title;
+ const res = await fetch(feedUrl)
+ const data = await res.json()
+ const post = data.items[0]
+ const { title, image } = post
+ return image ? `${title} ` : title
}
export async function getJsonFeedItemContent(feedUrl) {
- const res = await fetch(feedUrl);
- const data = await res.json();
- const post = data.items[0];
- const { content_html, image } = post;
+ 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();
- return image ? `${title} ` : title;
+ })?.trim()
+ return image ? `${title} ` : title
}
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 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;
- return `${title}
by ${artists.join(", ")}`;
+ } = scrobble.track
+ return `${title}
by ${artists.join(', ')}`
}
export async function getLetterboxdActivity(username) {
- const res = await fetch(`https://letterboxd.com/${username}/rss/`);
- const data = await res.text();
- const dom = new JSDOM(data);
-
- const item = dom.window.document.querySelector("item");
- const title = item.querySelector("title").textContent;
- const image = item.querySelector("description > img").src;
- return `${title} `;
+ const res = await fetch(`https://letterboxd.com/${username}/rss/`)
+ const data = await res.text()
+ const dom = new JSDOM(data)
+ const item = dom.window.document.querySelector('item')
+ const title = item.querySelector('title').textContent
+ const image = item.querySelector('description > img').src
+ return `${title} `
+}
+
+export async function getTraktEpisode(username, id) {
+ 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
+ return `${title} `
}