diff --git a/dosagelib/plugins/b.py b/dosagelib/plugins/b.py index ea932d5a8..26439137d 100644 --- a/dosagelib/plugins/b.py +++ b/dosagelib/plugins/b.py @@ -99,22 +99,9 @@ class Beetlebum(_BasicScraper): class Bethellium(_WPWebcomic): - stripUrl = 'http://dbcomics.darkblueworkshop.com/bethellium/%s/' - firstStripUrl = stripUrl % 'chapter-1/cover' - url = firstStripUrl - latestSearch = '//main' + _WPWebcomic.latestSearch - starter = indirectStarter - - def getPrevUrl(self, url, data): - prevUrl = super(Bethellium, self).getPrevUrl(url, data) - return prevUrl.replace('%webcomic2_storyline%', 'chapter-2-the-hemlocks-scar') - - def namer(self, imageUrl, pageUrl): - # Prepend chapter title to page filenames - chapter = pageUrl.rstrip('/').rsplit('/', 3)[-2] - chapter = chapter.replace('chapter-1', 'chapter-1-the-magic-city') - page = imageUrl.rsplit('/', 1)[-1] - return chapter + '_' + page + url = 'https://bethellium.darkbluecomics.com/' + stripUrl = url + 'comic/%s/' + firstStripUrl = stripUrl % 'cover' class BetterDays(_ParserScraper): @@ -349,3 +336,10 @@ class ButterSafe(_ParserScraper): imageSearch = '//div[@id="comic"]/img' prevSearch = '//a[@rel="prev"]' help = 'Index format: yyyy/mm/dd/stripname' + + +class ByTheBook(_WordPressScraper): + url = 'http://www.btbcomic.com/' + stripUrl = url + 'comic/%s/' + firstStripUrl = stripUrl % 'chapter-1-page-0' + adult = True diff --git a/dosagelib/plugins/c.py b/dosagelib/plugins/c.py index fc2acada4..da064e3c3 100644 --- a/dosagelib/plugins/c.py +++ b/dosagelib/plugins/c.py @@ -286,7 +286,7 @@ class CollegeCatastrophe(_ParserScraper): stripUrl = url + '/%s' firstStripUrl = stripUrl % '2000-11-10' imageSearch = '//img[@class="comic-image"]' - prevSearch = '//a[span[contains(text(),"Previous")]]' + prevSearch = '//a[./span[contains(text(), "Previous")]]' endOfLife = True multipleImagesPerStrip = True diff --git a/dosagelib/plugins/comicfury.py b/dosagelib/plugins/comicfury.py index bcb40e981..105cd724f 100644 --- a/dosagelib/plugins/comicfury.py +++ b/dosagelib/plugins/comicfury.py @@ -49,7 +49,7 @@ class ComicFury(_ParserScraper): help = 'Index format: n' starter = bounceStarter - def __init__(self, name, sub, lang=None, adult=False): + def __init__(self, name, sub, lang=None, adult=False, endOfLife=False): super(ComicFury, self).__init__('ComicFury/' + name) self.prefix = name self.url = 'http://%s.webcomic.ws/comics/' % sub @@ -59,6 +59,8 @@ class ComicFury(_ParserScraper): self.lang = lang if adult: self.adult = adult + if endOfLife: + self.endOfLife = endOfLife def namer(self, image_url, page_url): parts = page_url.split('/') @@ -638,6 +640,7 @@ class ComicFury(_ParserScraper): cls('MaxFuture', 'maxfuture'), cls('MAYBELOVE', 'emmacomics'), cls('MayonakaDensha', 'mayonakadensha'), + cls('MayTheRainCome', 'maytheraincome', endOfLife=True), cls('MegaMaidenVSTheChopChopPrincess', 'megamaiden'), cls('MeganKearneysBeautyAndTheBeast', 'batb'), cls('MelancholyGoRound', 'melancholygoround'), diff --git a/dosagelib/plugins/common.py b/dosagelib/plugins/common.py index 88892cb7c..27d9caf30 100644 --- a/dosagelib/plugins/common.py +++ b/dosagelib/plugins/common.py @@ -19,7 +19,7 @@ class _WordPressScraper(_ParserScraper): class _WordPressSpliced(_ParserScraper): - imageSearch = '//div[@id="spliced-comic"]//img' + imageSearch = '//div[@id="one-comic-option"]//img' prevSearch = '//a[d:class("previous-comic")]' diff --git a/dosagelib/plugins/d.py b/dosagelib/plugins/d.py index 000f9aec0..bf49824be 100644 --- a/dosagelib/plugins/d.py +++ b/dosagelib/plugins/d.py @@ -365,6 +365,14 @@ class Drowtales(_ParserScraper): help = 'Index format: number' +class DungeonsAndDenizens(_WPNavi): + url = ('https://web.archive.org/web/20160308001834/' + 'http://dungeond.com/') + stripUrl = url + '%s/' + firstStripUrl = stripUrl % '2005/08/23/08232005' + endOfLife = True + + class DumbingOfAge(_WPNavi): url = 'http://www.dumbingofage.com/' stripUrl = url + '%s/' diff --git a/dosagelib/plugins/f.py b/dosagelib/plugins/f.py index 90ab9c248..a3a61cc5e 100644 --- a/dosagelib/plugins/f.py +++ b/dosagelib/plugins/f.py @@ -20,6 +20,15 @@ class FalconTwin(_BasicScraper): help = 'Index format: nnn' +class FalseStart(_ParserScraper): + url = 'https://boneitiscomics.com/falsestart.php' + stripUrl = url + '?pg=%s' + firstStripUrl = stripUrl % '1' + imageSearch = '//div[@class="page"]//img' + prevSearch = '//a[@id="prev"]' + adult = True + + class Faneurysm(_WPNaviIn): url = 'http://hijinksensue.com/comic/think-only-tree/' firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/' diff --git a/dosagelib/plugins/l.py b/dosagelib/plugins/l.py index 2dc0579b0..75f4558cd 100644 --- a/dosagelib/plugins/l.py +++ b/dosagelib/plugins/l.py @@ -46,10 +46,16 @@ class LazJonesAndTheMayfieldRegulators(_ParserScraper): class LazJonesAndTheMayfieldRegulatorsSideStories(LazJonesAndTheMayfieldRegulators): name = 'LazJonesAndTheMayfieldRegulators/SideStories' baseUrl = 'https://www.lazjones.com/' - url = baseUrl + 'sidestories' + url = baseUrl + 'comics' stripUrl = baseUrl + 'comic/%s' firstStripUrl = stripUrl % 'journal01' + def getPrevUrl(self, url, data): + # Fix broken navigation links + if url == self.url and data.xpath(self.prevSearch + '/@href')[0] == self.stripUrl % 'summer00': + return self.stripUrl % 'summer21' + return super(LazJonesAndTheMayfieldRegulators, self).getPrevUrl(url, data) + class LeastICouldDo(_ParserScraper): url = 'https://leasticoulddo.com/' diff --git a/dosagelib/plugins/m.py b/dosagelib/plugins/m.py index 99f9d37e4..1fbfb89cd 100644 --- a/dosagelib/plugins/m.py +++ b/dosagelib/plugins/m.py @@ -84,6 +84,15 @@ class MarriedToTheSea(_ParserScraper): return '%s-%s' % (date, filename) +class MarryMe(_ParserScraper): + url = 'http://marryme.keenspot.com/' + stripUrl = url + 'd/%s.html' + firstStripUrl = stripUrl % '20120730' + imageSearch = '//img[@class="ksc"]' + prevSearch = '//a[@rel="prev"]' + endOfLife = True + + class MaxOveracts(_ParserScraper): url = 'http://occasionalcomics.com/' stripUrl = url + '%s/' @@ -179,26 +188,16 @@ class MonsieurLeChien(_BasicScraper): class Moonlace(_WPWebcomic): - stripUrl = 'http://dbcomics.darkblueworkshop.com/moonlace/%s/' - firstStripUrl = stripUrl % 'prologue/page-1' - url = firstStripUrl - latestSearch = '//main' + _WPWebcomic.latestSearch + url = 'https://moonlace.darkbluecomics.com/' + stripUrl = url + 'comic/%s/' + firstStripUrl = stripUrl % 'page-0-1' adult = True def starter(self): # Set age-gate cookie - self.session.cookies.set('age_gate', '1', domain='darkblueworkshop.com') + self.session.cookies.set('age_gate', '1', domain='moonlace.darkblueworkshop.com') return indirectStarter(self) - def namer(self, imageUrl, pageUrl): - # Prepend chapter title to page filenames - chapter = pageUrl.rstrip('/').rsplit('/', 3)[-2] - chapter = chapter.replace('prologue', 'chapter-0-prologue') - chapter = chapter.replace('chapter-1', 'chapter-1-heritage') - chapter = chapter.replace('chapter2', 'chapter-2') - page = imageUrl.rsplit('/', 1)[-1] - return chapter + '_' + page - class Moonsticks(_ParserScraper): url = "http://moonsticks.org/" diff --git a/dosagelib/plugins/mangadex.py b/dosagelib/plugins/mangadex.py index 37ad6615a..7f48d9e0e 100644 --- a/dosagelib/plugins/mangadex.py +++ b/dosagelib/plugins/mangadex.py @@ -25,7 +25,9 @@ class MangaDex(_ParserScraper): mangaData = manga.json() # Determine if manga is complete and/or adult if mangaData['manga']['last_chapter'] != '0': - self.endOfLife = True + for ch in mangaData['chapter']: + if mangaData['chapter'][ch]['chapter'] == mangaData['manga']['last_chapter']: + self.endOfLife = True if mangaData['manga']['hentai'] != '0': self.adult = True # Prepare chapter list @@ -71,8 +73,11 @@ class MangaDex(_ParserScraper): return ( cls('AttackonTitan', 429), cls('Beastars', 20523), + cls('BokuNoKokoroNoYabaiYatsu', 23811), cls('DeliciousinDungeon', 13871), cls('DragonDrive', 5165), + cls('FuguushokuKajishiDakedoSaikyouDesu', 56319), + cls('GanbareDoukiChan', 46585), cls('HangingOutWithAGamerGirl', 42490), cls('HoriMiya', 6770), cls('HowToOpenATriangularRiceball', 19305), @@ -84,19 +89,23 @@ class MangaDex(_ParserScraper): cls('Lv2KaraCheatDattaMotoYuushaKouhoNoMattariIsekaiLife', 33797), cls('MaouNoOreGaDoreiElfWoYomeNiShitandaGaDouMederebaIi', 25495), cls('ModernMoGal', 30308), + cls('MyTinySenpaiFromWork', 43610), cls('OMaidensinYourSavageSeason', 22030), cls('OokamiShounenWaKyouMoUsoOKasaneru', 14569), cls('OokamiToKoshinryou', 1168), cls('OtomeYoukaiZakuro', 4533), cls('OversimplifiedSCP', 32834), + cls('PashiriNaBokuToKoisuruBanchouSan', 25862), cls('PleaseDontBullyMeNagatoro', 22631), cls('PleaseDontBullyMeNagatoroComicAnthology', 31004), cls('PleaseTellMeGalkochan', 12702), cls('SaekiSanWaNemutteru', 28834), + cls('SenpaiGaUzaiKouhaiNoHanashi', 23825), cls('SewayakiKitsuneNoSenkoSan', 22723), cls('SousouNoFrieren', 48045), cls('SwordArtOnline', 1360), cls('SwordArtOnlineProgressive', 9604), + cls('TamenDeGushi', 13939), cls('TheWolfAndRedRidingHood', 31079), cls('TomoChanWaOnnanoko', 15722), cls('TonikakuKawaii', 23439), diff --git a/dosagelib/plugins/n.py b/dosagelib/plugins/n.py index 509f09fb3..2fb7f4009 100644 --- a/dosagelib/plugins/n.py +++ b/dosagelib/plugins/n.py @@ -153,7 +153,7 @@ class NineToNine(_ParserScraper): stripUrl = url + '/%s' firstStripUrl = stripUrl % '2014-01-01' imageSearch = '//img[@class="comic-image"]' - prevSearch = '//a[@class="prev"]' + prevSearch = '//a[./span[contains(text(), "Previous")]]' multipleImagesPerStrip = True diff --git a/dosagelib/plugins/old.py b/dosagelib/plugins/old.py index a682ed0b8..384650802 100644 --- a/dosagelib/plugins/old.py +++ b/dosagelib/plugins/old.py @@ -214,7 +214,6 @@ class Removed(Scraper): cls('DamnLol'), cls('DeathToTheExtremist'), cls('DoctorCat', 'brk'), - cls('DungeonsAndDenizens'), cls('EerieCuties'), cls('Ellerbisms'), cls('Eriadan'), @@ -630,8 +629,6 @@ class Removed(Scraper): cls('ComicFury/TheUnthinkableHybrid'), cls('ComicFury/TwentyFourSeven'), cls('ComicFury/TwentyFourSevenFans'), - cls('TheCyantianChronicles/CookieCaper'), - cls('TheCyantianChronicles/Pawprints'), cls('GoComics/2CowsAndAChicken'), cls('GoComics/AskAPortlySyndicatePerson'), cls('GoComics/Bewley'), @@ -775,7 +772,6 @@ class Removed(Scraper): cls('SmackJeeves/BoogeyDancingMonkeyPot'), cls('SmackJeeves/BreachOfAgency'), cls('SmackJeeves/Burn'), - cls('SmackJeeves/ByTheBook'), cls('SmackJeeves/CafeSuada'), cls('SmackJeeves/Cambion'), cls('SmackJeeves/CaptiveSoul'), @@ -1271,6 +1267,8 @@ class Removed(Scraper): cls('Shivae/Extras'), cls('SnafuComics/Titan'), cls('StuffNoOneToldMe'), + cls('TheCyantianChronicles/CookieCaper'), + cls('TheCyantianChronicles/Pawprints'), cls('VictimsOfTheSystem'), cls('WebDesignerCOTW'), ) @@ -1424,6 +1422,7 @@ class Renamed(Scraper): cls('GoComics/WebcomicName', 'WebcomicName'), cls('Shivae/BlackRose', 'BlackRose'), cls('SmackJeeves/BlackTapestries', 'ComicFury/BlackTapestries'), + cls('SmackJeeves/ByTheBook', 'ByTheBook'), cls('SmackJeeves/FurryExperience', 'ComicFury/FurryExperience'), cls('SmackJeeves/GrowingTroubles', 'ComicFury/GrowingTroubles'), cls('SmackJeeves/TheRealmOfKaerwyn', 'ComicFury/TheRealmOfKaerwyn'), diff --git a/dosagelib/plugins/p.py b/dosagelib/plugins/p.py index 53fad7afe..4f6fbce8a 100644 --- a/dosagelib/plugins/p.py +++ b/dosagelib/plugins/p.py @@ -248,11 +248,12 @@ class PoppyOPossum(_WordPressScraper): class PowerNap(_ParserScraper): - url = 'http://www.powernapcomic.com/' + url = 'https://www.powernapcomic.com/powernap/' stripUrl = url + 'd/%s.html' firstStripUrl = stripUrl % '20110617' - imageSearch = '//img[contains(@src, "/pnap")]' + imageSearch = '//center/img' prevSearch = '//a[./img[contains(@src, "previous")]]' + endOfLife = True def imageUrlModifier(self, url, data): return url.replace('\n', '').strip() diff --git a/dosagelib/plugins/q.py b/dosagelib/plugins/q.py index 9e553e463..999bb6f79 100644 --- a/dosagelib/plugins/q.py +++ b/dosagelib/plugins/q.py @@ -11,7 +11,7 @@ class QuantumVibe(_ParserScraper): stripUrl = url + 'strip?page=%s' firstStripUrl = stripUrl % '1' imageSearch = '//img[contains(@src, "disppageV3?story=qv")]' - prevSearch = '//a[./img[contains(@src, "nav/prevstrip")]]' + prevSearch = '//a[./img[@alt="Previous Strip"]]' class QuestionableContent(_ParserScraper): diff --git a/dosagelib/plugins/r.py b/dosagelib/plugins/r.py index 349af0f2b..0041b5237 100644 --- a/dosagelib/plugins/r.py +++ b/dosagelib/plugins/r.py @@ -78,6 +78,23 @@ class RealmOfAtland(_BasicScraper): help = 'Index format: nnn' +class Recursion(_ParserScraper): + url = 'https://recursioncomic.com/' + stripUrl = url + '%s' + firstStripUrl = stripUrl % '0001' + imageSearch = '//div[@class="content"]//img' + prevSearch = '//link[@rel="prev"]' + + def namer(self, imageUrl, pageUrl): + # Fix inconsistent filenames + filename = imageUrl.rsplit('/', 1)[-1] + filename = filename.replace('0bf62e92-2c98-4fb2-8ed7-4584980beb17', 'page0005') + filename = filename.replace('76112837-c5cd-4df7-8c53-3ed5c25194cf', 'page0003') + filename = filename.replace('ed271080-6b1b-4d7a-8509-b2d8a15da805', 'page0002') + filename = filename.replace('7b194ef7-ac77-4b5c-aed0-826901d13d04', 'page0001') + return filename + + class RedMeat(_ParserScraper): url = 'http://www.redmeat.com/max-cannon/FreshMeat' imageSearch = '//div[@class="comicStrip"]//img' diff --git a/dosagelib/plugins/s.py b/dosagelib/plugins/s.py index 25966a6e4..e6e07e6b5 100644 --- a/dosagelib/plugins/s.py +++ b/dosagelib/plugins/s.py @@ -312,15 +312,21 @@ class SluggyFreelance(_ParserScraper): class SMBC(_ComicControlScraper): - url = 'http://www.smbc-comics.com/' - firstStripUrl = url + 'comic/2002-09-05' - multipleImagesPerStrip = True + url = 'https://www.smbc-comics.com/' + stripUrl = url + 'comic/%s' + firstStripUrl = stripUrl % '2002-09-05' imageSearch = ['//img[@id="cc-comic"]', '//div[@id="aftercomic"]/img'] textSearch = '//img[@id="cc-comic"]/@title' + multipleImagesPerStrip = True - def namer(self, image_url, page_url): - """Remove random noise from name.""" - return image_url.rsplit('-', 1)[-1] + def namer(self, imageUrl, pageUrl): + # Remove random noise from filename + filename = imageUrl.rsplit('/', 1)[-1] + if '-' in filename and len(filename.rsplit('-', 1)[-1]) > 12: + filename = filename.rsplit('-', 1)[-1] + elif len(filename) > 22 and filename[0] == '1': + filename = filename[10:] + return filename class SnowFlame(_WordPressScraper): @@ -672,7 +678,7 @@ class Supercell(_ParserScraper): url = 'https://www.supercellcomic.com/' stripUrl = url + 'pages/%s.html' firstStripUrl = stripUrl % '0001' - imageSearch = '//div[@class="comicpage"]//img' + imageSearch = '//img[@class="comicStretch"]' prevSearch = '//div[@class="comicnav"]/a[./img[contains(@src, "comnav_02")]]' @@ -702,5 +708,5 @@ class SwordsAndSausages(_ParserScraper): stripUrl = url + '/%s' firstStripUrl = stripUrl % '1-1' imageSearch = '//img[@class="comic-image"]' - prevSearch = '//a[@class="prev"]' + prevSearch = '//a[./span[contains(text(), "Previous")]]' multipleImagesPerStrip = True diff --git a/dosagelib/plugins/shivaestudios.py b/dosagelib/plugins/shivaestudios.py index 641787289..4d28ca44d 100644 --- a/dosagelib/plugins/shivaestudios.py +++ b/dosagelib/plugins/shivaestudios.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT # Copyright (C) 2019-2021 Tobias Gruetzmacher -# Copyright (C) 2019-2020 Daniel Ring +# Copyright (C) 2019-2021 Daniel Ring from .common import _WordPressSpliced @@ -21,6 +21,12 @@ class AlienDice(_WordPressSpliced): stripUrl = url + 'comic/%s/' firstStripUrl = stripUrl % '05162001' + def getPrevUrl(self, url, data): + # Fix broken navigation + if url == self.stripUrl % 'day-29-part-2-page-3-4': + return self.stripUrl % 'day-29-part-2-page-3-2' + return super(AlienDice, self).getPrevUrl(url, data) + def namer(self, imageUrl, pageUrl): # Fix inconsistent filename return imageUrl.rsplit('/', 1)[-1].replace('20010831', '2001-08-31') @@ -28,12 +34,16 @@ class AlienDice(_WordPressSpliced): class AlienDiceLegacy(_WordPressSpliced): name = 'AlienDice/Legacy' - url = 'https://aliendice.com/chapter/legacy/' - stripUrl = url + 'page/%s/' - firstStripUrl = stripUrl % '45' - prevSearch = '//div[d:class("nav-previous")]/a' + baseUrl = 'https://aliendice.com/' + url = baseUrl + 'series/legacy/' + stripUrl = baseUrl + 'comic/%s/' + firstStripUrl = stripUrl % 'legacy-1' endOfLife = True + def isfirststrip(self, url): + # Strip series identifier + return super(AlienDiceLegacy, self).isfirststrip(url.rsplit('?', 1)[0]) + class BlackRose(_WordPressSpliced): url = 'https://www.blackrose.monster/' @@ -60,9 +70,9 @@ class TheCyantianChronicles(_WithSid): cls('CesileesDiary', 'cesilees-diary', '12062001-2', 16726, eol=True), cls('Darius', 'darius', '03102010', 14353, eol=True), cls('DracoVulpes', 'draco-vulpes', 'draco-vulpes', 13788), - cls('GenoworksSaga', 'genoworks-saga', '07012004', 13794, eol=True), + cls('GenoworksSaga', 'genoworks-saga', '07012004', 13794), cls('GralenCraggHall', 'kiet', '07152002', 13798, eol=True), - cls('Kiet', 'kiet-2', 'kiet-c01', 14351, eol=True), + cls('Kiet', 'kiet-2', 'kiet-c01', 14351), cls('NoAngel', 'no-angel', '08112001', 16644, eol=True), cls('RandomRamblings', 'gallery', 'cookie-war', 13801), cls('SinkOrSwim', 'sink-or-swim', '05112001', 13796, eol=True), @@ -77,7 +87,7 @@ class Shivae(_WordPressSpliced): class ShivaeComics(_WithSid): - baseUrl = 'https://shivae.net/index.php/' + baseUrl = 'https://shivae.net/' def __init__(self, name, path, first, sid, eol=False): super().__init__('Shivae/' + name, sid) diff --git a/dosagelib/plugins/t.py b/dosagelib/plugins/t.py index ee055b689..0792f63e1 100644 --- a/dosagelib/plugins/t.py +++ b/dosagelib/plugins/t.py @@ -23,6 +23,14 @@ class TailsAndTactics(_ParserScraper): prevSearch = '//a[text()=" Back"]' +class TaleOfTenThousand(_ParserScraper): + url = 'http://www.t10k.club/' + stripUrl = url + 'comic/%s' + firstStripUrl = stripUrl % '1-01_00' + imageSearch = '//article[@id="comic"]//img' + prevSearch = '//a[d:class("prev")]' + + class TekMage(_WPNavi): url = 'https://tekmagecomic.com/' stripUrl = url + 'comic/%s/' diff --git a/dosagelib/plugins/v.py b/dosagelib/plugins/v.py index 07df644b4..d375a7ee0 100644 --- a/dosagelib/plugins/v.py +++ b/dosagelib/plugins/v.py @@ -7,6 +7,15 @@ from ..scraper import _ParserScraper from ..helpers import bounceStarter, indirectStarter +class VampireHunterBoyfriends(_ParserScraper): + url = 'https://boneitiscomics.com/vhb.php' + stripUrl = url + '?pg=%s' + firstStripUrl = stripUrl % '1' + imageSearch = '//div[@class="page"]//img' + prevSearch = '//a[@id="prev"]' + adult = True + + class Vexxarr(_ParserScraper): baseUrl = 'http://www.vexxarr.com/' url = baseUrl + 'Index.php' diff --git a/dosagelib/plugins/webtoons.py b/dosagelib/plugins/webtoons.py index b1abcfca9..afded9b37 100644 --- a/dosagelib/plugins/webtoons.py +++ b/dosagelib/plugins/webtoons.py @@ -87,6 +87,8 @@ class WebToons(_ParserScraper): cls('BehindTheGIFs', 'comedy/behind-the-gifs', 658), cls('BigJo', 'romance/big-jo', 854), cls('BiteMe', 'thriller/bite-me', 1019), + cls('Blackened', 'challenge/blackened', 363805), + cls('BladesOfFurry', 'romance/blades-of-furry', 2383), cls('Blessed', 'drama/blessed', 1193), cls('BloodInk', 'action/blood-ink', 1490), cls('BloodlessWars', 'sf/bloodless-wars', 1622), @@ -109,19 +111,23 @@ class WebToons(_ParserScraper): cls('CherryBlossoms', 'romance/cherry-blossoms', 1005), cls('Chiller', 'thriller/chiller', 536), cls('ChocoLatte', 'romance/choco-latte', 1691), + cls('CChansACatgirl', 'challenge/c-chans-a-catgirl', 263430), cls('CityOfBlank', 'sf/city-of-blank', 1895), cls('CityOfWalls', 'drama/city-of-wall', 505), + cls('CityVamps', 'challenge/city-vamps-', 119224), cls('ClusterFudge', 'slice-of-life/cluster-fudge', 355), cls('CodeAdam', 'action/code-adam', 1657), cls('CookingComically', 'tiptoon/cooking-comically', 622), cls('CrapIDrewOnMyLunchBreak', 'challenge/crap-i-drew-on-my-lunch-break', 124756), cls('Crumbs', 'romance/crumbs', 1648), + cls('CrystalVirus', 'challenge/crystal-virus', 347038), cls('CupidsArrows', 'romance/cupids-arrows', 1538), cls('CursedPrincessClub', 'comedy/cursed-princess-club', 1537), cls('Cyberbunk', 'sf/cyberbunk', 466), cls('Cyberforce', 'super-hero/cyberforce', 531), cls('CykoKO', 'super-hero/cyko-ko', 560), cls('Darbi', 'action/darbi', 1098), + cls('DatingWithATail', 'romance/dating-with-a-tail', 1263), cls('Davinchibi', 'fantasy/davinchibi', 1190), cls('DaYomanvilleGang', 'drama/da-yomanville-gang', 1578), cls('DaysOfHana', 'drama/days-of-hana', 1246), @@ -140,6 +146,7 @@ class WebToons(_ParserScraper): cls('DownToEarth', 'romance/down-to-earth', 1817), cls('Dragnarok', 'fantasy/dragnarok', 1018), cls('DragnarokDescendants', 'fantasy/dragnarok-descendants', 1433), + cls('DrawnToYou', 'challenge/drawn-to-you', 172022), cls('DrFrost', 'drama/dr-frost', 371), cls('DungeonMinis', 'challenge/dungeonminis', 64132), cls('Dustinteractive', 'comedy/dustinteractive', 907), @@ -167,6 +174,7 @@ class WebToons(_ParserScraper): cls('FourLeaf', 'fantasy/four-leaf', 1454), cls('FreakingRomance', 'romance/freaking-romance', 1467), cls('FridayForbiddenTales', 'thriller/friday', 388), + cls('FutureYou', 'challenge/future-you', 288439), cls('GameMasters', 'challenge/game-masters', 237252), cls('GenshinImpact', 'challenge/genshin-impact', 242646), cls('Gepetto', 'sf/gepetto', 81), @@ -212,6 +220,7 @@ class WebToons(_ParserScraper): cls('JingleJungle', 'slice-of-life/jingle-jungle', 282), cls('JustAskYuli', 'slice-of-life/just-ask-yuli', 402), cls('JustForKicks', 'slice-of-life/just-for-kicks', 1152), + cls('JustFriends', 'challenge/just-friends', 190722), cls('JustPancakes', 'comedy/just-pancakes', 1651), cls('KidsAreAllRight', 'drama/kids-are-all-right', 283), cls('Killstagram', 'thriller/killstagram', 1971), @@ -237,6 +246,7 @@ class WebToons(_ParserScraper): cls('Lorna', 'slice-of-life/lorna', 1284), cls('LostInTranslation', 'drama/lost-in-translation', 1882), cls('LoveAdviceFromTheGreatDukeOfHell', 'comedy/love-advice', 1498), + cls('LoveMeKnot', 'romance/love-me-knot', 2224), cls('Lozolz', 'tiptoon/lozolz', 1268), cls('LUFF', 'romance/luff', 1489), cls('Luggage', 'fantasy/luggage', 1642), @@ -263,9 +273,11 @@ class WebToons(_ParserScraper): cls('Murrz', 'slice-of-life/murrz', 1281), cls('Muted', 'supernatural/muted', 1566), cls('MyBoo', 'supernatural/my-boo', 1185), + cls('MyAssassinGirlfriend', 'challenge/my-assassin-girlfriend', 249007), cls('MyDearColdBloodedKing', 'romance/my-dear-cold-blooded-king', 961), cls('MyDeepestSecret', 'thriller/my-deepest-secret', 1580), cls('MyDictatorBoyfriend', 'comedy/my-dictator-boyfriend', 1391), + cls('MyDragonGirlfriend', 'challenge/my-dragon-girlfriend', 162918), cls('MyGiantNerdBoyfriend', 'slice-of-life/my-giant-nerd-boyfriend', 958), cls('MyKittyAndOldDog', 'slice-of-life/my-kitty-and-old-dog', 184), cls('MyNameIsBenny', 'slice-of-life/my-name-is-benny', 1279), @@ -290,7 +302,9 @@ class WebToons(_ParserScraper): cls('OVERPOWERED', 'challenge/overpowered', 85292), cls('PacificRimAmara', 'sf/pacific-rim-amara', 1327), cls('PenguinLovesMev', 'slice-of-life/penguin-loves-mev', 86), + cls('Petrichor', 'challenge/petrichor', 100835), cls('PhantomParadise', 'fantasy/phantom-paradise', 1250), + cls('Phase', 'romance/phase', 2117), cls('Pigminted', 'slice-of-life/pigminted', 482), cls('PinchPoint', 'challenge/pinch-point-reborn', 334640), cls('Plum', 'sports/plum', 1605), @@ -335,6 +349,7 @@ class WebToons(_ParserScraper): cls('SoulOnHold', 'supernatural/soul-on-hold', 1701), cls('SpaceBoy', 'sf/space-boy', 400), cls('SpaceVixen', 'challenge/space-vixen-deep-space-k9', 207049), + cls('SpellsFromHell', 'fantasy/spells-from-hell', 2431), cls('SpiritFingers', 'drama/spirit-fingers', 1577), cls('Spirits', 'fantasy/spirits-re', 1348), cls('StalkerXStalker', 'challenge/stalker-x-stalker', 245662), @@ -421,6 +436,7 @@ class WebToons(_ParserScraper): cls('XINK3R', 'super-hero/xinker', 541), cls('YourAdventure', 'comedy/your-adventure', 506), cls('YourLetter', 'drama/your-letter', 1540), + cls('YouveGottaBeKittenMe', 'challenge/youve-gotta-be-kitten-me', 383661), cls('YumisCells', 'slice-of-life/yumi-cell', 478), cls('YunaAndKawachan', 'drama/yuna-and-kawachan', 1840), cls('ZeroGame', 'fantasy/zero-game', 1704),