Compare commits

..

130 Commits

Author SHA1 Message Date
Chopper
5ecf338be0
DiskusScan: Fix headers (#4568)
All checks were successful
CI / Prepare job (push) Successful in 6s
CI / Build individual modules (push) Successful in 4m11s
CI / Publish repo (push) Successful in 46s
Fix headers
2024-08-13 02:32:09 +01:00
子斗子
d2ad77c0a3
[NHentai] fix group info (#4567)
* fix group name.

* update extVersionCode
2024-08-13 02:32:09 +01:00
Vetle Ledaal
ac55757327
Add ManhwaFreak.xyz (#4547)
* Add Manhwa Freak

* rename

* rename2
2024-08-13 02:32:02 +01:00
KenjieDec
a1c813a40d
HentaiDex | Added HentaiDex (#4534)
* Add HentaiDex

* Thumbnail

* Use mangathemesia

* Use mangathemesia

* Use mangathemesia

* Apply suggestion

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* Fix chapters location

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:32:02 +01:00
AwkwardPeak7
9211ccee37
ZinChanManga: cleaner titles (#4560) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
10a0b67bf4
HentaiWebtoon: fix chapter list & search (#4559) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
e67653580e
Add Manhwalist.org (#4555) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
69ace8bba9
Remove KomikNesia (#4554) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
b1f0d14217
Add Void Scans (#4552) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
9ee1be41b8
Add YD-Comics (#4551) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
89dbb360d3
ManhwaLand.mom: update domain (#4550) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
15aebe8edb
Add Varna Scan (#4549) 2024-08-13 02:32:02 +01:00
Vetle Ledaal
b4dd656175
Add Snow Scans (#4548) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
c62cec150f
HentaiManga: fix chapter list & search (#4546) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
77ac036786
StrayFansub: update theme (#4545) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
39b1e20401
update domains (#4544)
* MangaSwat: update domain
	closes #4543

* HattoriManga: update domain
	closes #4541

* bump

* jiangzaitoon: update domain
	closes #4537

* fleurblanche: update domain
2024-08-13 02:32:02 +01:00
KenjieDec
b65681b8b7
SpyFakku | Fix SpyFakku (#4540)
FIx Spyfakku

- Use api again
2024-08-13 02:32:02 +01:00
KenjieDec
db149972bd
Koharu | Fix Pages (#4539)
Fix Pages

- Fix Chapter Images
- Fix Chapter not being viewable when quality's `id` or `public_key` is not provided
2024-08-13 02:32:02 +01:00
AwkwardPeak7
b99fc8af0d
MangaPro: deproxify images (#4533)
* MangaPro: deproxify images

* remove log
2024-08-13 02:32:02 +01:00
AwkwardPeak7
41cebfbf1d
TempleScan: fix comic list (#4531)
bruh
2024-08-13 02:32:02 +01:00
AwkwardPeak7
ca739c2278
HentaiCosplay: update domain (#4530) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
10a970a56d
remove instamanhwa (#4528) 2024-08-13 02:32:02 +01:00
AwkwardPeak7
32220c1673
MangaDistrict: get absolute dates from page list (#4527)
* MangaDistrict: get absolute dates from page list

* tfw
2024-08-13 02:32:01 +01:00
KenjieDec
d63c947ca7
ColoredManga | Increase extVersionCode to match for older versions (#4526)
Apply suggestion
2024-08-13 02:32:01 +01:00
AwkwardPeak7
48b0101075
ManhwaIndo: update domain & deduplicate images (#4513) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
a14bf9cc8b
WebDexScans: update manga url directory (#4512) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
fc27271192
InstaManhwa: fix (#4511) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
18863bcd7f
EnryuManga: update domain (#4510) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
292bcc93bd
ngkomik: update domain (#4508) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
6b764484d6
Kiryuu: fix image mime (#4507) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
490a7b1c0c
BlogTruyen: update page list selector (#4506)
BlogTruyen: update domain
2024-08-13 02:31:58 +01:00
AwkwardPeak7
afe2bf4e55
HunlightScans: reverse chapter list (#4504) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
e0a7051166
manjanoon: update domain (#4503) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
f4124bb944
alceascan: update domain (#4502) 2024-08-13 02:31:58 +01:00
KenjieDec
159bee785a
ManyToon & ManhwaHentaiMe | Fix Next Page Selector (#4500)
Fix Next Page Selector

- ManyToon: Fix Next Page Selector and Filters
- ManwhaHentaiMe: Fix Next Page Selector
2024-08-13 02:31:58 +01:00
TheKingTermux
2bab0cccdb
Add Crotpedia (#4489)
* Add CrotPedia

This is my first Ext
CMIIW

* Update CrotPedia.kt
2024-08-13 02:31:58 +01:00
KenjieDec
a27b852546
ManyToon | Fix Search (#4480)
* Fix Search

* Little Change

* lint
2024-08-13 02:31:58 +01:00
Chopper
4955c0f1e5
SushiScan: Add random UA (#4479)
Add UA
2024-08-13 02:31:58 +01:00
AwkwardPeak7
fa0910b72c
ManhwaDesu: update domain (#4477) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
425d6e839d
RocksManga: fix selectors and domain (#4476) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
93c5a106c4
Hentai2Read: update filters (#4475) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
4a7de77df7
Gri Melek: update domain (#4474) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
847f8d084f
Comicaso: change domain and fix page list (#4473) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
6711c29e74
MangaClick -> MangaHall: update domain (#4472)
MangaClick -> MangaHill: update domain
2024-08-13 02:31:58 +01:00
KenjieDec
b6cf811a63
ManhwaHentaiMe | Fixed Latest & Filters (#4450)
* Fix Latest, Fix Filters

- Their website is kinda broken right now | 'Latest' and 'Newest' have the same result

* Apply suggestion?

- Apply AwkwardPeak's suggestion

* lint
2024-08-13 02:31:58 +01:00
Chopper
18b6668b54
Remove AgiToon (#4465) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
987aa83570
ManyToons: fix chapter list & search (#4459) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
7ac206a61a
MikrokosmosFansub: fix page list (#4458) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
fdcae35d12
nekopost: fix webview urls (#4456) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
5fca0cb71f
kaiscans -> luascans (unoriginal): update domain (#4455)
* kaiscans -> luascans (unoriginal): update domain

* oops
2024-08-13 02:31:58 +01:00
AwkwardPeak7
271855037e
komiktap: correct image mime type (#4454) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
0ea2b99616
Utoon: filter paid chapters (#4453) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
c16c663fba
remove: TheGuild (#4452) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
b50b2c3275
MangaTop -> MangaScans: update domain (#4451) 2024-08-13 02:31:58 +01:00
AwkwardPeak7
6f51e9d50f
Vortex: fix page list (#4449) 2024-08-13 02:31:58 +01:00
are-are-are
45ec1a302d
Update NettruyenCO URL Change (#4448) 2024-08-13 02:31:58 +01:00
Wackery
6f98841b14
HeanCMS: Add chapter title support (#4447) 2024-08-13 02:31:58 +01:00
KenjieDec
cdb8de9fbf
Spyfakku | Fixed Some Images Not Loading (#4444)
* Fixed Some Images Not Loading

- Also Fixed Manga & Chapter Webview URL

* Update extVersionCode

* Fix?

* Little Change

- The website itself already provides cased tags
2024-08-13 02:31:58 +01:00
Chopper
9730a445c8
BlackoutComics: Fix loading pages (#4440)
* Fix loading pages

* Cleanup
2024-08-13 02:31:58 +01:00
Pedro Azevedo
a4558c60eb
HuntersScans: Updated Domain (#4438) 2024-08-13 02:31:58 +01:00
bapeey
6b8d072c6c
AsuraScans: Fix pages selector (#4432)
lel
2024-08-13 02:31:58 +01:00
bapeey
8b0ff6e537
IkigaiMangas: Update domain (#4427)
update domain again
2024-08-13 02:31:58 +01:00
Chopper
99caea527a
Add AltayScans (#4420) 2024-08-13 02:31:58 +01:00
Chopper
f765a61aa4
LunarScan(PT): Update domain (#4419)
Update domain
2024-08-13 02:31:58 +01:00
Vetle Ledaal
fb6bd6a041
PussyToons: fix duplicate entries (#4417) 2024-08-13 02:31:57 +01:00
Chaos Pjeles
39f83d1d77
foamgirl impl (#4407)
* impl

* Update src/all/foamgirl/src/eu/kanade/tachiyomi/extension/all/foamgirl/FoamGirl.kt

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* resolve suggestions

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:31:57 +01:00
Chopper
c78f0e45f1
Add DarkRoomFansub (#4406)
* Add DarkRoomFansub

* Some changes

* Remove URI fragment
2024-08-13 02:31:57 +01:00
kana-shii
cea1f3c81c
More scanlator stuff for batoto (#4398)
* scanlator stuff

* Update build.gradle

* Update BatoTo.kt

* fix

this was the only way I found to make the "unknown" work tbh.
prayge
2024-08-13 02:31:57 +01:00
bapeey
cca5e276d2
TMO / LectorManga: Move to factory (fix http 530) (#4393)
* damn

* shouldn't newBuilder() create a new instance?

* 1 second is enough

* remove lazy

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* imports

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:31:57 +01:00
jckli
118a905cef
fix: rebrand fire scans to firecomics (#4412)
* fix: rebrand fire scans to firecomics

* fix: change gradle

* chore: add old id
2024-08-13 02:31:57 +01:00
lamaxama
c02273905e
Remove MangaTopSite (#4411) 2024-08-13 02:31:57 +01:00
lamaxama
56aa26d330
Remove ComicScans and AnshScans (#4410) 2024-08-13 02:31:57 +01:00
Chopper
2d41904b79
Remove Eflee (#4405) 2024-08-13 02:31:41 +01:00
Chopper
3030e0c74f
Add MangaHub (#4404) 2024-08-13 02:31:40 +01:00
Chopper
8c4ee90ccc
Add HyperionScans (#4401) 2024-08-13 02:31:40 +01:00
Chopper
90ba562e46
Add Magerin (#4399) 2024-08-13 02:31:40 +01:00
Chopper
329738e39d
AncientComics: Theme changed (#4397)
Theme changed
2024-08-13 02:31:40 +01:00
Vetle Ledaal
ebdcdea164
Add Manga Okusana (#4396) 2024-08-13 02:31:40 +01:00
Vetle Ledaal
aece7b3d39
Add LumosKomik (#4395)
* Add LumosKomik

* update useLoadMoreRequest/useNEwChapterEndpoint
2024-08-13 02:31:40 +01:00
Vetle Ledaal
4dac2439f8
Add PussyToons (#4394) 2024-08-13 02:31:40 +01:00
Vetle Ledaal
a60cd07d45
Remove Manga-Raw.info (unoriginal) (#4387) 2024-08-13 02:31:40 +01:00
KenjieDec
da46ebfa9a
Reaperscans: Fix Latest (#4383)
* Fix latest

* Update

* Lint Fix?
2024-08-13 02:31:40 +01:00
AwkwardPeak7
1a1566be23
Reaper Scans: fix covers and date (#4382) 2024-08-13 02:31:40 +01:00
AwkwardPeak7
7a4fa5d46a
Reaper Scans: actually change id 2024-08-13 02:31:40 +01:00
Wackery
4554a0c717
Reaper Scans: Update to new website (#4359)
* Update reaper scans to new website

* Reaper Scans: Fix requested changes

* Reaper Scans: remove unused property.

* Reaper Scans: Fix no pages found error

they broke it already???

* Reaper Scans: Fix extra images in chapters.

* Reaper Scans: Replace scraping chapter pages with api

* Reaper Scans: Fix lint

hopefully

* HeanCms: Add cdnUrl option

for sources who host thumbnails/pages outside of the api domain

* Reaper Scans: it was a multisrc this whole time

pain.

* Reaper Scans: Remove id override

* Reaper Scans: Correct version number
2024-08-13 02:31:40 +01:00
CriosChan
7e3d185dab
AnimeSama: Add support for multiple scan versions (#4156) (#4325)
* feat(AnimeSama): Support multiple version of scan (Color and colorless for exemple)

* update(AnimeSama)

* fix(AnimeSama): Use Scanlators not multiple entries

* fix(AnimeSama): No more requests in chapterListRequest only in chapterListParse
2024-08-13 02:31:40 +01:00
Chopper
5824d4adfa
Add ErosScan (#4369) 2024-08-13 02:31:40 +01:00
Yush0DAN
ea99a44cf3
ManhwaWeb: Add header fix some covers (#4373)
add header, some covers did not load
2024-08-13 02:31:40 +01:00
AwkwardPeak7
a82548860a
Comick: attempt cache busting (#4363) 2024-08-13 02:31:40 +01:00
Secozzi
20b9eff851
Madokami: use relative chapter urls (#4362)
Use relative chapter urls
2024-08-13 02:31:40 +01:00
Chopper
e8d27b655e
DemonSect: Migrate theme (#4352)
* Migrate theme

* Use fetchChapterList
2024-08-13 02:31:40 +01:00
KenjieDec
869afb9534
Fix Spyfakku (#4345) 2024-08-13 02:31:40 +01:00
KirinRaikage
311bea3a8a
Manga-Scan (FR): Update domain (#4351) 2024-08-13 02:31:40 +01:00
KenjieDec
860155e34d
ManhwaHentai.me: Fix Search (#4348)
Fix Search
2024-08-13 02:31:40 +01:00
Chopper
5ba43beecc
Hentaing(HentaiKeyfi): Rebranding (#4336)
Rebranding
2024-08-13 02:31:40 +01:00
Chopper
709769b171
Add LimitedTimeProject (#4335) 2024-08-13 02:31:40 +01:00
Secozzi
e9d0013df3
Add atsumaru (#4330)
* add atsumaru

* remove unnecessary stuff
2024-08-13 02:31:40 +01:00
Norsze
0251a55109
Remove MangaHot (#4328) 2024-08-13 02:31:40 +01:00
Norsze
530e5500da
Remove ReadManga.at (#4327) 2024-08-13 02:31:40 +01:00
Norsze
5ae345113f
Remove Immortal Updates (#4326) 2024-08-13 02:31:40 +01:00
AwkwardPeak7
fa37d45021
MangaGalaxy/Iken: don't proxy thumbnail urls (#4322) 2024-08-13 02:31:40 +01:00
Luqman
4fc5107823
Kiryuu: update domain (#4320) 2024-08-13 02:31:40 +01:00
Chopper
01f3fa0191
Add ExHentai (#4313)
* Add ExHentai

* Rename
2024-08-13 02:31:40 +01:00
AwkwardPeak7
902e0242dd
TempleScan (#4316)
* temple

* rewrite

* description & tags cleanup

* readd ratelimit

* cloudflareclient

* optimize
2024-08-13 02:31:40 +01:00
Chopper
9e8187cd1f
Add ReaperScansUnoriginal (#4315)
* Add ReaperScansUnoriginal

* Update ext name
2024-08-13 02:31:40 +01:00
Chopper
362b739c88
Add TecnoScans (#4314) 2024-08-13 02:31:40 +01:00
Vetle Ledaal
e171d141f0
Add Xmanhwa (#4312) 2024-08-13 02:31:40 +01:00
AwkwardPeak7
401e53d45a
Asura: add type to genres (#4311) 2024-08-13 02:31:40 +01:00
AwkwardPeak7
e5a68f8ba4
MangaThemesiaAlt: use slug map (#4310)
* MangaThemesiaAlt: use slug map

* selector variable

* better name
2024-08-13 02:31:40 +01:00
Chopper
d07fbd5294
TsukiMangas: Fix (#4295)
* Fix content loading for the logged-in user

* Some changes

* Remove annotation

* Remove unneeded code

* Fix indentation

* Add suppress lint

* Enable blockNetworkImage

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:31:40 +01:00
Chopper
ee3d182a5f
Remove RawMangas (#4303) 2024-08-13 02:31:40 +01:00
Chopper
40f2170702
Add PrunusScans (#4302) 2024-08-13 02:31:40 +01:00
Chopper
f0e17a6531
TeamLanhLung: Update domain (#4301)
Update domain
2024-08-13 02:31:40 +01:00
Chopper
5dbcb16307
Add AstraScans (#4298) 2024-08-13 02:31:40 +01:00
KenjieDec
ef7ff81f1b
18Kami: Fix Pages (#4292)
* Fix Pages

* Update extVersionCode

* Typo Fix
2024-08-13 02:31:40 +01:00
AwkwardPeak7
8cb6533dcd
Webnovel: revert old behaviour (#4288)
bruh moment
2024-08-13 02:31:40 +01:00
Vetle Ledaal
0e2d9bf970
ReadManga (RU): update domain (#4285) 2024-08-13 02:31:40 +01:00
Vetle Ledaal
7dbe265e52
Thunder Scans (AR): update domain (#4284) 2024-08-13 02:31:39 +01:00
Vetle Ledaal
2623bf72c5
TeamX: update domain, baseUrl config, author + status fields (#4283)
* Team X: update domain

* add status, author

* add baseUrl override
2024-08-13 02:31:39 +01:00
Vetle Ledaal
13fcfc6996
MANGARAW+: update domain (#4282)
Cover images are broken on the site, fixing this by requesting the full
res cover instead.
2024-08-13 02:31:39 +01:00
Vetle Ledaal
0bf59dd5e8
Gri Melek: update domain (#4281) 2024-08-13 02:31:39 +01:00
KenjieDec
38ef5386a6
Koharu: Fix Pages Not Loading, Removed Faulty Filters (#4280)
Fix Pages Not Loading, Removed Faulty Filters
2024-08-13 02:31:39 +01:00
AwkwardPeak7
4eacdd057e
LuaScans: update domain (#4278) 2024-08-13 02:31:39 +01:00
KenjieDec
a5e5ccceec
Add 18Kami (#4262)
* Add 18Kami

* Apply suggestions

- Apply vetleledaal's suggestions

* Apply suggestion

- Apply bapeey's suggestion

Co-authored-by: bapeey <90949336+bapeey@users.noreply.github.com>

* Lint Fix

---------

Co-authored-by: bapeey <90949336+bapeey@users.noreply.github.com>
2024-08-13 02:31:39 +01:00
kana-shii
10ddb3734f
mangago add scanlator / remove suffix from titles (#4242)
* fix for 2 issues on mangago

* fix

* fix

forgot to remove the comment from when I was testing it out

* fix

* Update src/en/mangago/src/eu/kanade/tachiyomi/extension/en/mangago/Mangago.kt

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* Update src/en/mangago/src/eu/kanade/tachiyomi/extension/en/mangago/Mangago.kt

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* fix

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:31:39 +01:00
AwkwardPeak7
3e6c9170ab
webnovel: fix relative date parsing (#4275)
webnovel: adjust date parsing
2024-08-13 02:31:39 +01:00
bapeey
4d291d571d
InfernalVoidScans: Fix cloudflare (#4273)
fix cloudflare
2024-08-13 02:31:39 +01:00
bapeey
303f6d7737
AsuraScans: Update chapter list selector (#4268)
fix
2024-08-13 02:31:39 +01:00
KenjieDec
88fffed4f9
Koharu: Fix Pages (#4256)
* Fix Pages

* LF
2024-08-13 02:31:39 +01:00
KenjieDec
2f9ebadb08
MangaGeko: Fix Filters (#4221)
* Fix Filters

* Apply suggestion1

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* Apply suggestion2

* Apply Suggetions

- Apply AwkwardPeak7's suggestions

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
2024-08-13 02:31:39 +01:00
468 changed files with 3745 additions and 2902 deletions

View File

@ -2,4 +2,4 @@ plugins {
id("lib-multisrc")
}
baseVersionCode = 1
baseVersionCode = 2

View File

@ -291,7 +291,7 @@ abstract class BlogTruyen(
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("#content > img").forEachIndexed { i, e ->
document.select(".content > img, #content > img").forEachIndexed { i, e ->
pages.add(Page(i, imageUrl = e.absUrl("src")))
}

View File

@ -7,7 +7,7 @@ import android.os.Bundle
import android.util.Log
import kotlin.system.exitProcess
/**
* Springboard that accepts https://readmanga.live/xxx intents and redirects them to
* Springboard that accepts https://1.readmanga.io/xxx intents and redirects them to
* the main tachiyomi process. The idea is to not install the intent filter unless
* you have this extension installed, but still let the main tachiyomi app control
* things.

View File

@ -2,7 +2,7 @@ plugins {
id("lib-multisrc")
}
baseVersionCode = 25
baseVersionCode = 27
dependencies {
api(project(":lib:i18n"))

View File

@ -72,6 +72,8 @@ abstract class HeanCms(
protected open val coverPath: String = ""
protected open val cdnUrl = apiUrl
protected open val mangaSubDirectory: String = "series"
protected open val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US)
@ -206,7 +208,7 @@ abstract class HeanCms(
val result = json.parseAs<HeanCmsQuerySearchDto>()
val mangaList = result.data.map {
it.toSManga(apiUrl, coverPath, mangaSubDirectory)
it.toSManga(cdnUrl, coverPath, mangaSubDirectory)
}
return MangasPage(mangaList, result.meta?.hasNextPage() ?: false)
@ -242,7 +244,7 @@ abstract class HeanCms(
val seriesResult = result.getOrNull()
?: throw Exception(intl.format("url_changed_error", name, name))
val seriesDetails = seriesResult.toSManga(apiUrl, coverPath, mangaSubDirectory)
val seriesDetails = seriesResult.toSManga(cdnUrl, coverPath, mangaSubDirectory)
return seriesDetails.apply {
status = status.takeUnless { it == SManga.UNKNOWN }
@ -345,8 +347,8 @@ abstract class HeanCms(
}
}
private fun String.toAbsoluteUrl(): String {
return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this"
protected open fun String.toAbsoluteUrl(): String {
return if (startsWith("https://") || startsWith("http://")) this else "$cdnUrl/$coverPath$this"
}
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)

View File

@ -63,7 +63,7 @@ class HeanCmsSeriesDto(
) {
fun toSManga(
apiUrl: String,
cdnUrl: String,
coverPath: String,
mangaSubDirectory: String,
): SManga = SManga.create().apply {
@ -79,7 +79,7 @@ class HeanCmsSeriesDto(
.sortedBy(HeanCmsTagDto::name)
.joinToString { it.name }
thumbnail_url = thumbnail.ifEmpty { null }
?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
?.toAbsoluteThumbnailUrl(cdnUrl, coverPath)
status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN
url = "/$mangaSubDirectory/$slug#$id"
}
@ -103,6 +103,7 @@ class HeanCmsChapterPayloadDto(
class HeanCmsChapterDto(
private val id: Int,
@SerialName("chapter_name") private val name: String,
@SerialName("chapter_title") private val title: String? = null,
@SerialName("chapter_slug") private val slug: String,
@SerialName("created_at") private val createdAt: String,
val price: Int? = null,
@ -114,6 +115,10 @@ class HeanCmsChapterDto(
): SChapter = SChapter.create().apply {
name = this@HeanCmsChapterDto.name.trim()
if (title != null) {
name += " - ${title.trim()}"
}
if (price != 0) {
name += " \uD83D\uDD12"
}
@ -161,8 +166,8 @@ class HeanCmsGenreDto(
val name: String,
)
private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): String {
return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this"
private fun String.toAbsoluteThumbnailUrl(cdnUrl: String, coverPath: String): String {
return if (startsWith("https://") || startsWith("http://")) this else "$cdnUrl/$coverPath$this"
}
fun String.toStatus(): Int = when (this) {

View File

@ -2,4 +2,4 @@ plugins {
id("lib-multisrc")
}
baseVersionCode = 1
baseVersionCode = 3

View File

@ -4,7 +4,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonPrimitive
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.jsoup.Jsoup
import java.text.ParseException
import java.text.SimpleDateFormat
@ -31,14 +30,10 @@ class Manga(
private val seriesStatus: String? = null,
val genres: List<Genre> = emptyList(),
) {
fun toSManga(baseUrl: String) = SManga.create().apply {
fun toSManga() = SManga.create().apply {
url = "$slug#$id"
title = postTitle
thumbnail_url = "$baseUrl/_next/image".toHttpUrl().newBuilder().apply {
addQueryParameter("url", featuredImage)
addQueryParameter("w", "828")
addQueryParameter("q", "75")
}.toString()
thumbnail_url = featuredImage
author = this@Manga.author?.takeUnless { it.isEmpty() }
artist = this@Manga.artist?.takeUnless { it.isEmpty() }
description = buildString {

View File

@ -14,6 +14,7 @@ import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.injectLazy
abstract class Iken(
@ -43,7 +44,7 @@ abstract class Iken(
it.genres.map { genre ->
genre.name to genre.id.toString()
}
}
}.distinct()
}
.associateBy { it.slug }
}
@ -56,7 +57,7 @@ abstract class Iken(
.map { it.absUrl("href").substringAfterLast("/series/") }
val entries = slugs.mapNotNull {
titleCache[it]?.toSManga(baseUrl)
titleCache[it]?.toSManga()
}
return MangasPage(entries, false)
@ -84,7 +85,7 @@ abstract class Iken(
val entries = data.posts
.filterNot { it.isNovel }
.map { it.toSManga(baseUrl) }
.map { it.toSManga() }
val hasNextPage = data.totalCount > (page * perPage)
@ -98,32 +99,28 @@ abstract class Iken(
Filter.Header("Open popular mangas if genre filter is empty"),
)
override fun mangaDetailsRequest(manga: SManga): Request {
val id = manga.url.substringAfterLast("#")
val url = "$baseUrl/api/chapters?postId=$id&skip=0&take=1000&order=desc&userid="
return GET(url, headers)
}
override fun getMangaUrl(manga: SManga): String {
val slug = manga.url.substringBeforeLast("#")
return "$baseUrl/series/$slug"
}
override fun mangaDetailsParse(response: Response): SManga {
val data = response.parseAs<Post<Manga>>()
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val slug = manga.url.substringBeforeLast("#")
val update = titleCache[slug]?.toSManga() ?: manga
assert(!data.post.isNovel) { "Novels are unsupported" }
// genres are only returned in search call
// and not when fetching details
return data.post.toSManga(baseUrl).apply {
genre = titleCache[data.post.slug]?.getGenres()
}
return Observable.just(update)
}
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
override fun mangaDetailsParse(response: Response) =
throw UnsupportedOperationException()
override fun chapterListRequest(manga: SManga): Request {
val id = manga.url.substringAfterLast("#")
val url = "$baseUrl/api/chapters?postId=$id&skip=0&take=1000&order=desc&userid="
return GET(url, headers)
}
override fun chapterListParse(response: Response): List<SChapter> {
val data = response.parseAs<Post<ChapterListResponse>>()
@ -138,7 +135,7 @@ abstract class Iken(
override fun pageListParse(response: Response): List<Page> {
val document = response.asJsoup()
return document.select("main section > img").mapIndexed { idx, img ->
return document.select("main section img").mapIndexed { idx, img ->
Page(idx, imageUrl = img.absUrl("src"))
}
}

View File

@ -1,5 +0,0 @@
plugins {
id("lib-multisrc")
}
baseVersionCode = 6

View File

@ -5,7 +5,6 @@ import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
@ -32,8 +31,18 @@ abstract class MangaThemesiaAlt(
private val randomUrlPrefKey: String = "pref_auto_random_url",
) : MangaThemesia(name, baseUrl, lang, mangaUrlDirectory, dateFormat), ConfigurableSource {
protected open val listUrl = "$mangaUrlDirectory/list-mode/"
protected open val listSelector = "div#content div.soralist ul li a.series"
protected val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000).also {
if (it.contains("__random_part_cache")) {
it.edit().remove("__random_part_cache").apply()
}
if (it.contains("titles_without_random_part")) {
it.edit().remove("titles_without_random_part").apply()
}
}
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
@ -47,183 +56,11 @@ abstract class MangaThemesiaAlt(
private fun getRandomUrlPref() = preferences.getBoolean(randomUrlPrefKey, true)
private var randomPartCache = SuspendLazy(::getUpdatedRandomPart) { preferences.randomPartCache = it }
// cache in preference for webview urls
private var SharedPreferences.randomPartCache: String
get() = getString("__random_part_cache", "")!!
set(newValue) = edit().putString("__random_part_cache", newValue).apply()
// some new titles don't have random part
// se we save their slug and when they
// finally add it, we remove the slug in the interceptor
private var SharedPreferences.titlesWithoutRandomPart: MutableSet<String>
get() {
val value = getString("titles_without_random_part", null)
?: return mutableSetOf()
return json.decodeFromString(value)
}
set(newValue) {
val encodedValue = json.encodeToString(newValue)
edit().putString("titles_without_random_part", encodedValue).apply()
}
protected open fun getRandomPartFromUrl(url: String): String {
val slug = url
.removeSuffix("/")
.substringAfterLast("/")
return slugRegex.find(slug)?.groupValues?.get(1) ?: ""
}
protected open fun getRandomPartFromResponse(response: Response): String {
return response.asJsoup()
.selectFirst(searchMangaSelector())!!
.select("a").attr("href")
.let(::getRandomPartFromUrl)
}
protected suspend fun getUpdatedRandomPart(): String =
client.newCall(GET("$baseUrl$mangaUrlDirectory/", headers))
.await()
.use(::getRandomPartFromResponse)
override fun searchMangaParse(response: Response): MangasPage {
val mp = super.searchMangaParse(response)
if (!getRandomUrlPref()) return mp
// extract random part during browsing to avoid extra call
mp.mangas.firstOrNull()?.run {
val randomPart = getRandomPartFromUrl(url)
if (randomPart.isNotEmpty()) {
randomPartCache.set(randomPart)
}
}
val mangas = mp.mangas.toPermanentMangaUrls()
return MangasPage(mangas, mp.hasNextPage)
}
protected fun List<SManga>.toPermanentMangaUrls(): List<SManga> {
// some absolutely new titles don't have the random part yet
// save them so we know where to not apply it
val foundTitlesWithoutRandomPart = mutableSetOf<String>()
for (i in indices) {
val slug = this[i].url
.removeSuffix("/")
.substringAfterLast("/")
if (slugRegex.find(slug)?.groupValues?.get(1) == null) {
foundTitlesWithoutRandomPart.add(slug)
}
val permaSlug = slug
.replaceFirst(slugRegex, "")
this[i].url = "$mangaUrlDirectory/$permaSlug/"
}
if (foundTitlesWithoutRandomPart.isNotEmpty()) {
foundTitlesWithoutRandomPart.addAll(preferences.titlesWithoutRandomPart)
preferences.titlesWithoutRandomPart = foundTitlesWithoutRandomPart
}
return this
}
protected open val slugRegex = Regex("""^(\d+-)""")
override val client = super.client.newBuilder()
.addInterceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)
if (request.url.fragment != "titlesWithoutRandomPart") {
return@addInterceptor response
}
if (!response.isSuccessful && response.code == 404) {
response.close()
val slug = request.url.toString()
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
preferences.titlesWithoutRandomPart.run {
remove(slug)
preferences.titlesWithoutRandomPart = this
}
val randomPart = randomPartCache.blockingGet()
val newRequest = request.newBuilder()
.url("$baseUrl$mangaUrlDirectory/$randomPart$slug/")
.build()
return@addInterceptor chain.proceed(newRequest)
}
return@addInterceptor response
}
.build()
override fun mangaDetailsRequest(manga: SManga): Request {
if (!getRandomUrlPref()) return super.mangaDetailsRequest(manga)
val slug = manga.url
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
.replaceFirst(slugRegex, "")
if (preferences.titlesWithoutRandomPart.contains(slug)) {
return GET("$baseUrl${manga.url}#titlesWithoutRandomPart")
}
val randomPart = randomPartCache.blockingGet()
return GET("$baseUrl$mangaUrlDirectory/$randomPart$slug/", headers)
}
override fun getMangaUrl(manga: SManga): String {
if (!getRandomUrlPref()) return super.getMangaUrl(manga)
val slug = manga.url
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
.replaceFirst(slugRegex, "")
if (preferences.titlesWithoutRandomPart.contains(slug)) {
return "$baseUrl${manga.url}"
}
val randomPart = randomPartCache.peek() ?: preferences.randomPartCache
return "$baseUrl$mangaUrlDirectory/$randomPart$slug/"
}
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
}
internal class SuspendLazy(
private val initializer: suspend () -> String,
private val saveCache: (String) -> Unit,
) {
private val mutex = Mutex()
private var cachedValue: SoftReference<String>? = null
private var cachedValue: SoftReference<Map<String, String>>? = null
private var fetchTime = 0L
suspend fun get(): String {
private suspend fun getUrlMapInternal(): Map<String, String> {
if (fetchTime + 3600000 < System.currentTimeMillis()) {
// reset cache
cachedValue = null
@ -238,22 +75,104 @@ internal class SuspendLazy(
return it
}
initializer().also { set(it) }
fetchUrlMap().also {
cachedValue = SoftReference(it)
fetchTime = System.currentTimeMillis()
preferences.urlMapCache = it
}
}
}
fun set(newVal: String) {
cachedValue = SoftReference(newVal)
fetchTime = System.currentTimeMillis()
protected open fun fetchUrlMap(): Map<String, String> {
client.newCall(GET("$baseUrl$listUrl", headers)).execute().use { response ->
val document = response.asJsoup()
saveCache(newVal)
return document.select(listSelector).associate {
val url = it.absUrl("href")
val slug = url.removeSuffix("/")
.substringAfterLast("/")
val permaSlug = slug
.replaceFirst(slugRegex, "")
permaSlug to slug
}
}
}
fun peek(): String? {
return cachedValue?.get()
protected fun getUrlMap(cached: Boolean = false): Map<String, String> {
return if (cached && cachedValue == null) {
preferences.urlMapCache
} else {
runBlocking { getUrlMapInternal() }
}
}
fun blockingGet(): String {
return runBlocking { get() }
// cache in preference for webview urls
private var SharedPreferences.urlMapCache: Map<String, String>
get(): Map<String, String> {
val value = getString("url_map_cache", "{}")!!
return try {
json.decodeFromString(value)
} catch (_: Exception) {
emptyMap()
}
}
set(newMap) = edit().putString("url_map_cache", json.encodeToString(newMap)).apply()
override fun searchMangaParse(response: Response): MangasPage {
val mp = super.searchMangaParse(response)
if (!getRandomUrlPref()) return mp
val mangas = mp.mangas.toPermanentMangaUrls()
return MangasPage(mangas, mp.hasNextPage)
}
protected fun List<SManga>.toPermanentMangaUrls(): List<SManga> {
return onEach {
val slug = it.url
.removeSuffix("/")
.substringAfterLast("/")
val permaSlug = slug
.replaceFirst(slugRegex, "")
it.url = "$mangaUrlDirectory/$permaSlug/"
}
}
protected open val slugRegex = Regex("""^(\d+-)""")
override fun mangaDetailsRequest(manga: SManga): Request {
if (!getRandomUrlPref()) return super.mangaDetailsRequest(manga)
val slug = manga.url
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
.replaceFirst(slugRegex, "")
val randomSlug = getUrlMap()[slug] ?: slug
return GET("$baseUrl$mangaUrlDirectory/$randomSlug/", headers)
}
override fun getMangaUrl(manga: SManga): String {
if (!getRandomUrlPref()) return super.getMangaUrl(manga)
val slug = manga.url
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
.replaceFirst(slugRegex, "")
val randomSlug = getUrlMap(true)[slug] ?: slug
return "$baseUrl$mangaUrlDirectory/$randomSlug/"
}
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
}

View File

@ -1,7 +1,7 @@
ext {
extName = 'Bato.to'
extClass = '.BatoToFactory'
extVersionCode = 36
extVersionCode = 37
isNsfw = true
}

View File

@ -384,11 +384,14 @@ open class BatoTo(
val chapter = SChapter.create()
val urlElement = element.select("a.chapt")
val group = element.select("div.extra > a:not(.ps-3)").text()
val user = element.select("div.extra > a.ps-3").text()
val time = element.select("div.extra > i.ps-3").text()
chapter.setUrlWithoutDomain(urlElement.attr("href"))
chapter.name = urlElement.text()
if (group != "") {
chapter.scanlator = group
chapter.scanlator = when {
group.isNotBlank() -> group
user.isNotBlank() -> user
else -> "Unknown"
}
if (time != "") {
chapter.date_upload = parseChapterDate(time)

View File

@ -1,7 +1,7 @@
ext {
extName = 'Comick'
extClass = '.ComickFactory'
extVersionCode = 46
extVersionCode = 47
isNsfw = true
}

View File

@ -463,7 +463,16 @@ abstract class Comick(
override fun pageListParse(response: Response): List<Page> {
val result = response.parseAs<PageList>()
return result.chapter.images.mapIndexedNotNull { index, data ->
val images = result.chapter.images.ifEmpty {
// cache busting
val url = response.request.url.newBuilder()
.addQueryParameter("_", System.currentTimeMillis().toString())
.build()
client.newCall(GET(url, headers)).execute()
.parseAs<PageList>().chapter.images
}
return images.mapIndexedNotNull { index, data ->
if (data.url == null) null else Page(index = index, imageUrl = data.url)
}
}

View File

@ -1,6 +1,6 @@
ext {
extName = 'MangaHot'
extClass = '.MangaHot'
extName = 'FoamGirl'
extClass = '.FoamGirl'
extVersionCode = 1
isNsfw = true
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,127 @@
package eu.kanade.tachiyomi.extension.all.foamgirl
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
class FoamGirl() : ParsedHttpSource() {
override val baseUrl = "https://foamgirl.net"
override val lang = "all"
override val name = "FoamGirl"
override val supportsLatest = false
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
// Popular
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
thumbnail_url = element.select("img").attr("data-original")
title = element.select("a.meta-title").text()
setUrlWithoutDomain(element.select("a").attr("href"))
initialized = true
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return Observable.just(manga)
}
override fun mangaDetailsParse(document: Document): SManga {
throw UnsupportedOperationException()
}
override fun popularMangaNextPageSelector() = "a.next"
override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/page/$page", headers)
}
override fun popularMangaSelector() = ".update_area .i_list"
// Search
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
return GET(
baseUrl.toHttpUrl().newBuilder().apply {
addPathSegment("page")
addPathSegment("$page")
addQueryParameter("post_type", "post")
addQueryParameter("s", query)
}.build(),
headers,
)
}
override fun searchMangaSelector() = popularMangaSelector()
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
val imageCount = document.select(".post_title_topimg").text().substringAfter("(").substringBefore("P").toInt()
val imageUrl = document.select(".imageclick-imgbox").attr("href").toHttpUrl()
val imagePrefix = imageUrl.pathSegments.last().substringBefore(".").toLong() / 10
for (i in 0 until imageCount) {
pages.add(
Page(
i,
imageUrl = imageUrl.newBuilder().apply {
removePathSegment(imageUrl.pathSize - 1)
addPathSegment("${imagePrefix}${i + 2}.jpg")
}.build().toString(),
),
)
}
return pages
}
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.select("link[rel=canonical]").attr("abs:href"))
chapter_number = 0F
name = "GALLERY"
date_upload = getDate(element.select("span.image-info-time").text().substring(1))
}
override fun chapterListSelector() = "html"
// Pages
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SManga {
throw UnsupportedOperationException()
}
override fun latestUpdatesNextPageSelector(): String? {
throw UnsupportedOperationException()
}
override fun latestUpdatesRequest(page: Int): Request {
throw UnsupportedOperationException()
}
override fun latestUpdatesSelector(): String {
throw UnsupportedOperationException()
}
private fun getDate(str: String): Long {
return try {
DATE_FORMAT.parse(str)?.time ?: 0L
} catch (e: ParseException) {
0L
}
}
companion object {
private val DATE_FORMAT by lazy {
SimpleDateFormat("yyyy.M.d", Locale.ENGLISH)
}
}
}

View File

@ -1,7 +1,7 @@
ext {
extName = 'Hentai Cosplay'
extClass = '.HentaiCosplay'
extVersionCode = 3
extVersionCode = 4
isNsfw = true
}

View File

@ -24,7 +24,7 @@ class HentaiCosplay : HttpSource() {
override val name = "Hentai Cosplay"
override val baseUrl = "https://hentai-cosplays.com"
override val baseUrl = "https://hentai-cosplay-xxx.com"
override val lang = "all"

View File

@ -1,15 +0,0 @@
package eu.kanade.tachiyomi.extension.all.mangatopsite
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class MangaTopSite : Madara(
"MangaTop.site",
"https://mangatop.site",
"all",
dateFormat = SimpleDateFormat("d MMM yyyy", Locale.ENGLISH),
) {
override val useNewChapterEndpoint = false
override val chapterUrlSuffix = ""
}

View File

@ -1,7 +1,7 @@
ext {
extName = 'NHentai'
extClass = '.NHFactory'
extVersionCode = 40
extVersionCode = 41
isNsfw = true
}

View File

@ -220,7 +220,7 @@ open class NHentai(
thumbnail_url = document.select("#cover > a > img").attr("data-src")
status = SManga.COMPLETED
artist = getArtists(document)
author = artist
author = getGroups(document)
// Some people want these additional details in description
description = "Full English and Japanese titles:\n"
.plus("$fullTitle\n")

View File

@ -2,8 +2,8 @@ ext {
extName = 'Thunder Scans'
extClass = '.ThunderScansFactory'
themePkg = 'mangathemesia'
baseUrl = 'https://en-thunderepic.com'
overrideVersionCode = 2
baseUrl = 'https://en-thunderscans.com'
overrideVersionCode = 4
}
apply from: "$rootDir/common.gradle"

View File

@ -14,14 +14,14 @@ class ThunderScansFactory : SourceFactory {
class ThunderScansAR : MangaThemesiaAlt(
"Thunder Scans",
"https://ar-thunderepic.com",
"https://thunderscans.com",
"ar",
dateFormat = SimpleDateFormat("MMM d, yyy", Locale("ar")),
)
class ThunderScansEN : MangaThemesiaAlt(
"Thunder Scans",
"https://en-thunderepic.com",
"https://en-thunderscans.com",
"en",
mangaUrlDirectory = "/comics",
)

View File

@ -0,0 +1,10 @@
ext {
extName = 'MangaHub'
extClass = '.MangaHub'
themePkg = 'zeistmanga'
baseUrl = 'https://www.mangahub.link'
overrideVersionCode = 0
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,23 @@
package eu.kanade.tachiyomi.extension.ar.mangahub
import eu.kanade.tachiyomi.multisrc.zeistmanga.ZeistManga
import eu.kanade.tachiyomi.network.interceptor.rateLimit
class MangaHub : ZeistManga(
"MangaHub",
"https://www.mangahub.link",
"ar",
) {
override val client = super.client.newBuilder()
.rateLimit(3)
.build()
override val popularMangaSelector = "div#PopularPosts2 article"
override val popularMangaSelectorTitle = "h3"
override val popularMangaSelectorUrl = "a"
override val mangaDetailsSelector = ".grid.gap-5.gta-series"
override val mangaDetailsSelectorGenres = "dt:contains(التصنيف) + dd a[rel=tag]"
override val pageListSelector = "article#reader .separator, div.image-container"
}

View File

@ -2,8 +2,8 @@ ext {
extName = 'MangaNoon'
extClass = '.MangaNoon'
themePkg = 'mangathemesia'
baseUrl = 'https://manjanoon.co'
overrideVersionCode = 3
baseUrl = 'https://noonscan.net'
overrideVersionCode = 4
isNsfw = false
}

View File

@ -7,7 +7,7 @@ import java.util.Calendar
class MangaNoon : MangaThemesia(
"مانجا نون",
"https://manjanoon.co",
"https://noonscan.net",
"ar",
) {

View File

@ -3,7 +3,7 @@ ext {
extClass = '.MangaPro'
themePkg = 'mangathemesia'
baseUrl = 'https://promanga.pro'
overrideVersionCode = 2
overrideVersionCode = 3
}
apply from: "$rootDir/common.gradle"

View File

@ -1,6 +1,9 @@
package eu.kanade.tachiyomi.extension.ar.mangapro
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.source.model.Page
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.jsoup.nodes.Document
import java.text.SimpleDateFormat
import java.util.Locale
@ -11,4 +14,30 @@ class MangaPro : MangaThemesia(
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("ar")),
) {
override val versionId = 3
override fun pageListParse(document: Document): List<Page> {
return super.pageListParse(document).onEach {
val httpUrl = it.imageUrl!!.toHttpUrl()
if (wpImgRegex.containsMatchIn(httpUrl.host)) {
it.imageUrl = StringBuilder().apply {
val ssl = httpUrl.queryParameter("ssl")
when (ssl) {
null -> append(httpUrl.scheme)
"0" -> append("http")
else -> append("https")
}
append("://")
append(httpUrl.pathSegments.joinToString("/"))
val search = httpUrl.queryParameter("q")
if (search != null) {
append("?q=")
append(search)
}
}.toString()
}
}
}
}
private val wpImgRegex = Regex("""i\d+\.wp\.com""")

View File

@ -2,8 +2,8 @@ ext {
extName = 'MangaSwat'
extClass = '.MangaSwat'
themePkg = 'mangathemesia'
baseUrl = 'https://maxlevelteam.com'
overrideVersionCode = 20
baseUrl = 'https://tatwt.com'
overrideVersionCode = 21
}
apply from: "$rootDir/common.gradle"

View File

@ -24,7 +24,7 @@ import java.util.Locale
class MangaSwat :
MangaThemesia(
"MangaSwat",
"https://maxlevelteam.com",
"https://tatwt.com",
"ar",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("ar")),
),

View File

@ -2,8 +2,8 @@ ext {
extName = 'Rocks Manga'
extClass = '.RocksManga'
themePkg = 'madara'
baseUrl = 'https://rocks-manga.com'
overrideVersionCode = 0
baseUrl = 'https://rocksmanga.com'
overrideVersionCode = 1
isNsfw = false
}

View File

@ -2,39 +2,65 @@ package eu.kanade.tachiyomi.extension.ar.rocksmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class RocksManga : Madara(
"Rocks Manga",
"https://rocks-manga.com",
"https://rocksmanga.com",
"ar",
dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("ar")),
) {
override fun popularMangaSelector() = ".shido-manga"
override val popularMangaUrlSelector = "a.s-manga-title"
override val mangaDetailsSelectorTitle = ".title"
override val mangaDetailsSelectorAuthor = ".heading:contains(المؤلف:) + .content a"
override val mangaDetailsSelectorArtist = ".heading:contains(الرسام:) + .content a"
override fun popularMangaSelector() = "div.page-content-listing > .manga"
override val popularMangaUrlSelector = "div.manga-poster a"
override fun popularMangaFromElement(element: Element): SManga {
return super.popularMangaFromElement(element).apply {
title = element.selectFirst(popularMangaUrlSelector)!!.attr("title")
}
}
override fun searchMangaSelector() = "#manga-search-results .manga-item"
override fun searchMangaFromElement(element: Element): SManga {
val manga = SManga.create()
with(element) {
selectFirst("a.cover")!!.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
manga.title = it.attr("title")
}
selectFirst("img")?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
override val mangaDetailsSelectorTitle = ".manga-title"
override val mangaDetailsSelectorAuthor = "div.meta span:contains(المؤلف:) + span a"
override val mangaDetailsSelectorArtist = "div.meta span:contains(الرسام:) + span a"
override val mangaDetailsSelectorStatus = ".status"
override val mangaDetailsSelectorDescription = ".story"
override val mangaDetailsSelectorThumbnail = ".profile-manga .poster img"
override val mangaDetailsSelectorGenre = ".heading:contains(التصنيف:) + .content a"
override val altNameSelector = ".other-name"
override fun chapterListSelector() = "#chapter-list li.chapter-item"
override fun chapterDateSelector() = ".ch-post-time"
override val pageListParseSelector = ".reading-content img"
override val mangaDetailsSelectorDescription = "div.description"
override val mangaDetailsSelectorThumbnail = ".manga-poster img"
override val mangaDetailsSelectorGenre = "div.meta span:contains(التصنيف:) + span a"
override val altNameSelector = "div.alternative"
override fun chapterListSelector() = ".chapters-list li.chapter-item"
override fun chapterDateSelector() = ".chapter-release-date"
override val pageListParseSelector = ".chapter-reading-page img"
override val useLoadMoreRequest = LoadMoreStrategy.Never
override val useNewChapterEndpoint = false
override val fetchGenres = false
override val filterNonMangaItems = false
override fun chapterFromElement(element: Element): SChapter {
val chapter = super.chapterFromElement(element)
chapter.name = element.selectFirst(".detail-ch")!!.text()
chapter.name = element.selectFirst(".num")!!.text()
return chapter
}
}

View File

@ -1,7 +1,7 @@
ext {
extName = 'Team X'
extClass = '.TeamX'
extVersionCode = 17
extVersionCode = 18
isNsfw = false
}

View File

@ -1,7 +1,12 @@
package eu.kanade.tachiyomi.extension.ar.teamx
import android.app.Application
import android.content.SharedPreferences
import android.widget.Toast
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
@ -14,15 +19,19 @@ import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class TeamX : ParsedHttpSource() {
class TeamX : ParsedHttpSource(), ConfigurableSource {
override val name = "Team X"
override val baseUrl = "https://teamxnovel.com"
private val defaultBaseUrl = "https://teamoney.site"
override val baseUrl by lazy { getPrefBaseUrl() }
override val lang = "ar"
@ -34,6 +43,10 @@ class TeamX : ParsedHttpSource() {
.rateLimit(10, 1, TimeUnit.SECONDS)
.build()
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// Popular
override fun popularMangaRequest(page: Int): Request {
@ -130,6 +143,14 @@ class TeamX : ParsedHttpSource() {
}
genre = document.select("div.review-author-info a").joinToString { it.text() }
thumbnail_url = document.select("div.text-right img").first()!!.absUrl("src")
status = document
.selectFirst(".full-list-info > small:first-child:contains(الحالة) + small")
?.text()
.toStatus()
author = document
.selectFirst(".full-list-info > small:first-child:contains(الرسام) + small")
?.text()
?.takeIf { it != "غير معروف" }
}
}
@ -187,6 +208,14 @@ class TeamX : ParsedHttpSource() {
}.getOrNull() ?: 0
}
private fun String?.toStatus() = when (this) {
"مستمرة" -> SManga.ONGOING
"قادم قريبًا" -> SManga.ONGOING // "coming soon"
"مكتمل" -> SManga.COMPLETED
"متوقف" -> SManga.ON_HIATUS
else -> SManga.UNKNOWN
}
// Pages
override fun pageListParse(document: Document): List<Page> {
@ -196,4 +225,41 @@ class TeamX : ParsedHttpSource() {
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
companion object {
private const val RESTART_APP = ".لتطبيق الإعدادات الجديدة أعد تشغيل التطبيق"
private const val BASE_URL_PREF_TITLE = "تعديل الرابط"
private const val BASE_URL_PREF = "overrideBaseUrl"
private const val BASE_URL_PREF_SUMMARY = ".للاستخدام المؤقت. تحديث التطبيق سيؤدي الى حذف الإعدادات"
private const val DEFAULT_BASE_URL_PREF = "defaultBaseUrl"
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val baseUrlPref = androidx.preference.EditTextPreference(screen.context).apply {
key = BASE_URL_PREF
title = BASE_URL_PREF_TITLE
summary = BASE_URL_PREF_SUMMARY
this.setDefaultValue(defaultBaseUrl)
dialogTitle = BASE_URL_PREF_TITLE
dialogMessage = "Default: $defaultBaseUrl"
setOnPreferenceChangeListener { _, _ ->
Toast.makeText(screen.context, RESTART_APP, Toast.LENGTH_LONG).show()
true
}
}
screen.addPreference(baseUrlPref)
}
private fun getPrefBaseUrl(): String = preferences.getString(BASE_URL_PREF, defaultBaseUrl)!!
init {
preferences.getString(DEFAULT_BASE_URL_PREF, null).let { prefDefaultBaseUrl ->
if (prefDefaultBaseUrl != defaultBaseUrl) {
preferences.edit()
.putString(BASE_URL_PREF, defaultBaseUrl)
.putString(DEFAULT_BASE_URL_PREF, defaultBaseUrl)
.apply()
}
}
}
}

View File

@ -0,0 +1,9 @@
ext {
extName = 'Altay Scans'
extClass = '.AltayScans'
themePkg = 'mangathemesia'
baseUrl = 'https://altayscans.com'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.extension.en.altayscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
class AltayScans : MangaThemesia(
"Altay Scans",
"https://altayscans.com",
"en",
) {
override val client = super.client.newBuilder()
.rateLimit(3)
.build()
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Ansh Scans'
extClass = '.AnshScans'
themePkg = 'madara'
baseUrl = 'https://anshscans.org'
overrideVersionCode = 1
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,11 +0,0 @@
package eu.kanade.tachiyomi.extension.en.anshscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
class AnshScans : Madara("Ansh Scans", "https://anshscans.org", "en") {
override val useNewChapterEndpoint = true
override val mangaDetailsSelectorStatus = "div.summary-heading:contains(Status) + div.summary-content"
override val mangaSubString = "comic"
}

View File

@ -0,0 +1,9 @@
ext {
extName = 'Astra Scans'
extClass = '.AstraScans'
themePkg = 'mangathemesia'
baseUrl = 'https://astrascans.org'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,15 @@
package eu.kanade.tachiyomi.extension.en.astrascans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
class AstraScans : MangaThemesia(
"Astra Scans",
"https://astrascans.org",
"en",
"/series",
) {
override val client = super.client.newBuilder()
.rateLimit(3)
.build()
}

View File

@ -1,7 +1,7 @@
ext {
extName = 'Asura Scans'
extClass = '.AsuraScans'
extVersionCode = 36
extVersionCode = 39
}
apply from: "$rootDir/common.gradle"

View File

@ -205,7 +205,12 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
description = document.selectFirst("span.font-medium.text-sm")?.text()
author = document.selectFirst("div.grid > div:has(h3:eq(0):containsOwn(Author)) > h3:eq(1)")?.ownText()
artist = document.selectFirst("div.grid > div:has(h3:eq(0):containsOwn(Artist)) > h3:eq(1)")?.ownText()
genre = document.select("div[class^=space] > div.flex > button.text-white").joinToString { it.ownText() }
genre = buildList {
document.selectFirst("div.flex:has(h3:eq(0):containsOwn(type)) > h3:eq(1)")
?.ownText()?.let(::add)
document.select("div[class^=space] > div.flex > button.text-white")
.forEach { add(it.ownText()) }
}.joinToString()
status = parseStatus(document.selectFirst("div.flex:has(h3:eq(0):containsOwn(Status)) > h3:eq(1)")?.ownText())
}
@ -229,10 +234,10 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
override fun chapterListSelector() = "div.scrollbar-thumb-themecolor > a.block"
override fun chapterListSelector() = "div.scrollbar-thumb-themecolor > div.group"
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.attr("abs:href").toPermSlugIfNeeded())
setUrlWithoutDomain(element.selectFirst("a")!!.attr("abs:href").toPermSlugIfNeeded())
name = element.selectFirst("h3:eq(0)")!!.text()
date_upload = try {
val text = element.selectFirst("h3:eq(1)")!!.ownText()
@ -253,7 +258,7 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
}
override fun pageListParse(document: Document): List<Page> {
return document.select("div > img[alt=chapter]").mapIndexed { i, element ->
return document.select("div > img[alt*=chapter]").mapIndexed { i, element ->
Page(i, imageUrl = element.attr("abs:src"))
}
}

View File

@ -1,6 +1,6 @@
ext {
extName = 'AgiToon'
extClass = '.AgiToon'
extName = 'Atsumaru'
extClass = '.Atsumaru'
extVersionCode = 1
isNsfw = true
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,156 @@
package eu.kanade.tachiyomi.extension.en.atsumaru
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class Atsumaru : HttpSource() {
override val name = "Atsumaru"
override val baseUrl = "https://atsu.moe"
private val apiUrl = "$baseUrl/api/v1"
override val lang = "en"
override val supportsLatest = true
override val client = network.cloudflareClient.newBuilder()
.rateLimit(2)
.build()
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
private fun apiHeadersBuilder() = headersBuilder().apply {
add("Accept", "*/*")
add("Host", apiUrl.toHttpUrl().host)
}
private val apiHeaders by lazy { apiHeadersBuilder().build() }
private val json: Json by injectLazy()
// ============================== Popular ===============================
override fun popularMangaRequest(page: Int): Request {
return GET("$apiUrl/layouts/s1/sliders/hotUpdates", apiHeaders)
}
override fun popularMangaParse(response: Response): MangasPage {
val data = response.parseAs<BrowseMangaDto>().items
return MangasPage(data.map { it.manga.toSManga() }, false)
}
// =============================== Latest ===============================
override fun latestUpdatesRequest(page: Int): Request {
return GET("$apiUrl/layouts/s1/latest-updates", apiHeaders)
}
override fun latestUpdatesParse(response: Response): MangasPage {
return popularMangaParse(response)
}
// =============================== Search ===============================
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$apiUrl/search".toHttpUrl().newBuilder()
.addPathSegment(query)
.build()
return GET(url, apiHeaders)
}
override fun searchMangaParse(response: Response): MangasPage {
val data = response.parseAs<SearchResultsDto>().hits
return MangasPage(data.map { it.info.toSManga() }, false)
}
// =========================== Manga Details ============================
override fun getMangaUrl(manga: SManga): String {
return baseUrl + manga.url
}
override fun mangaDetailsRequest(manga: SManga): Request {
return GET(apiUrl + manga.url, apiHeaders)
}
override fun mangaDetailsParse(response: Response): SManga {
return response.parseAs<MangaObjectDto>().manga.toSManga()
}
// ============================== Chapters ==============================
override fun chapterListRequest(manga: SManga): Request {
return mangaDetailsRequest(manga)
}
override fun chapterListParse(response: Response): List<SChapter> {
val chapterList = response.parseAs<MangaObjectDto>().manga.chapters!!.map {
it.toSChapter(response.request.url.pathSegments.last())
}
return chapterList.sortedWith(
compareBy(
{ it.chapter_number },
{ it.scanlator },
),
).reversed()
}
override fun getChapterUrl(chapter: SChapter): String {
val (slug, name) = chapter.url.split("/")
return "$baseUrl/read/s1/$slug/$name/1"
}
// =============================== Pages ================================
override fun pageListRequest(chapter: SChapter): Request {
val (slug, name) = chapter.url.split("/")
return GET("$apiUrl/manga/s1/$slug#$name", apiHeaders)
}
override fun pageListParse(response: Response): List<Page> {
val chapter = response.parseAs<MangaObjectDto>().manga.chapters!!.first {
it.name == response.request.url.fragment
}
return chapter.pages.map { page ->
Page(page.name.toInt(), imageUrl = page.pageURLs.first())
}.sortedBy { it.index }
}
override fun imageRequest(page: Page): Request {
val imgHeaders = headersBuilder().apply {
add("Accept", "image/avif,image/webp,*/*")
add("Host", page.imageUrl!!.toHttpUrl().host)
}.build()
return GET(page.imageUrl!!, imgHeaders)
}
override fun imageUrlParse(response: Response): String {
throw UnsupportedOperationException()
}
// ============================= Utilities ==============================
private inline fun <reified T> Response.parseAs(): T {
return json.decodeFromString(body.string())
}
}

View File

@ -0,0 +1,115 @@
package eu.kanade.tachiyomi.extension.en.atsumaru
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.Serializable
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
@Serializable
class BrowseMangaDto(
val items: List<MangaObjectDto>,
)
@Serializable
class MangaObjectDto(
val manga: MangaDto,
)
@Serializable
class SearchResultsDto(
val hits: List<SearchMangaDto>,
) {
@Serializable
class SearchMangaDto(
val info: MangaDto,
)
}
@Serializable
class MangaDto(
// Common
private val title: String,
private val cover: String,
private val slug: String,
// Details
private val authors: List<String>? = null,
private val description: String? = null,
private val genres: List<String>? = null,
private val statuses: List<String>? = null,
// Chapters
val chapters: List<ChapterDto>? = null,
) {
fun toSManga(): SManga = SManga.create().apply {
title = this@MangaDto.title
thumbnail_url = cover
url = "/manga/s1/$slug"
authors?.let {
author = it.joinToString()
}
description = this@MangaDto.description
genres?.let {
genre = it.joinToString()
}
statuses?.let {
status = when (it.first().lowercase().substringBefore(" ")) {
"ongoing" -> SManga.ONGOING
"complete" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
}
}
}
@Serializable
class ChapterDto(
val pages: List<PageDto>,
val name: String,
private val type: String,
private val title: String? = null,
private val date: String? = null,
) {
fun toSChapter(slug: String): SChapter = SChapter.create().apply {
val chapterNumber = this@ChapterDto.name.replace("_", ".")
.filter { it.isDigit() || it == '.' }
name = buildString {
append("Chapter ")
append(chapterNumber)
if (title != null) {
append(" - ")
append(title)
}
}
url = "$slug/${this@ChapterDto.name}"
chapter_number = chapterNumber.toFloat()
scanlator = type.takeUnless { it == "Chapter" }
date?.let {
date_upload = parseDate(it)
}
}
private fun parseDate(dateStr: String): Long {
return try {
DATE_FORMAT.parse(dateStr)!!.time
} catch (_: ParseException) {
0L
}
}
companion object {
private val DATE_FORMAT by lazy {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH)
}
}
}
@Serializable
class PageDto(
val pageURLs: List<String>,
val name: String,
)

View File

@ -1,7 +1,7 @@
ext {
extName = 'ColoredManga'
extClass = '.ColoredManga'
extVersionCode = 3
extVersionCode = 35
isNsfw = true
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Comic Scans'
extClass = '.ComicScans'
themePkg = 'madara'
baseUrl = 'https://www.comicscans.org'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

View File

@ -1,7 +0,0 @@
package eu.kanade.tachiyomi.extension.en.comicscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
class ComicScans : Madara("Comic Scans", "https://www.comicscans.org", "en") {
override val useNewChapterEndpoint = true
}

View File

@ -2,8 +2,8 @@ ext {
extName = 'EnryuManga'
extClass = '.EnryuManga'
themePkg = 'mangathemesia'
baseUrl = 'https://enryumanga.com'
overrideVersionCode = 0
baseUrl = 'https://enryumanga.net'
overrideVersionCode = 1
}
apply from: "$rootDir/common.gradle"

View File

@ -2,4 +2,4 @@ package eu.kanade.tachiyomi.extension.en.enryumanga
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
class EnryuManga : MangaThemesia("EnryuManga", "https://enryumanga.com", "en")
class EnryuManga : MangaThemesia("EnryuManga", "https://enryumanga.net", "en")

View File

@ -0,0 +1,9 @@
ext {
extName = 'Eros Scans'
extClass = '.ErosScans'
themePkg = 'mangathemesia'
baseUrl = 'https://erosscans.xyz'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.extension.en.erosscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
class ErosScans : MangaThemesia(
"Eros Scans",
"https://erosscans.xyz",
"en",
) {
override val client = super.client.newBuilder()
.rateLimit(3)
.build()
}

View File

@ -1,9 +1,9 @@
ext {
extName = 'Fire Scans'
extClass = '.FireScans'
extName = 'Firecomics'
extClass = '.Firecomics'
themePkg = 'madara'
baseUrl = 'https://firescans.xyz'
overrideVersionCode = 1
baseUrl = 'https://firecomics.org'
overrideVersionCode = 2
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -11,8 +11,9 @@ import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient
import org.jsoup.nodes.Document
class FireScans : Madara("Fire Scans", "https://firescans.xyz", "en") {
class Firecomics : Madara("Firecomics", "https://firecomics.org", "en") {
override val id: Long = 5761461704760730187
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(20, 5)
.build()

View File

@ -1,7 +1,7 @@
ext {
extName = 'Hentai2Read'
extClass = '.Hentai2Read'
extVersionCode = 16
extVersionCode = 17
isNsfw = true
}

View File

@ -0,0 +1,10 @@
ext {
extName = 'HentaiDex'
extClass = '.HentaiDex'
themePkg = 'mangathemesia'
baseUrl = 'https://dexhentai.com'
overrideVersionCode = 0
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Some files were not shown because too many files have changed in this diff Show More