From d1744a96d33655f17c7f80e5535017a97839c42a Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 04:33:35 -0300 Subject: [PATCH 01/14] feat(Novel Mania): Update and add setting up for v2 --- websites/N/Novel Mania/{ => v1}/metadata.json | 0 websites/N/Novel Mania/{ => v1}/presence.ts | 0 websites/N/Novel Mania/v2/metadata.json | 60 +++++ websites/N/Novel Mania/v2/novelmania.json | 54 +++++ websites/N/Novel Mania/v2/presence.ts | 222 ++++++++++++++++++ 5 files changed, 336 insertions(+) rename websites/N/Novel Mania/{ => v1}/metadata.json (100%) rename websites/N/Novel Mania/{ => v1}/presence.ts (100%) create mode 100644 websites/N/Novel Mania/v2/metadata.json create mode 100644 websites/N/Novel Mania/v2/novelmania.json create mode 100644 websites/N/Novel Mania/v2/presence.ts diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/v1/metadata.json similarity index 100% rename from websites/N/Novel Mania/metadata.json rename to websites/N/Novel Mania/v1/metadata.json diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/v1/presence.ts similarity index 100% rename from websites/N/Novel Mania/presence.ts rename to websites/N/Novel Mania/v1/presence.ts diff --git a/websites/N/Novel Mania/v2/metadata.json b/websites/N/Novel Mania/v2/metadata.json new file mode 100644 index 000000000000..cd507f0f66b7 --- /dev/null +++ b/websites/N/Novel Mania/v2/metadata.json @@ -0,0 +1,60 @@ +{ + "apiVersion": 2, + "author": { + "name": "Shuichi", + "id": "179440483796385792" + }, + "service": "Novel Mania", + "altnames": [ + "NovelMania" + ], + "description": { + "en": "Read webnovels in Portuguese anywhere and anytime.", + "pt-br": "Leia webnovels em português a qualquer momento e a qualquer hora." + }, + "url": "novelmania.com.br", + "regExp": "^https?[:][/][/]([a-z0-9-]+[.])*novelmania[.]com[.]br[/]", + "version": "2.0.0", + "logo": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png", + "thumbnail": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/thumbnail.jpg", + "color": "#008cff", + "category": "other", + "tags": [ + "novel", + "lightnovel", + "light novel", + "webnovel", + "web novel", + "reader", + "scanlator", + "translation", + "book" + ], + "settings": [ + { + "id": "lang", + "multiLanguage": true + }, + { + "id": "hideInfo", + "title": "Privacy Mode", + "icon": "fas fa-compress-arrows-alt", + "value": false + }, + { + "id": "showButtons", + "title": "Show Buttons", + "icon": "fas fa-compress-arrows-alt", + "value": true, + "if": { + "showInfo": false + } + }, + { + "id": "showTimestamp", + "title": "Show Timestamp", + "icon": "fas fa-clock", + "value": true + } + ] +} \ No newline at end of file diff --git a/websites/N/Novel Mania/v2/novelmania.json b/websites/N/Novel Mania/v2/novelmania.json new file mode 100644 index 000000000000..a094bd0bab9c --- /dev/null +++ b/websites/N/Novel Mania/v2/novelmania.json @@ -0,0 +1,54 @@ +{ + "novelmania.volume": { + "description": "Text for when user's reading a novel with volumes.", + "message": "Volume" + }, + "novelmania.book": { + "description": "Text for when user's reading a novel with books.", + "message": "Book" + }, + "novelmania.viewingProfile": { + "description": "Text for when user's visualizing someone's profile.", + "message": "Viewing profile" + }, + "novelmania.lists": { + "description": "Text for when user's visualizing 'lists' page.", + "message": "listas" + }, + "novelmania.news": { + "description": "Text for when user's visualizing 'news' page.", + "message": "news" + }, + "novelmania.genre": { + "description": "Text for when user's browsing genres.", + "message": "genres" + }, + "novelmania.novel": { + "description": "Just a placeholder for a novel title. It doesn't matter what it is, it will be replaced by the actual title.", + "message": "novel" + }, + "novelmania.readNovelButton": { + "description": "", + "message": "Read this novel!" + }, + "novelmania.readChapterButton": { + "description": "Text from 'reading chapter button'. Call to read along!", + "message": "Read this chapter!" + }, + "novelmania.visitWebsiteButton": { + "description": "Text from 'visit website button'.", + "message": "Visit this website!" + }, + "novelmania.readListButton": { + "description": "Text from 'read this list button'.", + "message": "Read this list!" + }, + "novelmania.readNewsButton": { + "description": "Text from 'read this news button'.", + "message": "Read this news!" + }, + "novelmania.visitUserProfileButton": { + "description": "Text from 'spy on this user button'. Naughty, naughty...", + "message": "Spy on this user!" + } +} \ No newline at end of file diff --git a/websites/N/Novel Mania/v2/presence.ts b/websites/N/Novel Mania/v2/presence.ts new file mode 100644 index 000000000000..069fb51e17dd --- /dev/null +++ b/websites/N/Novel Mania/v2/presence.ts @@ -0,0 +1,222 @@ +import { ActivityType, Assets } from 'premid' + +const presence = new Presence({ + clientId: '738522217221980222', +}) +const browsingTimestamp = Math.floor(Date.now() / 1000) +enum ActivityAssets { + Logo = 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', +} +async function getStrings() { + return presence.getStrings({ + browse: 'general.browsing', + home: 'general.viewHome', + privacy: 'general.privacy', + reading: 'general.reading', + view: 'general.view', + volume: 'novelmania.volume', + profile: 'general.viewProfile', + lists: 'novelmania.lists', + news: 'novelmania.news', + genre: 'novelmania.genre', + novel: 'novelmania.novel', + readNovelButton: 'novelmania.readNovelButton', + readChapterButton: 'novelmania.readChapterButton', + visitWebsiteButton: 'novelmania.visitWebsiteButton', + readListButton: 'novelmania.readListButton', + readNewsButton: 'novelmania.readNewsButton', + visitUserProfileButton: 'novelmania.visitUserProfileButton', + }) +} +let oldUserLanguage: string | null = null +let strings: Awaited> + +presence.on('UpdateData', async () => { + strings = await getStrings() + + const [showButtons, showTime, hideInfo, userLanguage] = await Promise.all([ + presence.getSetting('showButtons') || true, + presence.getSetting('showTimestamp') || true, + presence.getSetting('hideInfo') || false, + presence.getSetting('lang').catch(() => 'pt') + ]); + + if (oldUserLanguage !== userLanguage) { + oldUserLanguage = userLanguage + strings = await getStrings() + } + + + const presenceData: PresenceData = { + largeImageKey: ActivityAssets.Logo, + startTimestamp: showTime ? browsingTimestamp : undefined, + type: ActivityType.Watching + + } + const { pathname, origin } = window.location + const cleanPath = pathname.replace(/\/$/, '') || '/' + const [part1, part2, part3, part4] = cleanPath.slice(1).split('/') // page, slug (if any), chapter (if any), volume/book (if any) + + const privacyCheck = (foo: any): string => { + return !hideInfo ? foo : strings.privacy + } + + const getPageTitle = (): string => document.querySelector('#main h1')?.textContent || strings.novel + let buttons: [ButtonData, ButtonData?] | undefined + + switch (part1) { + case '': + if (cleanPath === '/') { + presenceData.state = strings.home; + + buttons = [ + { + label: strings.visitWebsiteButton, + url: origin, + }, + ] + } + break + + case 'u': /* Seeing some user profile */ + if (part2) { + presenceData.details = `${strings.profile}` + presenceData.state = privacyCheck(getPageTitle()); + buttons = [ + { + label: strings.visitUserProfileButton, + url: origin + `/u/${part2}`, + }, + ] + } + break + + case 'novels': + if (!part2) { /* Searching some novel */ + presenceData.details = `${strings.browse}`; + presenceData.state = privacyCheck(getPageTitle()); + + const params = new URLSearchParams(window.location.search); + const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q'); + + if (searchTerm) { + presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}`; + } + + // Extrai nomes dos filtros - apenas se houver busca ou query params + if (searchTerm || window.location.search) { + const badges = document.querySelectorAll('span.inline-flex.rounded-full.border'); + if (badges.length > 0) { + const visibleFilters: string[] = []; + for (let i = 0; i < badges.length; i++) { + const text = badges[i]?.childNodes[0]?.textContent?.trim(); + if (text) visibleFilters.push(text); + } + if (visibleFilters.length) { + presenceData.state = privacyCheck(visibleFilters.join(', ')); + } + } + } + break + } + if (part3 === 'capitulos' && part4) { /* Reading some novel's chapter */ + const novelName = document.querySelector("#conteudo-principal > div > header > div > p")?.textContent || part2?.split('-').slice(0, 2).join(' ') || strings.novel; + const noveltype = document.querySelector("#conteudo-principal > div > main > div > div > header > p")?.textContent || part4?.split('-').slice(0, 2).join(' ') || strings.volume; + const currentChapTitle = document.querySelector("#reader-chapter-title")?.textContent || novelName; + + presenceData.details = `${strings.reading} ${privacyCheck(novelName)}`; + presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readNovelButton, + url: origin + `/novels/${part2}`, + }, + { + label: strings.readChapterButton, + url: origin + `/novels/${part2}/capitulos/${part4}`, + }, + ] + break + } + if (part2) { /* At some novel's page */ + const novelName = document.querySelector("#main > div > h1")?.textContent || strings.novel + presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}`; + + buttons = [ + { + label: strings.readNovelButton, + url: origin + `/novels/${part2}`, + }, + ] + } + break + + case 'listas': /* Searching some lists */ + if (!part2) { + presenceData.state = `${strings.browse} ${strings.lists}`; + presenceData.smallImageKey = Assets.Reading + break + } + + presenceData.details = `${strings.view} ${strings.lists}`; + presenceData.state = `${privacyCheck(getPageTitle())} - ${privacyCheck(document.querySelector("#main > div > div:nth-child(2) > a")?.textContent || strings.novel)}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readListButton, + url: origin + `/listas/${part2}`, + }, + ] + break + + case 'noticias': + if (!part2) { /* Searching some news */ + presenceData.details = `${strings.reading} ${strings.news}`; /* reading news list */ + presenceData.state = `${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + break + } + + presenceData.details = `${strings.reading} ${strings.news}`; /* reading a news */ + presenceData.state = `${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readNewsButton, + url: origin + `/noticias/${part2}`, + }, + ] + break + + case 'genero': /* Browsing some genres */ + if (part2) { + presenceData.details = `${strings.browse} ${strings.genre}`; + presenceData.state = privacyCheck(getPageTitle()); + presenceData.smallImageKey = Assets.Reading + } + break + + default: /* At any other page, it doesn't matter */ + presenceData.state = `${strings.view} ${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + break + } + + if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) + presenceData.buttons = buttons + + // Set the activity + if (presenceData.state) { + presence.setActivity(presenceData) + + if (!showTime) + delete presenceData.startTimestamp + + } else { + presence.clearActivity() + } +}) From 61b70b607c0abeafd43e70e23b360f3f2bf70e6b Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 04:42:04 -0300 Subject: [PATCH 02/14] fix(Novel Mania): Update everything website has changed --- websites/N/Novel Mania/v2/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/websites/N/Novel Mania/v2/metadata.json b/websites/N/Novel Mania/v2/metadata.json index cd507f0f66b7..3fba9a9aa0ad 100644 --- a/websites/N/Novel Mania/v2/metadata.json +++ b/websites/N/Novel Mania/v2/metadata.json @@ -1,5 +1,6 @@ { - "apiVersion": 2, + "$schema": "https://schemas.premid.app/metadata/1.17", + "apiVersion": 1, "author": { "name": "Shuichi", "id": "179440483796385792" From 1649427b44b18285859c5a4ca140a0aed886c48d Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:01:01 -0300 Subject: [PATCH 03/14] Remove folders as I dont know whta to do with then --- websites/N/Novel Mania/v1/metadata.json | 26 --- websites/N/Novel Mania/v1/presence.ts | 78 -------- websites/N/Novel Mania/v2/metadata.json | 61 ------ websites/N/Novel Mania/v2/novelmania.json | 54 ------ websites/N/Novel Mania/v2/presence.ts | 222 ---------------------- 5 files changed, 441 deletions(-) delete mode 100644 websites/N/Novel Mania/v1/metadata.json delete mode 100644 websites/N/Novel Mania/v1/presence.ts delete mode 100644 websites/N/Novel Mania/v2/metadata.json delete mode 100644 websites/N/Novel Mania/v2/novelmania.json delete mode 100644 websites/N/Novel Mania/v2/presence.ts diff --git a/websites/N/Novel Mania/v1/metadata.json b/websites/N/Novel Mania/v1/metadata.json deleted file mode 100644 index 7ad8f79cd1de..000000000000 --- a/websites/N/Novel Mania/v1/metadata.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://schemas.premid.app/metadata/1.16", - "apiVersion": 1, - "author": { - "name": "Shuichi", - "id": "179440483796385792" - }, - "service": "Novel Mania", - "description": { - "en": "Read webnovels in Portuguese anywhere and anytime.", - "nl": "Lees overal en altijd webnovels in het Portugees.", - "pt-br": "Leia webnovels em português a qualquer momento e a qualquer hora." - }, - "url": "novelmania.com.br", - "regExp": "^https?[:][/][/]([a-z0-9-]+[.])*novelmania[.]com[.]br[/]", - "version": "1.1.0", - "logo": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png", - "thumbnail": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/thumbnail.jpg", - "color": "#008cff", - "category": "other", - "tags": [ - "novel", - "mania", - "translator" - ] -} diff --git a/websites/N/Novel Mania/v1/presence.ts b/websites/N/Novel Mania/v1/presence.ts deleted file mode 100644 index f3b79755c8d9..000000000000 --- a/websites/N/Novel Mania/v1/presence.ts +++ /dev/null @@ -1,78 +0,0 @@ -const presence = new Presence({ - clientId: '738522217221980222', -}) -const browsingTimestamp = Math.floor(Date.now() / 1000) - -presence.on('UpdateData', async () => { - const presenceData: PresenceData = { - largeImageKey: 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', - startTimestamp: browsingTimestamp, - } - const path = document.location.pathname - const porcent = document.querySelector( - '#settings-section > div > ul > li:nth-child(1) > div > div', - ) - const currentChapTitle = document.querySelector( - 'body > div:nth-child(4) > main > section.landing.novel-single > div.novel-head.pt-3 > div > div > div:nth-child(1) > nav > ol > li.breadcrumb-item.active', - ) - const novelName = document.querySelector('h1') - const VolNumb = document.querySelector('#chapter-content > h3') - const NovelTitle = document.querySelector( - 'body > div:nth-child(4) > main > section.landing.novel-single > div.novel-head.pt-3 > div > div > div:nth-child(2) > div > h1 > a', - ) - const PagTitle = document.querySelector('h2') - if (path === '/' || !path) { - presenceData.details = 'Na página inicial' /* at home */ - presenceData.state = 'Só olhando... Que estranho!' /* Juist lookin, how strange! */ - } - else if (path.includes('/noticias/')) { - presenceData.details = 'Lendo Notícia:' /* reading a notice */ - presenceData.state = novelName?.textContent - } - else if (path.includes('/novels/')) { - if (document.body.contains(document.querySelector('#myTab'))) { - presenceData.details = 'No Indice da Novel:' /* At the novels's indice */ - presenceData.state = novelName?.textContent - } - else if (document.body.contains(VolNumb)) { - presenceData.details = `Lendo ${NovelTitle?.textContent} || ${VolNumb?.textContent}` /* reading volume */ - presenceData.state = `Em ${porcent?.textContent} do ${currentChapTitle?.textContent}` /* in X% of... novel chapter */ - } - else { - presenceData.details = `Lendo${NovelTitle?.textContent}` /* reading *novel**/ - presenceData.state = `Em ${porcent?.textContent}do${currentChapTitle?.textContent}` /* in X% of... novel chapter */ - } - } - else if (path.includes('/u/')) { - presenceData.details = 'Bisbilhotando:' /* Seeing the * user profile */ - presenceData.state = document.querySelector( - 'body > div > main > section.profile-top > div > div > div > div.col-sm-8.col-md-9.d-flex.align-items-center > div > ul > li.admin-name > h5', - )?.textContent - } - else if ( - path.includes('/editoria') - || path.includes('/salao-da-contribuicao') - || path.includes('/regras-setorias') - || path.includes('/politica-de-privacidade') - || path.includes('contato') - ) { - presenceData.details = 'Lendo Página: ' /* reading page */ - presenceData.state = PagTitle?.textContent - } - else if ( - path.includes('/genero/') - || path.includes('/chinesa') - || path.includes('/japonesa') - || path.includes('/coreana') - || path.includes('/brasileira') - || path.includes('/americana') - ) { - presenceData.details = 'Procurando:' /* searching for */ - presenceData.state = PagTitle?.textContent - } - else { - presenceData.details = 'Buscando...' /* searching... */ - presenceData.state = 'Algo Incrível' /* Something incredible */ - } - presence.setActivity(presenceData) -}) diff --git a/websites/N/Novel Mania/v2/metadata.json b/websites/N/Novel Mania/v2/metadata.json deleted file mode 100644 index 3fba9a9aa0ad..000000000000 --- a/websites/N/Novel Mania/v2/metadata.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "https://schemas.premid.app/metadata/1.17", - "apiVersion": 1, - "author": { - "name": "Shuichi", - "id": "179440483796385792" - }, - "service": "Novel Mania", - "altnames": [ - "NovelMania" - ], - "description": { - "en": "Read webnovels in Portuguese anywhere and anytime.", - "pt-br": "Leia webnovels em português a qualquer momento e a qualquer hora." - }, - "url": "novelmania.com.br", - "regExp": "^https?[:][/][/]([a-z0-9-]+[.])*novelmania[.]com[.]br[/]", - "version": "2.0.0", - "logo": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png", - "thumbnail": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/thumbnail.jpg", - "color": "#008cff", - "category": "other", - "tags": [ - "novel", - "lightnovel", - "light novel", - "webnovel", - "web novel", - "reader", - "scanlator", - "translation", - "book" - ], - "settings": [ - { - "id": "lang", - "multiLanguage": true - }, - { - "id": "hideInfo", - "title": "Privacy Mode", - "icon": "fas fa-compress-arrows-alt", - "value": false - }, - { - "id": "showButtons", - "title": "Show Buttons", - "icon": "fas fa-compress-arrows-alt", - "value": true, - "if": { - "showInfo": false - } - }, - { - "id": "showTimestamp", - "title": "Show Timestamp", - "icon": "fas fa-clock", - "value": true - } - ] -} \ No newline at end of file diff --git a/websites/N/Novel Mania/v2/novelmania.json b/websites/N/Novel Mania/v2/novelmania.json deleted file mode 100644 index a094bd0bab9c..000000000000 --- a/websites/N/Novel Mania/v2/novelmania.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "novelmania.volume": { - "description": "Text for when user's reading a novel with volumes.", - "message": "Volume" - }, - "novelmania.book": { - "description": "Text for when user's reading a novel with books.", - "message": "Book" - }, - "novelmania.viewingProfile": { - "description": "Text for when user's visualizing someone's profile.", - "message": "Viewing profile" - }, - "novelmania.lists": { - "description": "Text for when user's visualizing 'lists' page.", - "message": "listas" - }, - "novelmania.news": { - "description": "Text for when user's visualizing 'news' page.", - "message": "news" - }, - "novelmania.genre": { - "description": "Text for when user's browsing genres.", - "message": "genres" - }, - "novelmania.novel": { - "description": "Just a placeholder for a novel title. It doesn't matter what it is, it will be replaced by the actual title.", - "message": "novel" - }, - "novelmania.readNovelButton": { - "description": "", - "message": "Read this novel!" - }, - "novelmania.readChapterButton": { - "description": "Text from 'reading chapter button'. Call to read along!", - "message": "Read this chapter!" - }, - "novelmania.visitWebsiteButton": { - "description": "Text from 'visit website button'.", - "message": "Visit this website!" - }, - "novelmania.readListButton": { - "description": "Text from 'read this list button'.", - "message": "Read this list!" - }, - "novelmania.readNewsButton": { - "description": "Text from 'read this news button'.", - "message": "Read this news!" - }, - "novelmania.visitUserProfileButton": { - "description": "Text from 'spy on this user button'. Naughty, naughty...", - "message": "Spy on this user!" - } -} \ No newline at end of file diff --git a/websites/N/Novel Mania/v2/presence.ts b/websites/N/Novel Mania/v2/presence.ts deleted file mode 100644 index 069fb51e17dd..000000000000 --- a/websites/N/Novel Mania/v2/presence.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { ActivityType, Assets } from 'premid' - -const presence = new Presence({ - clientId: '738522217221980222', -}) -const browsingTimestamp = Math.floor(Date.now() / 1000) -enum ActivityAssets { - Logo = 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', -} -async function getStrings() { - return presence.getStrings({ - browse: 'general.browsing', - home: 'general.viewHome', - privacy: 'general.privacy', - reading: 'general.reading', - view: 'general.view', - volume: 'novelmania.volume', - profile: 'general.viewProfile', - lists: 'novelmania.lists', - news: 'novelmania.news', - genre: 'novelmania.genre', - novel: 'novelmania.novel', - readNovelButton: 'novelmania.readNovelButton', - readChapterButton: 'novelmania.readChapterButton', - visitWebsiteButton: 'novelmania.visitWebsiteButton', - readListButton: 'novelmania.readListButton', - readNewsButton: 'novelmania.readNewsButton', - visitUserProfileButton: 'novelmania.visitUserProfileButton', - }) -} -let oldUserLanguage: string | null = null -let strings: Awaited> - -presence.on('UpdateData', async () => { - strings = await getStrings() - - const [showButtons, showTime, hideInfo, userLanguage] = await Promise.all([ - presence.getSetting('showButtons') || true, - presence.getSetting('showTimestamp') || true, - presence.getSetting('hideInfo') || false, - presence.getSetting('lang').catch(() => 'pt') - ]); - - if (oldUserLanguage !== userLanguage) { - oldUserLanguage = userLanguage - strings = await getStrings() - } - - - const presenceData: PresenceData = { - largeImageKey: ActivityAssets.Logo, - startTimestamp: showTime ? browsingTimestamp : undefined, - type: ActivityType.Watching - - } - const { pathname, origin } = window.location - const cleanPath = pathname.replace(/\/$/, '') || '/' - const [part1, part2, part3, part4] = cleanPath.slice(1).split('/') // page, slug (if any), chapter (if any), volume/book (if any) - - const privacyCheck = (foo: any): string => { - return !hideInfo ? foo : strings.privacy - } - - const getPageTitle = (): string => document.querySelector('#main h1')?.textContent || strings.novel - let buttons: [ButtonData, ButtonData?] | undefined - - switch (part1) { - case '': - if (cleanPath === '/') { - presenceData.state = strings.home; - - buttons = [ - { - label: strings.visitWebsiteButton, - url: origin, - }, - ] - } - break - - case 'u': /* Seeing some user profile */ - if (part2) { - presenceData.details = `${strings.profile}` - presenceData.state = privacyCheck(getPageTitle()); - buttons = [ - { - label: strings.visitUserProfileButton, - url: origin + `/u/${part2}`, - }, - ] - } - break - - case 'novels': - if (!part2) { /* Searching some novel */ - presenceData.details = `${strings.browse}`; - presenceData.state = privacyCheck(getPageTitle()); - - const params = new URLSearchParams(window.location.search); - const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q'); - - if (searchTerm) { - presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}`; - } - - // Extrai nomes dos filtros - apenas se houver busca ou query params - if (searchTerm || window.location.search) { - const badges = document.querySelectorAll('span.inline-flex.rounded-full.border'); - if (badges.length > 0) { - const visibleFilters: string[] = []; - for (let i = 0; i < badges.length; i++) { - const text = badges[i]?.childNodes[0]?.textContent?.trim(); - if (text) visibleFilters.push(text); - } - if (visibleFilters.length) { - presenceData.state = privacyCheck(visibleFilters.join(', ')); - } - } - } - break - } - if (part3 === 'capitulos' && part4) { /* Reading some novel's chapter */ - const novelName = document.querySelector("#conteudo-principal > div > header > div > p")?.textContent || part2?.split('-').slice(0, 2).join(' ') || strings.novel; - const noveltype = document.querySelector("#conteudo-principal > div > main > div > div > header > p")?.textContent || part4?.split('-').slice(0, 2).join(' ') || strings.volume; - const currentChapTitle = document.querySelector("#reader-chapter-title")?.textContent || novelName; - - presenceData.details = `${strings.reading} ${privacyCheck(novelName)}`; - presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}`; - presenceData.smallImageKey = Assets.Reading - - buttons = [ - { - label: strings.readNovelButton, - url: origin + `/novels/${part2}`, - }, - { - label: strings.readChapterButton, - url: origin + `/novels/${part2}/capitulos/${part4}`, - }, - ] - break - } - if (part2) { /* At some novel's page */ - const novelName = document.querySelector("#main > div > h1")?.textContent || strings.novel - presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}`; - - buttons = [ - { - label: strings.readNovelButton, - url: origin + `/novels/${part2}`, - }, - ] - } - break - - case 'listas': /* Searching some lists */ - if (!part2) { - presenceData.state = `${strings.browse} ${strings.lists}`; - presenceData.smallImageKey = Assets.Reading - break - } - - presenceData.details = `${strings.view} ${strings.lists}`; - presenceData.state = `${privacyCheck(getPageTitle())} - ${privacyCheck(document.querySelector("#main > div > div:nth-child(2) > a")?.textContent || strings.novel)}`; - presenceData.smallImageKey = Assets.Reading - - buttons = [ - { - label: strings.readListButton, - url: origin + `/listas/${part2}`, - }, - ] - break - - case 'noticias': - if (!part2) { /* Searching some news */ - presenceData.details = `${strings.reading} ${strings.news}`; /* reading news list */ - presenceData.state = `${privacyCheck(getPageTitle())}`; - presenceData.smallImageKey = Assets.Reading - break - } - - presenceData.details = `${strings.reading} ${strings.news}`; /* reading a news */ - presenceData.state = `${privacyCheck(getPageTitle())}`; - presenceData.smallImageKey = Assets.Reading - - buttons = [ - { - label: strings.readNewsButton, - url: origin + `/noticias/${part2}`, - }, - ] - break - - case 'genero': /* Browsing some genres */ - if (part2) { - presenceData.details = `${strings.browse} ${strings.genre}`; - presenceData.state = privacyCheck(getPageTitle()); - presenceData.smallImageKey = Assets.Reading - } - break - - default: /* At any other page, it doesn't matter */ - presenceData.state = `${strings.view} ${privacyCheck(getPageTitle())}`; - presenceData.smallImageKey = Assets.Reading - break - } - - if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) - presenceData.buttons = buttons - - // Set the activity - if (presenceData.state) { - presence.setActivity(presenceData) - - if (!showTime) - delete presenceData.startTimestamp - - } else { - presence.clearActivity() - } -}) From 58342d519c319c8e3f1ddc230f493fd4e56199b5 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:05:52 -0300 Subject: [PATCH 04/14] update(Novel Mania): Remove versionize folders as I actually didn't needed them --- websites/N/Novel Mania/metadata.json | 61 +++++++ websites/N/Novel Mania/novelmania.json | 54 ++++++ websites/N/Novel Mania/presence.ts | 222 +++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 websites/N/Novel Mania/metadata.json create mode 100644 websites/N/Novel Mania/novelmania.json create mode 100644 websites/N/Novel Mania/presence.ts diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json new file mode 100644 index 000000000000..3fba9a9aa0ad --- /dev/null +++ b/websites/N/Novel Mania/metadata.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.premid.app/metadata/1.17", + "apiVersion": 1, + "author": { + "name": "Shuichi", + "id": "179440483796385792" + }, + "service": "Novel Mania", + "altnames": [ + "NovelMania" + ], + "description": { + "en": "Read webnovels in Portuguese anywhere and anytime.", + "pt-br": "Leia webnovels em português a qualquer momento e a qualquer hora." + }, + "url": "novelmania.com.br", + "regExp": "^https?[:][/][/]([a-z0-9-]+[.])*novelmania[.]com[.]br[/]", + "version": "2.0.0", + "logo": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png", + "thumbnail": "https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/thumbnail.jpg", + "color": "#008cff", + "category": "other", + "tags": [ + "novel", + "lightnovel", + "light novel", + "webnovel", + "web novel", + "reader", + "scanlator", + "translation", + "book" + ], + "settings": [ + { + "id": "lang", + "multiLanguage": true + }, + { + "id": "hideInfo", + "title": "Privacy Mode", + "icon": "fas fa-compress-arrows-alt", + "value": false + }, + { + "id": "showButtons", + "title": "Show Buttons", + "icon": "fas fa-compress-arrows-alt", + "value": true, + "if": { + "showInfo": false + } + }, + { + "id": "showTimestamp", + "title": "Show Timestamp", + "icon": "fas fa-clock", + "value": true + } + ] +} \ No newline at end of file diff --git a/websites/N/Novel Mania/novelmania.json b/websites/N/Novel Mania/novelmania.json new file mode 100644 index 000000000000..a094bd0bab9c --- /dev/null +++ b/websites/N/Novel Mania/novelmania.json @@ -0,0 +1,54 @@ +{ + "novelmania.volume": { + "description": "Text for when user's reading a novel with volumes.", + "message": "Volume" + }, + "novelmania.book": { + "description": "Text for when user's reading a novel with books.", + "message": "Book" + }, + "novelmania.viewingProfile": { + "description": "Text for when user's visualizing someone's profile.", + "message": "Viewing profile" + }, + "novelmania.lists": { + "description": "Text for when user's visualizing 'lists' page.", + "message": "listas" + }, + "novelmania.news": { + "description": "Text for when user's visualizing 'news' page.", + "message": "news" + }, + "novelmania.genre": { + "description": "Text for when user's browsing genres.", + "message": "genres" + }, + "novelmania.novel": { + "description": "Just a placeholder for a novel title. It doesn't matter what it is, it will be replaced by the actual title.", + "message": "novel" + }, + "novelmania.readNovelButton": { + "description": "", + "message": "Read this novel!" + }, + "novelmania.readChapterButton": { + "description": "Text from 'reading chapter button'. Call to read along!", + "message": "Read this chapter!" + }, + "novelmania.visitWebsiteButton": { + "description": "Text from 'visit website button'.", + "message": "Visit this website!" + }, + "novelmania.readListButton": { + "description": "Text from 'read this list button'.", + "message": "Read this list!" + }, + "novelmania.readNewsButton": { + "description": "Text from 'read this news button'.", + "message": "Read this news!" + }, + "novelmania.visitUserProfileButton": { + "description": "Text from 'spy on this user button'. Naughty, naughty...", + "message": "Spy on this user!" + } +} \ No newline at end of file diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts new file mode 100644 index 000000000000..069fb51e17dd --- /dev/null +++ b/websites/N/Novel Mania/presence.ts @@ -0,0 +1,222 @@ +import { ActivityType, Assets } from 'premid' + +const presence = new Presence({ + clientId: '738522217221980222', +}) +const browsingTimestamp = Math.floor(Date.now() / 1000) +enum ActivityAssets { + Logo = 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', +} +async function getStrings() { + return presence.getStrings({ + browse: 'general.browsing', + home: 'general.viewHome', + privacy: 'general.privacy', + reading: 'general.reading', + view: 'general.view', + volume: 'novelmania.volume', + profile: 'general.viewProfile', + lists: 'novelmania.lists', + news: 'novelmania.news', + genre: 'novelmania.genre', + novel: 'novelmania.novel', + readNovelButton: 'novelmania.readNovelButton', + readChapterButton: 'novelmania.readChapterButton', + visitWebsiteButton: 'novelmania.visitWebsiteButton', + readListButton: 'novelmania.readListButton', + readNewsButton: 'novelmania.readNewsButton', + visitUserProfileButton: 'novelmania.visitUserProfileButton', + }) +} +let oldUserLanguage: string | null = null +let strings: Awaited> + +presence.on('UpdateData', async () => { + strings = await getStrings() + + const [showButtons, showTime, hideInfo, userLanguage] = await Promise.all([ + presence.getSetting('showButtons') || true, + presence.getSetting('showTimestamp') || true, + presence.getSetting('hideInfo') || false, + presence.getSetting('lang').catch(() => 'pt') + ]); + + if (oldUserLanguage !== userLanguage) { + oldUserLanguage = userLanguage + strings = await getStrings() + } + + + const presenceData: PresenceData = { + largeImageKey: ActivityAssets.Logo, + startTimestamp: showTime ? browsingTimestamp : undefined, + type: ActivityType.Watching + + } + const { pathname, origin } = window.location + const cleanPath = pathname.replace(/\/$/, '') || '/' + const [part1, part2, part3, part4] = cleanPath.slice(1).split('/') // page, slug (if any), chapter (if any), volume/book (if any) + + const privacyCheck = (foo: any): string => { + return !hideInfo ? foo : strings.privacy + } + + const getPageTitle = (): string => document.querySelector('#main h1')?.textContent || strings.novel + let buttons: [ButtonData, ButtonData?] | undefined + + switch (part1) { + case '': + if (cleanPath === '/') { + presenceData.state = strings.home; + + buttons = [ + { + label: strings.visitWebsiteButton, + url: origin, + }, + ] + } + break + + case 'u': /* Seeing some user profile */ + if (part2) { + presenceData.details = `${strings.profile}` + presenceData.state = privacyCheck(getPageTitle()); + buttons = [ + { + label: strings.visitUserProfileButton, + url: origin + `/u/${part2}`, + }, + ] + } + break + + case 'novels': + if (!part2) { /* Searching some novel */ + presenceData.details = `${strings.browse}`; + presenceData.state = privacyCheck(getPageTitle()); + + const params = new URLSearchParams(window.location.search); + const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q'); + + if (searchTerm) { + presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}`; + } + + // Extrai nomes dos filtros - apenas se houver busca ou query params + if (searchTerm || window.location.search) { + const badges = document.querySelectorAll('span.inline-flex.rounded-full.border'); + if (badges.length > 0) { + const visibleFilters: string[] = []; + for (let i = 0; i < badges.length; i++) { + const text = badges[i]?.childNodes[0]?.textContent?.trim(); + if (text) visibleFilters.push(text); + } + if (visibleFilters.length) { + presenceData.state = privacyCheck(visibleFilters.join(', ')); + } + } + } + break + } + if (part3 === 'capitulos' && part4) { /* Reading some novel's chapter */ + const novelName = document.querySelector("#conteudo-principal > div > header > div > p")?.textContent || part2?.split('-').slice(0, 2).join(' ') || strings.novel; + const noveltype = document.querySelector("#conteudo-principal > div > main > div > div > header > p")?.textContent || part4?.split('-').slice(0, 2).join(' ') || strings.volume; + const currentChapTitle = document.querySelector("#reader-chapter-title")?.textContent || novelName; + + presenceData.details = `${strings.reading} ${privacyCheck(novelName)}`; + presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readNovelButton, + url: origin + `/novels/${part2}`, + }, + { + label: strings.readChapterButton, + url: origin + `/novels/${part2}/capitulos/${part4}`, + }, + ] + break + } + if (part2) { /* At some novel's page */ + const novelName = document.querySelector("#main > div > h1")?.textContent || strings.novel + presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}`; + + buttons = [ + { + label: strings.readNovelButton, + url: origin + `/novels/${part2}`, + }, + ] + } + break + + case 'listas': /* Searching some lists */ + if (!part2) { + presenceData.state = `${strings.browse} ${strings.lists}`; + presenceData.smallImageKey = Assets.Reading + break + } + + presenceData.details = `${strings.view} ${strings.lists}`; + presenceData.state = `${privacyCheck(getPageTitle())} - ${privacyCheck(document.querySelector("#main > div > div:nth-child(2) > a")?.textContent || strings.novel)}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readListButton, + url: origin + `/listas/${part2}`, + }, + ] + break + + case 'noticias': + if (!part2) { /* Searching some news */ + presenceData.details = `${strings.reading} ${strings.news}`; /* reading news list */ + presenceData.state = `${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + break + } + + presenceData.details = `${strings.reading} ${strings.news}`; /* reading a news */ + presenceData.state = `${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + + buttons = [ + { + label: strings.readNewsButton, + url: origin + `/noticias/${part2}`, + }, + ] + break + + case 'genero': /* Browsing some genres */ + if (part2) { + presenceData.details = `${strings.browse} ${strings.genre}`; + presenceData.state = privacyCheck(getPageTitle()); + presenceData.smallImageKey = Assets.Reading + } + break + + default: /* At any other page, it doesn't matter */ + presenceData.state = `${strings.view} ${privacyCheck(getPageTitle())}`; + presenceData.smallImageKey = Assets.Reading + break + } + + if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) + presenceData.buttons = buttons + + // Set the activity + if (presenceData.state) { + presence.setActivity(presenceData) + + if (!showTime) + delete presenceData.startTimestamp + + } else { + presence.clearActivity() + } +}) From 214401d9cd2d13c654eff2de00f612135136d712 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:09:09 -0300 Subject: [PATCH 05/14] small change... --- websites/N/Novel Mania/metadata.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json index 3fba9a9aa0ad..2b9422a0a967 100644 --- a/websites/N/Novel Mania/metadata.json +++ b/websites/N/Novel Mania/metadata.json @@ -11,6 +11,7 @@ ], "description": { "en": "Read webnovels in Portuguese anywhere and anytime.", + "nl": "Lees overal en altijd webnovels in het Portugees.", "pt-br": "Leia webnovels em português a qualquer momento e a qualquer hora." }, "url": "novelmania.com.br", @@ -22,6 +23,8 @@ "category": "other", "tags": [ "novel", + "mania", + "translator", "lightnovel", "light novel", "webnovel", From 5532a1eb27fe5d1871ef28278d77ac9de4b71ff2 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:20:09 -0300 Subject: [PATCH 06/14] =?UTF-8?q?small=20change=20=C2=B2...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- websites/N/Novel Mania/presence.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts index 069fb51e17dd..925909a0277f 100644 --- a/websites/N/Novel Mania/presence.ts +++ b/websites/N/Novel Mania/presence.ts @@ -49,7 +49,7 @@ presence.on('UpdateData', async () => { const presenceData: PresenceData = { largeImageKey: ActivityAssets.Logo, - startTimestamp: showTime ? browsingTimestamp : undefined, + startTimestamp: browsingTimestamp, type: ActivityType.Watching } From b7514b555fd67de26f145bb562a5750b6b190fe1 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:25:03 -0300 Subject: [PATCH 07/14] =?UTF-8?q?small=20change=20=C2=B3...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- websites/N/Novel Mania/metadata.json | 2 +- websites/N/Novel Mania/novelmania.json | 106 ++++++++++++------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json index 2b9422a0a967..e2ac14e93707 100644 --- a/websites/N/Novel Mania/metadata.json +++ b/websites/N/Novel Mania/metadata.json @@ -61,4 +61,4 @@ "value": true } ] -} \ No newline at end of file +} diff --git a/websites/N/Novel Mania/novelmania.json b/websites/N/Novel Mania/novelmania.json index a094bd0bab9c..08ba60ff2a6e 100644 --- a/websites/N/Novel Mania/novelmania.json +++ b/websites/N/Novel Mania/novelmania.json @@ -1,54 +1,54 @@ { - "novelmania.volume": { - "description": "Text for when user's reading a novel with volumes.", - "message": "Volume" - }, - "novelmania.book": { - "description": "Text for when user's reading a novel with books.", - "message": "Book" - }, - "novelmania.viewingProfile": { - "description": "Text for when user's visualizing someone's profile.", - "message": "Viewing profile" - }, - "novelmania.lists": { - "description": "Text for when user's visualizing 'lists' page.", - "message": "listas" - }, - "novelmania.news": { - "description": "Text for when user's visualizing 'news' page.", - "message": "news" - }, - "novelmania.genre": { - "description": "Text for when user's browsing genres.", - "message": "genres" - }, - "novelmania.novel": { - "description": "Just a placeholder for a novel title. It doesn't matter what it is, it will be replaced by the actual title.", - "message": "novel" - }, - "novelmania.readNovelButton": { - "description": "", - "message": "Read this novel!" - }, - "novelmania.readChapterButton": { - "description": "Text from 'reading chapter button'. Call to read along!", - "message": "Read this chapter!" - }, - "novelmania.visitWebsiteButton": { - "description": "Text from 'visit website button'.", - "message": "Visit this website!" - }, - "novelmania.readListButton": { - "description": "Text from 'read this list button'.", - "message": "Read this list!" - }, - "novelmania.readNewsButton": { - "description": "Text from 'read this news button'.", - "message": "Read this news!" - }, - "novelmania.visitUserProfileButton": { - "description": "Text from 'spy on this user button'. Naughty, naughty...", - "message": "Spy on this user!" - } -} \ No newline at end of file + "novelmania.volume": { + "description": "Text for when user's reading a novel with volumes.", + "message": "Volume" + }, + "novelmania.book": { + "description": "Text for when user's reading a novel with books.", + "message": "Book" + }, + "novelmania.viewingProfile": { + "description": "Text for when user's visualizing someone's profile.", + "message": "Viewing profile" + }, + "novelmania.lists": { + "description": "Text for when user's visualizing 'lists' page.", + "message": "listas" + }, + "novelmania.news": { + "description": "Text for when user's visualizing 'news' page.", + "message": "news" + }, + "novelmania.genre": { + "description": "Text for when user's browsing genres.", + "message": "genres" + }, + "novelmania.novel": { + "description": "Just a placeholder for a novel title. It doesn't matter what it is, it will be replaced by the actual title.", + "message": "novel" + }, + "novelmania.readNovelButton": { + "description": "", + "message": "Read this novel!" + }, + "novelmania.readChapterButton": { + "description": "Text from 'reading chapter button'. Call to read along!", + "message": "Read this chapter!" + }, + "novelmania.visitWebsiteButton": { + "description": "Text from 'visit website button'.", + "message": "Visit this website!" + }, + "novelmania.readListButton": { + "description": "Text from 'read this list button'.", + "message": "Read this list!" + }, + "novelmania.readNewsButton": { + "description": "Text from 'read this news button'.", + "message": "Read this news!" + }, + "novelmania.visitUserProfileButton": { + "description": "Text from 'spy on this user button'. Naughty, naughty...", + "message": "Spy on this user!" + } +} From 661e52f81eb15b5f383c1d74a6b3713a66565116 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 11:56:39 -0300 Subject: [PATCH 08/14] Fixing lint match pattern error in tags --- websites/N/Novel Mania/metadata.json | 15 ++--- websites/N/Novel Mania/presence.ts | 84 ++++++++++++++-------------- 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json index e2ac14e93707..e0549df10314 100644 --- a/websites/N/Novel Mania/metadata.json +++ b/websites/N/Novel Mania/metadata.json @@ -22,17 +22,18 @@ "color": "#008cff", "category": "other", "tags": [ - "novel", - "mania", - "translator", + "novel-mania", + "translation", "lightnovel", - "light novel", + "light-novel-translation", "webnovel", - "web novel", + "web-novel-translation", "reader", "scanlator", - "translation", - "book" + "novel-translation", + "book", + "books", + "book-translation" ], "settings": [ { diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts index 925909a0277f..ef4c3d946ea0 100644 --- a/websites/N/Novel Mania/presence.ts +++ b/websites/N/Novel Mania/presence.ts @@ -38,19 +38,18 @@ presence.on('UpdateData', async () => { presence.getSetting('showButtons') || true, presence.getSetting('showTimestamp') || true, presence.getSetting('hideInfo') || false, - presence.getSetting('lang').catch(() => 'pt') - ]); + presence.getSetting('lang').catch(() => 'pt'), + ]) if (oldUserLanguage !== userLanguage) { oldUserLanguage = userLanguage strings = await getStrings() } - const presenceData: PresenceData = { largeImageKey: ActivityAssets.Logo, startTimestamp: browsingTimestamp, - type: ActivityType.Watching + type: ActivityType.Watching, } const { pathname, origin } = window.location @@ -67,7 +66,7 @@ presence.on('UpdateData', async () => { switch (part1) { case '': if (cleanPath === '/') { - presenceData.state = strings.home; + presenceData.state = strings.home buttons = [ { @@ -81,11 +80,11 @@ presence.on('UpdateData', async () => { case 'u': /* Seeing some user profile */ if (part2) { presenceData.details = `${strings.profile}` - presenceData.state = privacyCheck(getPageTitle()); + presenceData.state = privacyCheck(getPageTitle()) buttons = [ { label: strings.visitUserProfileButton, - url: origin + `/u/${part2}`, + url: `${origin}/u/${part2}`, }, ] } @@ -93,61 +92,62 @@ presence.on('UpdateData', async () => { case 'novels': if (!part2) { /* Searching some novel */ - presenceData.details = `${strings.browse}`; - presenceData.state = privacyCheck(getPageTitle()); + presenceData.details = `${strings.browse}` + presenceData.state = privacyCheck(getPageTitle()) - const params = new URLSearchParams(window.location.search); - const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q'); + const params = new URLSearchParams(window.location.search) + const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q') if (searchTerm) { - presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}`; + presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}` } // Extrai nomes dos filtros - apenas se houver busca ou query params if (searchTerm || window.location.search) { - const badges = document.querySelectorAll('span.inline-flex.rounded-full.border'); + const badges = document.querySelectorAll('span.inline-flex.rounded-full.border') if (badges.length > 0) { - const visibleFilters: string[] = []; + const visibleFilters: string[] = [] for (let i = 0; i < badges.length; i++) { - const text = badges[i]?.childNodes[0]?.textContent?.trim(); - if (text) visibleFilters.push(text); + const text = badges[i]?.childNodes[0]?.textContent?.trim() + if (text) + visibleFilters.push(text) } if (visibleFilters.length) { - presenceData.state = privacyCheck(visibleFilters.join(', ')); + presenceData.state = privacyCheck(visibleFilters.join(', ')) } } } break } if (part3 === 'capitulos' && part4) { /* Reading some novel's chapter */ - const novelName = document.querySelector("#conteudo-principal > div > header > div > p")?.textContent || part2?.split('-').slice(0, 2).join(' ') || strings.novel; - const noveltype = document.querySelector("#conteudo-principal > div > main > div > div > header > p")?.textContent || part4?.split('-').slice(0, 2).join(' ') || strings.volume; - const currentChapTitle = document.querySelector("#reader-chapter-title")?.textContent || novelName; + const novelName = document.querySelector('#conteudo-principal > div > header > div > p')?.textContent || part2?.split('-').slice(0, 2).join(' ') || strings.novel + const noveltype = document.querySelector('#conteudo-principal > div > main > div > div > header > p')?.textContent || part4?.split('-').slice(0, 2).join(' ') || strings.volume + const currentChapTitle = document.querySelector('#reader-chapter-title')?.textContent || novelName - presenceData.details = `${strings.reading} ${privacyCheck(novelName)}`; - presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}`; + presenceData.details = `${strings.reading} ${privacyCheck(novelName)}` + presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}` presenceData.smallImageKey = Assets.Reading buttons = [ { label: strings.readNovelButton, - url: origin + `/novels/${part2}`, + url: `${origin}/novels/${part2}`, }, { label: strings.readChapterButton, - url: origin + `/novels/${part2}/capitulos/${part4}`, + url: `${origin}/novels/${part2}/capitulos/${part4}`, }, ] break } if (part2) { /* At some novel's page */ - const novelName = document.querySelector("#main > div > h1")?.textContent || strings.novel - presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}`; + const novelName = document.querySelector('#main > div > h1')?.textContent || strings.novel + presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}` buttons = [ { label: strings.readNovelButton, - url: origin + `/novels/${part2}`, + url: `${origin}/novels/${part2}`, }, ] } @@ -155,53 +155,53 @@ presence.on('UpdateData', async () => { case 'listas': /* Searching some lists */ if (!part2) { - presenceData.state = `${strings.browse} ${strings.lists}`; + presenceData.state = `${strings.browse} ${strings.lists}` presenceData.smallImageKey = Assets.Reading break } - presenceData.details = `${strings.view} ${strings.lists}`; - presenceData.state = `${privacyCheck(getPageTitle())} - ${privacyCheck(document.querySelector("#main > div > div:nth-child(2) > a")?.textContent || strings.novel)}`; + presenceData.details = `${strings.view} ${strings.lists}` + presenceData.state = `${privacyCheck(getPageTitle())} - ${privacyCheck(document.querySelector('#main > div > div:nth-child(2) > a')?.textContent || strings.novel)}` presenceData.smallImageKey = Assets.Reading buttons = [ { label: strings.readListButton, - url: origin + `/listas/${part2}`, + url: `${origin}/listas/${part2}`, }, ] break case 'noticias': - if (!part2) { /* Searching some news */ - presenceData.details = `${strings.reading} ${strings.news}`; /* reading news list */ - presenceData.state = `${privacyCheck(getPageTitle())}`; + if (!part2) { /* Searching some news */ + presenceData.details = `${strings.reading} ${strings.news}` /* reading news list */ + presenceData.state = `${privacyCheck(getPageTitle())}` presenceData.smallImageKey = Assets.Reading break } - presenceData.details = `${strings.reading} ${strings.news}`; /* reading a news */ - presenceData.state = `${privacyCheck(getPageTitle())}`; + presenceData.details = `${strings.reading} ${strings.news}` /* reading a news */ + presenceData.state = `${privacyCheck(getPageTitle())}` presenceData.smallImageKey = Assets.Reading buttons = [ { label: strings.readNewsButton, - url: origin + `/noticias/${part2}`, + url: `${origin}/noticias/${part2}`, }, ] break case 'genero': /* Browsing some genres */ if (part2) { - presenceData.details = `${strings.browse} ${strings.genre}`; - presenceData.state = privacyCheck(getPageTitle()); + presenceData.details = `${strings.browse} ${strings.genre}` + presenceData.state = privacyCheck(getPageTitle()) presenceData.smallImageKey = Assets.Reading } break default: /* At any other page, it doesn't matter */ - presenceData.state = `${strings.view} ${privacyCheck(getPageTitle())}`; + presenceData.state = `${strings.view} ${privacyCheck(getPageTitle())}` presenceData.smallImageKey = Assets.Reading break } @@ -215,8 +215,8 @@ presence.on('UpdateData', async () => { if (!showTime) delete presenceData.startTimestamp - - } else { + } + else { presence.clearActivity() } }) From 70724745f8b17d7d9180a4aa13e0e8a43d5a5202 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 12:01:13 -0300 Subject: [PATCH 09/14] Translating a comment --- websites/N/Novel Mania/presence.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts index ef4c3d946ea0..41eec86d417c 100644 --- a/websites/N/Novel Mania/presence.ts +++ b/websites/N/Novel Mania/presence.ts @@ -102,7 +102,7 @@ presence.on('UpdateData', async () => { presenceData.details = `${strings.browse} ${privacyCheck(decodeURIComponent(searchTerm))}` } - // Extrai nomes dos filtros - apenas se houver busca ou query params + /* Extract query params while searching for some novel */ if (searchTerm || window.location.search) { const badges = document.querySelectorAll('span.inline-flex.rounded-full.border') if (badges.length > 0) { From 9ddf4662b96e6e8b30639343f6638b50707a8986 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 12:25:46 -0300 Subject: [PATCH 10/14] Fix timestamp. Not in the mood to make one for each state --- websites/N/Novel Mania/presence.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts index 41eec86d417c..aa6cf3b0be02 100644 --- a/websites/N/Novel Mania/presence.ts +++ b/websites/N/Novel Mania/presence.ts @@ -3,7 +3,8 @@ import { ActivityType, Assets } from 'premid' const presence = new Presence({ clientId: '738522217221980222', }) -const browsingTimestamp = Math.floor(Date.now() / 1000) +let browsingTimestamp = Math.floor(Date.now() / 1000) + enum ActivityAssets { Logo = 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', } @@ -94,7 +95,6 @@ presence.on('UpdateData', async () => { if (!part2) { /* Searching some novel */ presenceData.details = `${strings.browse}` presenceData.state = privacyCheck(getPageTitle()) - const params = new URLSearchParams(window.location.search) const searchTerm = (document.querySelector('input[name="q"]') as HTMLInputElement)?.value || params.get('q') @@ -127,7 +127,6 @@ presence.on('UpdateData', async () => { presenceData.details = `${strings.reading} ${privacyCheck(novelName)}` presenceData.state = `${privacyCheck(currentChapTitle)} - ${privacyCheck(noveltype)}` presenceData.smallImageKey = Assets.Reading - buttons = [ { label: strings.readNovelButton, @@ -143,7 +142,6 @@ presence.on('UpdateData', async () => { if (part2) { /* At some novel's page */ const novelName = document.querySelector('#main > div > h1')?.textContent || strings.novel presenceData.state = ` ${strings.view} ${privacyCheck(novelName)}` - buttons = [ { label: strings.readNovelButton, @@ -157,6 +155,7 @@ presence.on('UpdateData', async () => { if (!part2) { presenceData.state = `${strings.browse} ${strings.lists}` presenceData.smallImageKey = Assets.Reading + break } @@ -206,15 +205,14 @@ presence.on('UpdateData', async () => { break } - if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) - presenceData.buttons = buttons - // Set the activity if (presenceData.state) { - presence.setActivity(presenceData) - if (!showTime) delete presenceData.startTimestamp + if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) + presenceData.buttons = buttons + presence.setActivity(presenceData) + } else { presence.clearActivity() From 774fb8102285adb24ef7227138ff9872105376f1 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 12:52:29 -0300 Subject: [PATCH 11/14] Fix more lint errors --- websites/N/Novel Mania/presence.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/websites/N/Novel Mania/presence.ts b/websites/N/Novel Mania/presence.ts index aa6cf3b0be02..cdd226369f74 100644 --- a/websites/N/Novel Mania/presence.ts +++ b/websites/N/Novel Mania/presence.ts @@ -3,7 +3,7 @@ import { ActivityType, Assets } from 'premid' const presence = new Presence({ clientId: '738522217221980222', }) -let browsingTimestamp = Math.floor(Date.now() / 1000) +const browsingTimestamp = Math.floor(Date.now() / 1000) enum ActivityAssets { Logo = 'https://cdn.rcd.gg/PreMiD/websites/N/Novel%20Mania/assets/logo.png', @@ -207,12 +207,13 @@ presence.on('UpdateData', async () => { // Set the activity if (presenceData.state) { - if (!showTime) + if (!showTime) { delete presenceData.startTimestamp - if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) + } + if (showButtons && buttons && (cleanPath === '/' || !hideInfo)) { presenceData.buttons = buttons + } presence.setActivity(presenceData) - } else { presence.clearActivity() From 9e6b65648fd2cf28abd616a99592cac6cddf3991 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 13:02:56 -0300 Subject: [PATCH 12/14] I forgor my discord name have changed... --- websites/N/Novel Mania/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json index e0549df10314..2b933388751e 100644 --- a/websites/N/Novel Mania/metadata.json +++ b/websites/N/Novel Mania/metadata.json @@ -2,7 +2,7 @@ "$schema": "https://schemas.premid.app/metadata/1.17", "apiVersion": 1, "author": { - "name": "Shuichi", + "name": "obudista", "id": "179440483796385792" }, "service": "Novel Mania", @@ -62,4 +62,4 @@ "value": true } ] -} +} \ No newline at end of file From 877623fb26d7c9ad4cd76578d34f58848ecd7af7 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 13:18:14 -0300 Subject: [PATCH 13/14] This bot's nuts --- websites/N/Novel Mania/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websites/N/Novel Mania/metadata.json b/websites/N/Novel Mania/metadata.json index 2b933388751e..65fd4ac93d75 100644 --- a/websites/N/Novel Mania/metadata.json +++ b/websites/N/Novel Mania/metadata.json @@ -62,4 +62,4 @@ "value": true } ] -} \ No newline at end of file +} From 0e87e1637e7551f97174fa578c841c5968821f74 Mon Sep 17 00:00:00 2001 From: Shulchl Date: Fri, 3 Jul 2026 16:32:40 -0300 Subject: [PATCH 14/14] it went unnoticed... --- websites/N/Novel Mania/novelmania.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websites/N/Novel Mania/novelmania.json b/websites/N/Novel Mania/novelmania.json index 08ba60ff2a6e..bdce914c113f 100644 --- a/websites/N/Novel Mania/novelmania.json +++ b/websites/N/Novel Mania/novelmania.json @@ -13,7 +13,7 @@ }, "novelmania.lists": { "description": "Text for when user's visualizing 'lists' page.", - "message": "listas" + "message": "lists" }, "novelmania.news": { "description": "Text for when user's visualizing 'news' page.", @@ -28,7 +28,7 @@ "message": "novel" }, "novelmania.readNovelButton": { - "description": "", + "description": "Text from 'viewing novel's button'.", "message": "Read this novel!" }, "novelmania.readChapterButton": {