rss-feed

Guide for Updating Novel/Translator Mappings and Host Utilities

This guide explains which elements need to be updated whenever a new novel, translator, or hosting site is added. Please update the following files accordingly.


1. novel_mappings.py

This file contains mapping data for each hosting site. When adding a new novel or new hosting site, you will update:

๐Ÿ“ฆ pyproject.toml lets other projects (like the Discord webhook script) install this repo as a package using pip. It tells Python where to find novel_mappings.py so the webhook scripts can always pull the latest novel data straight from here ๐Ÿ”„โœจ.

Example

HOSTING_SITE_DATA = {
    "Dragonholic": {
        "feed_url": "https://dragonholic.com/feed/manga-chapters/",
        "comments_feed_url": "https://dragonholic.com/comments/feed/",
        "translator": "Cannibal Turtle",
        "host_logo": "https://dragonholic.com/wp-content/uploads/2025/01/Web-Logo-White.png",
        "coin_emoji": "๐Ÿ”ฅ",
        "novels": {
            "Quick Transmigration: The Villain Is Too Pampered and Alluring": {
                "discord_role_id": "<@&1329391480435114005>",
                "novel_url": "https://dragonholic.com/novel/quick-transmigration-the-villain-is-too-pampered-and-alluring/",
                "featured_image": "https://dragonholic.com/wp-content/uploads/2024/08/177838.jpg",
                "pub_date_override": {"hour": 12, "minute": 0, "second": 0}
                # โ”€โ”€โ”€ webhook-only fields โ”€โ”€โ”€
                "chapter_count": "1184 chapters + 8 extras",
                "last_chapter": "Extra 8",
                "start_date": "31/8/2024",
                "free_feed": "https://cannibal-turtle.github.io/rss-feed/free_chapters_feed.xml",
                "paid_feed": "https://cannibal-turtle.github.io/rss-feed/paid_chapters_feed.xml",
                "custom_emoji":   ":man_supervillain:",
                "discord_role_url":"https://discord.com/channels/1329384099609051136/1329419555600203776/1330466188349800458",
                "history_file":   "tvitpa_history.json"

            },
            # Second novel here
            },
            # Add more novels as needed.
        }
    },
    # Add additional hosting sites here.
}
def get_nsfw_novels():
    return [
        # List NSFW novel titles here, e.g.:
        "Some NSFW Novel Title"
    ]

2. host_utils.py

Dragonholic Functions

Host Utility Dispatcher

To get the appropriate utility functions for a specific host, use:

get_host_utils("Dragonholic")

---

Summary Checklist

  1. Add a New Novel on an Existing Host:
    • In novel_mappings.py, add or update the novels dictionary under the appropriate host in HOSTING_SITE_DATA.
    • If the novel is NSFW, also add it to get_nsfw_novels().
  2. Add a New Hosting Site:
    • In novel_mappings.py, create a new entry in HOSTING_SITE_DATA with:
      • feed_url, translator, host_logo, and a novels dictionary.
    • In host_utils.py, create new siteโ€‘specific functions and group them in a new dictionary. Update get_host_utils(host) to return that dictionary.

Following these steps keeps your feed generator modular and easy to update.

๐Ÿ“„ Sample Output (What the Final RSS Feed Looks Like)

Each generated .xml feed (free or paid) will contain structured entries enriched with metadata like volume, chapter name, link, description, translator, Discord role, hosting site, and more.

<item>
  <title>Quick Transmigration: The Villain Is Too Pampered and Alluring</title>
  <volume>ใ€Arc 5ใ€‘The Fake Daughter Will Not Be a Cannon Fodder</volume>
  <chaptername>Chapter 250</chaptername>
  <nameextend>***Uglier Than a Monkey***</nameextend>
  <link>https://dragonholic.com/novel/.../chapter-250/</link>
  <description><![CDATA[A deadly twist awaits in the mirror world...]]></description>
  <category>SFW</category>
  <translator>Cannibal Turtle</translator>
  <discord_role_id><![CDATA[<@&1329XXXXXX>]]></discord_role_id>
  <featuredImage url="https://dragonholic.com/.../cover.jpg"/>
  <coin>๐Ÿ”ฅย 10</coin>
  <pubDate>Fri, 18 Apr 2025 12:00:00 +0000</pubDate>
  <host>Dragonholic</host>
  <hostLogo url="https://dragonholic.com/.../logo.png"/>
  <guid isPermaLink="false">chapter-250-guid</guid>
</item>

๐Ÿ†• Mistmint Haven (Quick Setup) [UPDATE 4.0]

Modes

Mapping (novel_mappings.py)

Add:

HOSTING_SITE_DATA["Mistmint Haven"] = {
  "token_secret": "MISTMINT_COOKIE",   # name of the repo secret to read at runtime
}

Required repo secrets


Token-Expiry Alerts

  1. Hourly job runs comments.py โ†’ calls maybe_dispatch_token_alerts if token is expiring โ†’ send_token_alert.yml โ†’ send_token_alert.py.
  2. For each host with token_secret, it reads that env var, decodes JWT exp, and if โ‰ค 1 day, fires: repository_dispatch โ†’ event_type: token-expiring.
  3. .token_alert_state.json stores the last exp per (host, token_secret) so you arenโ€™t spammed hourly.

NSFW Catch Update

Now also updates <category> if <chaptername> and <nameextend> has these keywords:

Will match (โœ…) - Not case sensitive


๐Ÿ†• Automatic Novel Status Updater (Cross-Bot Integration)

This system keeps existing Discord novel cards up-to-date whenever new free chapters are announced, without reposting or changing formatting.

It is designed to work across repositories and servers.


๐Ÿ” Overview: How Status Auto-Updates Work

When a new free chapter is detected and posted:

  1. Free Chapters Bot (discord-webhook repo)
    • Posts the chapter announcement to Discord
    • Collects:
      • Novel title
      • Host (e.g. Mistmint Haven, Dragonholic)
    • Fires a repository_dispatch event to the rss-feed repo
  2. rss-feed Repo
    • Receives the dispatch
    • Runs the status updater script
    • Resolves:
      title + host โ†’ short_code (via HOSTING_SITE_DATA)
      
    • Updates only the Status field of existing embeds
  3. Target Discord Messages
    • Are edited in-place
    • Formatting, emojis, and layout are preserved
    • No reposts, no duplication

๐Ÿ“ Where the Mapping Happens (Important)

๐Ÿ”‘ Short codes are NOT passed between repos

Resolution happens only inside the updater Python script, using mappings.

Title + Host
   โ†“
HOSTING_SITE_DATA
   โ†“
short_code

๐Ÿ“„ Status Target Mapping

The updater uses a static map of existing Discord messages that should be updated.

Example (novel_status_targets.json):

{
  "TVITPA": [
    {
      "channel_id": "123456789",
      "message_id": "123456789"
    }
  ],
  "TDLBKGC": [
    {
      "channel_id": "123456789",
      "message_id": "123456789"
    }
  ],
  "ATVHE": [
    {
      "channel_id": "123456789",
      "message_id": "123456789"
    }
  ]
}

Notes


โœ๏ธ What the Updater Changes (and What It Doesnโ€™t)

โœ… Updated

โŒ Not touched

If a serverโ€™s embed does not have a Role field, the updater skips it safely.


๐Ÿง  How Status Is Calculated

The updater:

  1. Fetches the paid/free chapter API
  2. Determines:
    • Whether all paid chapters are released
    • Whether future free chapters exist
  3. Produces one of:
    • *Completed*
    • *Ongoing*
    • Next free chapter live <t:โ€ฆ:R>
    • All chapters are now free
    • _Free release schedule not available_

๐Ÿ” Required Secrets (Cross-Repo)

Because this system triggers across repositories, a PAT is required.

Required Secrets

| Secret | Repo | Purpose | |โ€”|โ€”|โ€”| | PAT_GITHUB | Source repo (in this case discord-webhook) | Dispatch events to rss-feed | | DISCORD_BOT_TOKEN | rss-feed | Edit existing Discord messages | | MISTMINT_COOKIE | rss-feed | Paid/free API access (if applicable) |

โš ๏ธ GITHUB_TOKEN is not sufficient for cross-repo dispatch.


๐Ÿงฉ Adding a New Novel (With Auto-Updates)

To enable automatic status updates for a new novel:

  1. Add the novel to HOSTING_SITE_DATA
  2. Assign it a unique short_code
  3. Add its Discord message(s) to novel_status_targets.json

โœ… Design Guarantees

Discord free chapter announcement
   โ†“
Trigger GitHub event
   โ†“
Recompute novel status
   โ†“
Edit existing embeds

Result:

image