Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions plugins/english/novelfire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { storage } from '@libs/storage';
class NovelFire implements Plugin.PluginBase {
id = 'novelfire';
name = 'Novel Fire';
version = '1.1.8';
version = '1.1.9';
icon = 'src/en/novelfire/icon.png';
site = 'https://novelfire.net/';

Expand Down Expand Up @@ -111,11 +111,41 @@ class NovelFire implements Plugin.PluginBase {
async getAllChapters(
novelPath: string,
post_id: string,
totalChapters: string,
): Promise<Plugin.ChapterItem[]> {
const allChapters: Plugin.ChapterItem[] = [];

const url = `${this.site}listChapterDataAjax?post_id=${post_id}`;
const result = await fetchApi(url);
const url = `${this.site}ajax/listChapterDataAjax`;
const params = new URLSearchParams({
draw: '1',
'columns[0][data]': 'n_sort',
'columns[0][name]': 'cmm_posts_detail.n_sort',
'columns[0][searchable]': 'true',
'columns[0][orderable]': 'true',
'columns[0][search][value]': '',
'columns[0][search][regex]': 'false',

'columns[1][data]': 'bookmark_created_at',
'columns[1][name]': 'bookmark_chapters.created_at',
'columns[1][searchable]': 'false',
'columns[1][orderable]': 'true',
'columns[1][search][value]': '',
'columns[1][search][regex]': 'false',

'order[0][column]': '0',
'order[0][dir]': 'asc',
'order[0][name]': 'cmm_posts_detail.n_sort',

start: '0',
length: totalChapters,
'search[value]': '',
'search[regex]': 'false',
post_id: post_id,
only_bookmark: 'false',
_: Date.now().toString(),
});

const result = await fetchApi(`${url}?${params.toString()}`);
const body = await result.text();

if (body.includes('You are being rate limited')) {
Expand Down Expand Up @@ -219,8 +249,6 @@ class NovelFire implements Plugin.PluginBase {
const $ = await this.getCheerio(this.site + novelPath, false);
const baseUrl = this.site;

let post_id = '0';

const novel: Partial<Plugin.SourceNovel & { totalPages: number }> = {
path: novelPath,
totalPages: 1,
Expand Down Expand Up @@ -276,16 +304,24 @@ class NovelFire implements Plugin.PluginBase {

novel.rating = parseFloat($('.nub').text().trim());

post_id = $('#novel-report').attr('report-post_id') || '0';
const post_id = $('#novel-report').attr('report-post_id') || '0';
const totalChapters = $('.header-stats i.icon-book-open')
.parent()
.text()
.trim();

try {
novel.chapters = await this.getAllChapters(novelPath, post_id);
novel.chapters = await this.getAllChapters(
novelPath,
post_id,
totalChapters,
);
} catch (error) {
const totalChapters = $('.header-stats .icon-book-open')
.parent()
.text()
.trim();
novel.totalPages = Math.ceil(parseInt(totalChapters) / 100);
novel.totalPages = Math.ceil(parseInt(totalChapters) / 50);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anyway to dynamically get this number of chapters per page instead of hard coding?

In case NovelFire changes it again in future, it would need a plugin update.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const firstPage = await this.parsePage(novelPath, '1');
const chaptersPerPage = firstPage.chapters.length;
novel.totalPages = chaptersPerPage > 0
  ? Math.ceil(parseInt(totalChapters) / chaptersPerPage)
  : 1;

This is what I've got after a bit of looking around. But this requires an extra API call, so not sure if there are better solutions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if we want to have a fallback -

let chaptersPerPage = 50; // fallback
try {
  const firstPage = await this.parsePage(novelPath, '1');
  const count = firstPage.chapters.length;
  if (count > 0) chaptersPerPage = count;
} catch (e) {
  console.warn('[NovelFire] Failed to get chaptersPerPage, falling back to 50:', e);
}
novel.totalPages = Math.ceil(parseInt(totalChapters) / chaptersPerPage);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a bad idea to make the extra request first to get the correct number of pages. The getAllChaptersForce already makes a separate request for each page. The only other solution I have in mind would be to fetch the total amount of chapters from the main novel page and then keep iterating through pages until all the chapters are fetched. Either way is one more request. I'm not great at Javascript, so not sure what the exact implementation would look like, I just wanted to at least get the plugin into a working state.

Looking a little bit further in though, it looks like the page that the parsePage function fetches has the latest chapter number under the CSS selector: "header.container > p:nth-child(5) > a:nth-child(1)". I think it would be possible to just make the fetchPage function additionally return that value on top of what it returns already so we can have the total amount of chapters without making an extra request since we would always be grabbing the first page no matter what. Once we have that getAllChaptersForce would just have to be modified so it keeps fetching the next page until allChapters.length() is equal to the most recent chapter.

@vnkavali vnkavali Apr 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we have that getAllChaptersForce would just have to be modified so it keeps fetching the next page until allChapters.length() is equal to the most recent chapter.

This might involve more changes than expected, as the API seems to be designed to do things in paralel based on the total number of pages passed along.

I am in favour of getting the fix in firstly to resolve the issue.

@Seuhen Seuhen Apr 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this might fix it for now but it should have a dynamic fix that contends to future updates and changes to the site. All in all, I am in favor of pushing this fix for now. It's feasible and will get the job done.

Also, I am a newbie at this kind of thing and would like your help in fixing it for myself temporarily because don't know when the issue will get fixed officially.

Thanks and good work, mate!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this PR mostly as a hotfix to get things working again, I agree that it needs a minor revamp to prevent this issue in the future.

Also, I am a newbie at this kind of thing and would like your help in fixing it for myself temporarily because don't know when the issue will get fixed officially.

You should be able to fork the repo, make the one line change to the file, and then run "npm run publish:plugins -- --all-branches" on your local copy of the repo. I couldn't get the GitHub action working on my fork, but manually running the command worked. You can then add your repo as a plugin repo in the app.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thank you!

if (this.singlePage) {
novel.chapters = await this.getAllChaptersForce(
novelPath,
Expand Down