Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1445fee

Browse files
committed
Add dridespoon and fix voidscans
1 parent4038bef commit1445fee

File tree

6 files changed

+336
-3
lines changed

6 files changed

+336
-3
lines changed

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Misc. sources for scanlators and aggregators.
33

44
#Websites
55
*https://catmanga.org/
6+
*http://dridesp.ooo/n/
67
*https://glitchycomics.com/
78
*https://www.novelcool.com/
89
*https://rainofsnow.com/

‎src/Dridespoon/Dridespoon.ts‎

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import{
2+
Chapter,
3+
ChapterDetails,
4+
HomeSection,
5+
LanguageCode,
6+
Manga,
7+
MangaStatus,
8+
MangaTile,
9+
MangaUpdates,
10+
PagedResults,
11+
Request,
12+
RequestManager,
13+
SearchRequest,
14+
Source,
15+
SourceInfo,
16+
TagType,
17+
}from"paperback-extensions-common"
18+
import{DridespoonParser}from"./DridespoonParser";
19+
20+
constBASE="http://dridesp.ooo"
21+
22+
exportconstDridespoonInfo:SourceInfo={
23+
icon:"icon.png",
24+
version:"1.0.0",
25+
name:"Dridespoon",
26+
author:"PythonCoderAS",
27+
authorWebsite:"https://github.com/PythonCoderAS",
28+
description:"Extension that pulls manga from Dridespoon",
29+
language:"en",
30+
hentaiSource:false,
31+
websiteBaseURL:BASE,
32+
sourceTags:[
33+
{
34+
text:"Notifications",
35+
type:TagType.GREEN
36+
}
37+
]
38+
}
39+
40+
exportclassDridespoonextendsSource{
41+
42+
privatereadonlyparser:DridespoonParser=newDridespoonParser();
43+
44+
45+
readonlyrequestManager:RequestManager=createRequestManager({
46+
requestsPerSecond:5,
47+
requestTimeout:10000
48+
});
49+
50+
getMangaShareUrl(mangaId:string):string{
51+
return`${BASE}/n/${mangaId}`;
52+
}
53+
54+
asyncgetHomePageSections(sectionCallback:(section:HomeSection)=>void):Promise<void>{
55+
constoptions:Request=createRequestObject({
56+
url:`${BASE}/n/`,
57+
method:'GET'
58+
});
59+
letresponse=awaitthis.requestManager.schedule(options,1);
60+
let$=this.cheerio.load(response.data);
61+
sectionCallback(createHomeSection({
62+
id:"1",
63+
items:this.parser.parseMangaList($,BASE,"sfw"),
64+
title:"Involvements"
65+
}));
66+
sectionCallback(createHomeSection({
67+
id:"2",
68+
items:this.parser.parseMangaList($,BASE,"collapseOne"),
69+
title:"Past Involvements"
70+
}));
71+
sectionCallback(createHomeSection({
72+
id:"3",
73+
items:this.parser.parseMangaList($,BASE,"collapseThree"),
74+
title:"Finished Projects"
75+
}));
76+
}
77+
78+
79+
asyncgetWebsiteMangaDirectory(metadata:any):Promise<PagedResults>{
80+
constoptions:Request=createRequestObject({
81+
url:`${BASE}/n/`,
82+
method:'GET'
83+
});
84+
letresponse=awaitthis.requestManager.schedule(options,1);
85+
let$=this.cheerio.load(response.data);
86+
returncreatePagedResults({
87+
results:this.parser.parseMangaList($,BASE,"main")
88+
})
89+
}
90+
91+
asyncgetChapterDetails(mangaId:string,chapterId:string):Promise<ChapterDetails>{
92+
leturl=this.getMangaShareUrl(mangaId);
93+
if(chapterId!=="Paperback-iOS-sentinel-id"){
94+
url+="/"+chapterId
95+
}
96+
constoptions:Request=createRequestObject({
97+
url:url,
98+
method:'GET'
99+
});
100+
letresponse=awaitthis.requestManager.schedule(options,1);
101+
let$=this.cheerio.load(response.data);
102+
constpages=this.parser.parsePages($,BASE)
103+
returncreateChapterDetails({
104+
id:chapterId,
105+
longStrip:false,
106+
mangaId:mangaId,
107+
pages:pages
108+
})
109+
}
110+
111+
asyncgetChapters(mangaId:string):Promise<Chapter[]>{
112+
constoptions:Request=createRequestObject({
113+
url:this.getMangaShareUrl(mangaId),
114+
method:'GET'
115+
});
116+
letresponse=awaitthis.requestManager.schedule(options,1);
117+
let$=this.cheerio.load(response.data);
118+
letparsedPages=this.parser.parsePages($,BASE);
119+
if(parsedPages.length!==0){
120+
return[createChapter({
121+
chapNum:1,
122+
id:"Paperback-iOS-sentinel-id",
123+
langCode:LanguageCode.ENGLISH,
124+
mangaId:mangaId
125+
})]
126+
}else{
127+
returnthis.parser.parseChapterList($,mangaId);
128+
}
129+
}
130+
131+
asyncgetMangaDetails(mangaId:string):Promise<Manga>{
132+
constoptions:Request=createRequestObject({
133+
url:this.getMangaShareUrl(mangaId),
134+
method:'GET'
135+
});
136+
letresponse=awaitthis.requestManager.schedule(options,1);
137+
let$=this.cheerio.load(response.data);
138+
letparsedPages=this.parser.parsePages($,BASE);
139+
if(parsedPages.length!==0){
140+
returncreateManga({
141+
id:mangaId,
142+
image:parsedPages[0],
143+
rating:0,
144+
status:MangaStatus.COMPLETED,
145+
titles:[mangaId]
146+
})
147+
}else{
148+
returnthis.parser.parseManga($,mangaId,BASE);
149+
}
150+
}
151+
152+
asyncsearchRequest(query:SearchRequest,metadata:any):Promise<PagedResults>{
153+
// TODO: Wait for search to be implemented on the website.
154+
constresults=(awaitthis.getWebsiteMangaDirectory(null)).results;
155+
constdata:MangaTile[]=[];
156+
for(leti=0;i<results.length;i++){
157+
constkey=results[i];
158+
if(query.title){
159+
if((key.title.text||"").toLowerCase().includes((query.title.toLowerCase()))){
160+
data.push(key);
161+
}
162+
}
163+
}
164+
returncreatePagedResults({
165+
results:data
166+
});
167+
}
168+
169+
170+
asyncfilterUpdatedManga(mangaUpdatesFoundCallback:(updates:MangaUpdates)=>void,time:Date,ids:string[]):Promise<void>{
171+
mangaUpdatesFoundCallback(createMangaUpdates({ids:ids}));
172+
}
173+
}

‎src/Dridespoon/DridespoonParser.ts‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import{Chapter,LanguageCode,Manga,MangaStatus,MangaTile}from"paperback-extensions-common";
2+
3+
exportclassDridespoonParser{
4+
5+
pageRegex=/src:"(https:\/\/beta\.voidscans\.net\/[^\s"']+)"/g
6+
7+
parseMangaList($:CheerioStatic,base:string,id:string){
8+
constmangaTiles:MangaTile[]=[];
9+
$(`#${id} div.col-md-4.picture-item:not(.manga-card)`).map((index,element)=>{
10+
constlink=$("a",$("li.list-group-item",element).last());
11+
letlinkId=link.attr("href");
12+
if(!linkId){
13+
constlink2=$("a",element).first().attr("href")
14+
if(link2&&link2.match(/\/$/)){
15+
// Exception for manga where there are no chapters but the manga itself is the chapter.
16+
linkId=link2;
17+
}
18+
}
19+
if(linkId){
20+
mangaTiles.push(createMangaTile({
21+
id:linkId.replace(`/n/`,"").replace("/",""),
22+
title:createIconText({
23+
text:$("p",element).first().text().trim().replaceAll(/\s{2,}/g,"")
24+
}),
25+
image:`${base}/${($("img",element).first().attr("src")||"").replace(/^\//,"")}`
26+
}))
27+
}
28+
})
29+
returnmangaTiles;
30+
}
31+
32+
parsePages($:CheerioStatic,base:string):string[]{
33+
constpages:string[]=[];
34+
$("img[data-src]").map((index,element)=>{
35+
pages.push(element.attribs["data-src"].replace("/../..",base))
36+
})
37+
returnpages;
38+
}
39+
40+
parseChapterList($:CheerioStatic,mangaId:string){
41+
constchapters:Chapter[]=[];
42+
$("table[data-sort-name] tbody tr").map((index,element)=>{
43+
constchapNum=Number($("th",element).first().text());
44+
constdata:Chapter={
45+
chapNum:chapNum,
46+
id:String(chapNum),
47+
langCode:LanguageCode.ENGLISH,
48+
mangaId:mangaId,
49+
time:newDate($("td",element).last().text()),
50+
name:$("td",element).first().text()
51+
}
52+
chapters.push(createChapter(data))
53+
})
54+
returnchapters
55+
}
56+
57+
parseManga($:CheerioStatic,mangaId:string,base:string){
58+
constmangaObj:Manga={
59+
desc:$("p#series_desc").first().text().trim(),
60+
id:mangaId,
61+
image:base+($("img").attr("src")||""),
62+
rating:0,
63+
status:MangaStatus.ONGOING,
64+
titles:[$("h1").first().text()],
65+
}
66+
returncreateManga(mangaObj)
67+
}
68+
69+
}

‎src/Dridespoon/includes/icon.png‎

47 KB
Loading

‎src/VoidScans/VoidScans.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const BASE = "https://voidscans.net"
1515

1616
exportconstVoidScansInfo:SourceInfo={
1717
icon:"icon.svg",
18-
version:"1.3.2",
18+
version:"1.4.0",
1919
name:"VoidScans",
2020
author:"PythonCoderAS",
2121
authorWebsite:"https://github.com/PythonCoderAS",
@@ -69,7 +69,7 @@ export class VoidScans extends Source {
6969
constpages=this.parser.parsePages($)
7070
returncreateChapterDetails({
7171
id:chapterId,
72-
longStrip:true,
72+
longStrip:false,
7373
mangaId:mangaId,
7474
pages:pages
7575
})
@@ -102,7 +102,7 @@ export class VoidScans extends Source {
102102
for(leti=0;i<results.length;i++){
103103
constkey=results[i];
104104
if(query.title){
105-
if((key.primaryText?.text||"").toLowerCase().includes((query.title.toLowerCase()))){
105+
if((key.title.text||"").toLowerCase().includes((query.title.toLowerCase()))){
106106
data.push(key);
107107
}
108108
}
@@ -114,6 +114,8 @@ export class VoidScans extends Source {
114114

115115

116116
asyncfilterUpdatedManga(mangaUpdatesFoundCallback:(updates:MangaUpdates)=>void,time:Date,ids:string[]):Promise<void>{
117+
// TODO: Wait for times to be implemented.
118+
/*
117119
const options: Request = createRequestObject({
118120
url: `${BASE}`,
119121
method: 'GET'
@@ -123,5 +125,6 @@ export class VoidScans extends Source {
123125
mangaUpdatesFoundCallback(createMangaUpdates({
124126
ids: this.parser.parseUpdatedManga($, BASE, time)
125127
}));
128+
*/
126129
}
127130
}

‎src/tests/Dridespoon.test.ts‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
importcheeriofrom"cheerio";
2+
import{Dridespoon}from"../Dridespoon/Dridespoon";
3+
import{APIWrapper,Source}from"paperback-extensions-common";
4+
5+
describe("Dridespoon Tests",function(){
6+
letwrapper:APIWrapper=newAPIWrapper();
7+
letsource:Source=newDridespoon(cheerio);
8+
letchai=require("chai"),
9+
expect=chai.expect;
10+
letchaiAsPromised=require("chai-as-promised");
11+
chai.use(chaiAsPromised);
12+
13+
letmangaId="GT-giRl";
14+
15+
it("Retrieve Manga Details",async()=>{
16+
letdetails=awaitwrapper.getMangaDetails(source,mangaId);
17+
expect(
18+
details,
19+
"No results found with test-defined ID ["+mangaId+"]"
20+
).to.exist;
21+
22+
// Validate that the fields are filled
23+
letdata=details;
24+
expect(data.id,"Missing ID").to.be.not.empty;
25+
expect(data.image,"Missing Image").to.exist;
26+
expect(data.status,"Missing Status").to.exist;
27+
expect(data.titles,"Missing Titles").to.be.not.empty;
28+
expect(data.rating,"Missing Rating").to.exist;
29+
expect(data.desc,"Missing Description").to.be.not.empty;
30+
});
31+
32+
it("Get Chapters",async()=>{
33+
letdata=awaitwrapper.getChapters(source,mangaId);
34+
35+
expect(data,"No chapters present for: ["+mangaId+"]").to.not.be.empty;
36+
37+
letentry=data[0];
38+
expect(entry.id,"No ID present").to.not.be.empty;
39+
expect(entry.chapNum,"No chapter number present").to.exist;
40+
});
41+
42+
it("Get Chapter Details",async()=>{
43+
letchapters=awaitwrapper.getChapters(source,mangaId);
44+
letdata=awaitwrapper.getChapterDetails(source,mangaId,chapters[0].id);
45+
46+
expect(data,"Empty server response").to.not.be.empty;
47+
48+
expect(data.id,"Missing ID").to.be.not.empty;
49+
expect(data.mangaId,"Missing MangaID").to.be.not.empty;
50+
expect(data.pages,"No pages present").to.be.not.empty;
51+
});
52+
53+
it("Testing search",async()=>{
54+
lettestSearch=createSearchRequest({
55+
title:"GT",
56+
});
57+
58+
letsearch=awaitwrapper.searchRequest(source,testSearch);
59+
letresult=search.results[0];
60+
61+
expect(result,"No response from server").to.exist;
62+
63+
expect(result.id,"No ID found for search query").to.be.not.empty;
64+
expect(result.title,"No title").to.be.not.empty;
65+
});
66+
67+
it("Testing Home Page",async()=>{
68+
letresult=awaitwrapper.getHomePageSections(source);
69+
expect(result,"No response from server").to.exist;
70+
letitem=result[0];
71+
expect(item,"Empty response from server").to.exist;
72+
if(item.items){
73+
letsubitem=item.items[0];
74+
75+
expect(subitem.id,"No ID found for homepage item").to.not.be.empty;
76+
expect(subitem.title,"No Title found for homepage item").to.not.be.empty;
77+
expect(subitem.image,"No Image found for homepage item").to.not.be.empty;
78+
}
79+
})
80+
81+
it("Testing Notifications",async()=>{
82+
letupdates=awaitwrapper.filterUpdatedManga(source,newDate("2021-1-27"),[mangaId])
83+
expect(updates,"No server response").to.exist
84+
expect(updates,"Empty server response").to.not.be.empty
85+
expect(updates[0],"No updates").to.not.be.empty;
86+
})
87+
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp