Update your Now page, automatically https://dylan.omg.lol/now
Find a file
dylan bc18d5beca
All checks were successful
update now / build (push) Successful in 15s
Merge pull request 'Fix regex, again!' (#5) from fix/image-updates into main
Reviewed-on: #5
2025-12-31 09:30:12 +00:00
.forgejo/workflows added HARDCOVER_API_KEY to environment variables in update.yml 2025-12-28 18:14:05 +00:00
.env.example added HARDCOVER_API_KEY to .env.example for hardcover service 2025-12-28 18:13:32 +00:00
.gitignore removed local development files from .gitignore 2025-12-28 16:57:45 +00:00
config.js moved services from config.js into their own services.js 2025-12-28 16:52:26 +00:00
index.js updated regex replacement to include old text in debug logging 2025-12-31 00:19:26 +00:00
now-page-template.md updated now-page-template with new image handling and layout adjustments 2025-12-31 00:19:37 +00:00
package-lock.json letterboxd support 2025-12-17 21:35:31 -08:00
package.json added local development files to .gitignore and updated package.json to include preview script 2025-12-28 13:32:09 +00:00
profile-page-template.md added profile and now page templates with updated content and links 2025-12-25 18:27:26 +00:00
README.md updated README to include details on new image handling 2025-12-29 19:30:19 +00:00
services.js updated some.pics integration 2025-12-28 20:51:19 +00:00
utils.js updated regex to match service by data-service attribute in html anchor tags 2025-12-31 00:19:02 +00:00

now-updater

Automatically updates your omg.lol Now page with your latest activity.

Fork of melanie/now-updater with added support for HTML links, images/videos, Steam, Hardcover, some.pics, and simplified service configuration.

Demo: dylan.omg.lol/now

How It Works

Fetches content from RSS feeds, JSON feeds, and different services (Letterboxd, Trakt, Last.fm, Steam, Hardcover, etc.) and updates HTML or markdown links on your Now page. Supports optional images and videos for services that provide them (These are... iffy so if something breaks it's probably this). Runs every 3 hours via Forgejo Actions, only updating your page when changes are detected.

Images are matched using a data-service attribute on the img tag, which allows them to be updated repeatedly even after the initial replacement.

Example

Your Now page links will be automatically updated from this:

HTML links (before):

<a href="service-link">blog</a>
<a href="service-link">gitlab</a>

Markdown links (before):

[blog](service-link)
[gitlab](service-link)

to this:

HTML links (after):

<a href="https://your-blog.com/2025/12/my-latest-post">My Latest Post</a>
<a href="https://gitlab.com/username/project">Pushed to repository</a>

Markdown links (after):

[My Latest Post](https://your-blog.com/2025/12/my-latest-post)
[Pushed to repository](https://gitlab.com/username/project)

Setup

  1. Fork this repo
  2. Enable Actions in repo settings
  3. Add Actions variables: OMGLOL_USERNAME (your omg.lol username)
  4. Add Actions secrets: OMGLOL_KEY (your API key)
  5. Add optional secrets for services you want to use: TRAKT_SLURM, STEAM_WEBAPI_KEY, HARDCOVER_API_KEY
  6. Activate your services in services.js by setting isActive: true

For local development, copy .env.example to .env with your credentials.

Basic Example

Now page template:

I wrote this: <a href="https://your-blog.com">blog</a>
I watched this: <a href="https://letterboxd.com/username">letterboxd</a>
<img data-service="letterboxd" src="letterboxd-image" style="max-width: 120px;">
I listened to: <a href="https://www.last.fm/user/username">lastfm</a>

services.js:

export const services = [
  {
    id: 'blog',
    isActive: true,
    feedUrl: 'https://your-blog.com/feed.json',
    feedType: 'json',
  },
  {
    id: 'letterboxd',
    isActive: true,
    userId: 'your-username',
    feedUrlTemplate: 'https://letterboxd.com/{userId}/rss/',
    feedType: 'letterboxd',
    showImage: true, // optional: include movie posters
  },
  {
    id: 'lastfm',
    isActive: true,
    userId: 'your-username',
    feedUrlTemplate: 'https://lfm.xiffy.nl/{userId}',
    feedType: 'rss',
  },
]

Configuration

Quick Start

  1. In your Now page, use service names as link text:
<a href="service-link">blog</a>
<a href="service-link">gitlab</a>
  1. In services.js, find the service and flip isActive to true:
{
  id: 'gitlab',
  isActive: true,  // just change this!
  userId: 'your-username',
  feedUrlTemplate: 'https://gitlab.com/users/{userId}/activity.atom',
  feedType: 'atom',
}

The service id is used to match the link text in your Now page (e.g., <a href="...">blog</a> matches id: 'blog'). If you need multiple instances of the same service just create separate entries in services.js with unique ids and matching link texts. Like so:

	{
		id: 'mastodon-personal',
		isActive: false,
		userId: 'dylan',
		instance: 'social.lol', // your mastodon instance
		feedUrlTemplate: 'https://{instance}/@{userId}.rss',
		feedType: 'mastodon',
		showImage: true,
	},
  {
    id: 'mastodon-work',
    isActive: false,
    userId: 'mrdylan',
    instance: 'mastodon.instance', // your mastodon instance
    feedUrlTemplate: 'https://{instance}/@{userId}.rss',
    feedType: 'mastodon',
    showImage: true,
  },

Then you can have multiple Mastodon accounts on your Now page with different link texts: [mastodon-personal](service-link) and [mastodon-work](service-link).

Files

  • config.js - Link format setting (html or markdown) and filter logic
  • services.js - All available services with isActive flags (edit this to enable/disable services)
  • utils.js - Generic feed handlers and service-specific logic

Service Structure

Each service has:

  • id: Identifier that matches the link text in your Now page (e.g., id: 'blog-1' matches <a>blog-1</a>)
  • isActive: true to enable, false to disable
  • feedType: Handler to use (rss, atom, json, or special handler name like letterboxd, steam, hardcover)
  • feedUrl: Direct feed URL (use this for custom feeds without usernames)
  • feedUrlTemplate: URL template with {userId} or {instance} placeholders
  • userId: Your username/ID (only needed with feedUrlTemplate)
  • showImage: Optional. Controls whether image/videos are included (defaults based on service)
  • Extra params as needed (e.g., instance for federated services, traktId for Trakt widgets)

Set linkFormat in config.js to 'html' or 'markdown' depending on your Now page format.

Image and Video Support

Many services support optional images and videos:

  • Letterboxd: Movie posters from CDATA descriptions
  • Trakt: Episode/movie poster widgets (portrait orientation, change the URL from poster to thumb for landscape)
  • Hardcover: Book cover images
  • Steam: Game library posters
  • Mastodon: Attached images and videos from media:content tags (iffy, may not always work)
  • some.pics: Photo images from RSS CDATA

Control image inclusion with the showImage flag in your service config. Images are returned separately from text so you can control placement on your Now page.

To use images, your img tags must include a data-service attribute matching the service id from services.js. For example:

<img data-service="letterboxd" src="letterboxd-image" style="max-width: 120px;">
<img data-service="steam" src="steam-image" style="max-width: 120px;">

The src attribute can start with a placeholder (like letterboxd-image) or an existing URL - the updater will replace it either way as long as the data-service attribute is present.

Available Services

All handlers now use a config object with consistent parameters. The feedType in services.js maps to these handlers.

Generic Feed Handlers

  • getRSSItemTitle(feedUrl) - Standard RSS feeds
  • getAtomFeed(url) - Standard Atom feeds
  • getJsonFeedItemTitle(feedUrl, showImage) - JSON feeds with optional images

omg.lol Services

  • getSomePicsPost(feedUrl) - some.pics photo posts with images extracted from CDATA

Music

  • getListenBrainzScrobble(config) - ListenBrainz scrobbles (not tested, let me know!)
    • Config: { feedUrl, userId }
  • For Last.fm, use generic RSS handler with https://lfm.xiffy.nl/{userId}

Social Media

  • getMastodonPost(config) - Latest non-reply Mastodon post with optional images/videos
    • Config: { feedUrl, showImage }
    • Extracts media from media:content tags and filters out replies

Movies & TV

  • getLetterboxdActivity(config) - Letterboxd activity with optional poster images
    • Config: { feedUrl, showImage }
    • Extracts images from CDATA descriptions
  • getTraktEpisode(config) - Latest TV episode with optional poster
    • Config: { userId, traktId, showImage }
    • Requires TRAKT_SLURM environment variable
    • Uses portrait poster widgets
  • getTraktMovie(config) - Latest movie with optional poster
    • Config: { userId, traktId, showImage }
    • Requires TRAKT_SLURM environment variable
    • Uses portrait poster widgets

Books

  • getHardcoverActivity(config) - Currently reading books with cover images
    • Config: { userId, feedUrl }
    • Uses GraphQL API, requires HARDCOVER_API_KEY
    • userId must be numeric user ID (not username)

Gaming

  • getSteamRecentlyPlayed(config) - Recently played Steam game with library poster
    • Config: { userId }
    • Requires STEAM_WEBAPI_KEY environment variable
    • userId must be Steam ID 64 (convert at https://steamid.io/)

Code & Development

  • getSourceTubeActivity(config) - Forgejo activity on source.tube
    • Config: { feedUrl, userId }
    • Strips username prefix from activity descriptions (e.g., "dylan pushed to repository" becomes "pushed to repository")

Important Notes:

  • showImage controls whether images/videos are included in the response
  • Images and videos are returned separately from text (as { text, url, image, video })
  • Generic RSS/Atom/JSON handlers work with most standard feeds

API Keys Setup

Trakt

To get your Trakt slurm key, follow these steps:

  1. Go to your History page on Trakt: https://trakt.tv/users/your-username/history
  2. There should be an RSS feed icon on the top right of the page. Click it.
  3. The URL it shows will look something like this: https://trakt.tv/users/username/history.atom?slurm=your-slurm-key
  4. Copy the slurm value from the URL and add it as a secret in your Actions settings named TRAKT_SLURM.
  5. Add it to your .env file for local testing.

Steam

To get your Steam Web API key:

  1. Visit https://steamcommunity.com/dev/apikey
  2. Enter a domain name (I used omg.lol, I don't know if that will cause me issues later)
  3. Agree to the terms and get your API key
  4. Add it to your .env as STEAM_WEBAPI_KEY and to Actions secrets
  5. Find your Steam ID 64 at https://steamid.io/ (enter your profile URL)

Note: The Steam handler uses the GetOwnedGames API endpoint sorted by rtime_last_played, which has no time limit. GetRecentlyPlayedGames can be used too, but it only shows anything played in the last 14 days which may be limiting.

Hardcover

To get your Hardcover API key:

  1. Visit https://hardcover.app/account/api (Make sure you're logged in)
  2. Find the authorisation header token section
  3. Important: The token shown will include "Bearer " at the beginning - do not include this prefix when adding it (Note the space after "Bearer", that needs to be removed too)
  4. Add the token to your .env file as HARDCOVER_API_KEY and to Actions secrets

Credits

Original project by melanie kat. Without her work, this fork would not exist.

Thank you also to xiffy for the Last.fm scrobble fetching service this uses.

Support

Did you find this useful like I did? Melanie asks that you donate to Trans Lifeline or The Trevor Project if you can. I will also add Belong To to that list.