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

Commit440820d

Browse files
committed
Add DankeMoe and MahouShoujoBu
1 parent2217de4 commit440820d

File tree

8 files changed

+419
-0
lines changed

8 files changed

+419
-0
lines changed

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ Misc. sources for scanlators and aggregators.
33

44
#Websites
55
*https://catmanga.org/
6+
*https://danke.moe/
67
*http://dridesp.ooo/n/
78
*https://glitchycomics.com/
9+
*https://mahoushoujobu.com/
810
*https://www.novelcool.com/
911
*https://rainofsnow.com/
1012
*https://raw.senmanga.com/

‎src/DankeFurs/DankeFurs.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import{SourceInfo}from"paperback-extensions-common"
2+
import{GuyaTemplate}from"../GuyaTemplate";
3+
4+
constBASE="https://danke.moe"
5+
6+
exportconstDankeFursInfo:SourceInfo={
7+
icon:"icon.png",
8+
version:"1.0.0",
9+
name:"DankeFurs",
10+
author:"PythonCoderAS",
11+
authorWebsite:"https://github.com/PythonCoderAS",
12+
description:"Extension that pulls manga from DankeFurs",
13+
language:"en",
14+
hentaiSource:false,
15+
websiteBaseURL:BASE
16+
}
17+
18+
exportclassDankeFursextendsGuyaTemplate{
19+
readonlybaseUrl:string=BASE;
20+
}

‎src/DankeFurs/includes/icon.png‎

6.3 KB
Loading

‎src/GuyaTemplate.ts‎

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/**
2+
* This is <b>not</b> a dedicated Guya.moe template repo. However, I feel that it is pointless to introduce yet another
3+
* repository for what is essentially 2-3 sources.
4+
*/
5+
6+
import{
7+
Source,
8+
Manga,
9+
Chapter,
10+
ChapterDetails,
11+
HomeSection,
12+
SearchRequest,
13+
LanguageCode,
14+
MangaStatus,
15+
MangaUpdates,
16+
PagedResults,
17+
}from"paperback-extensions-common"
18+
19+
constSPLIT_VAR="|"
20+
21+
exportabstractclassGuyaTemplateextendsSource{
22+
readonlyabstractbaseUrl:string;
23+
asyncgetMangaDetails(mangaId:string):Promise<Manga>{
24+
25+
letrequest=createRequestObject({
26+
metadata:{ mangaId},
27+
url:`${this.baseUrl}/api/get_all_series/`,
28+
method:"GET",
29+
})
30+
31+
letresponse=awaitthis.requestManager.schedule(request,1)
32+
33+
letresult=typeofresponse.data==="string" ?JSON.parse(response.data) :response.data
34+
35+
letmangas=[]
36+
for(letseriesinresult){
37+
letseriesDetails=result[series]
38+
if(mangaId.includes(seriesDetails["slug"])){
39+
mangas.push(
40+
createManga({
41+
id:seriesDetails["slug"],
42+
titles:[series],
43+
image:`${this.baseUrl}/${seriesDetails["cover"]}`,
44+
rating:5,
45+
status:MangaStatus.ONGOING,
46+
artist:seriesDetails["artist"],
47+
author:seriesDetails["author"],
48+
desc:seriesDetails["description"],
49+
})
50+
)
51+
}
52+
}
53+
54+
returnmangas[0]
55+
}
56+
57+
58+
asyncgetChapters(mangaId:string):Promise<Chapter[]>{
59+
letrequest=createRequestObject({
60+
metadata:{ mangaId},
61+
url:`${this.baseUrl}/api/series/${mangaId}/`,
62+
method:"GET",
63+
})
64+
65+
letresponse=awaitthis.requestManager.schedule(request,1)
66+
67+
letresult=typeofresponse.data==="string" ?JSON.parse(response.data) :response.data
68+
letrawChapters=result["chapters"]
69+
letgroupMap=result["groups"]
70+
71+
letchapters=[]
72+
for(letchapterinrawChapters){
73+
letchapterMetadata=rawChapters[chapter]
74+
for(letgroupinchapterMetadata["groups"]){
75+
chapters.push(
76+
createChapter({
77+
id:`${chapter}${SPLIT_VAR}${group}`,
78+
mangaId:mangaId,
79+
chapNum:Number(chapter),
80+
langCode:LanguageCode.ENGLISH,
81+
name:chapterMetadata["title"],
82+
volume:chapterMetadata["volume"],
83+
group:groupMap[group],
84+
time:newDate(
85+
Number(chapterMetadata["release_date"][group])*1000
86+
),
87+
})
88+
)
89+
}
90+
}
91+
returnchapters
92+
}
93+
94+
asyncgetChapterDetails(mangaId:string,chapterId:string):Promise<ChapterDetails>{
95+
96+
constrequest=createRequestObject({
97+
url:`${this.baseUrl}/api/series/${mangaId}/`,
98+
method:"GET",
99+
})
100+
101+
constdata=awaitthis.requestManager.schedule(request,1)
102+
103+
letresult=typeofdata.data==="string" ?JSON.parse(data.data) :data.data
104+
letrawChapters=result["chapters"]
105+
let[chapter,group]=chapterId.split(SPLIT_VAR)
106+
returncreateChapterDetails({
107+
id:chapterId,
108+
longStrip:false,
109+
mangaId:mangaId,
110+
pages:rawChapters[chapter]["groups"][group].map(
111+
(page:string)=>
112+
`${this.baseUrl}/media/manga/${mangaId}/chapters/${rawChapters[chapter]["folder"]}/${group}/${page}`
113+
),
114+
})
115+
}
116+
117+
asyncsearchRequest(searchQuery:SearchRequest,metadata:any):Promise<PagedResults>{
118+
119+
constrequest=createRequestObject({
120+
url:`${this.baseUrl}/api/get_all_series/`,
121+
method:"GET",
122+
})
123+
124+
constdata=awaitthis.requestManager.schedule(request,1)
125+
126+
letresult=typeofdata.data==="string" ?JSON.parse(data.data) :data.data
127+
letquery=searchQuery.title??''
128+
129+
letfilteredResults=Object.keys(result).filter((e)=>
130+
e.toLowerCase().includes(query.toLowerCase())
131+
)
132+
133+
lettiles=filteredResults.map((series)=>{
134+
letseriesMetadata=result[series]
135+
returncreateMangaTile({
136+
id:seriesMetadata["slug"],
137+
image:`${this.baseUrl}/${seriesMetadata["cover"]}`,
138+
title:createIconText({text:series}),
139+
})
140+
})
141+
142+
returncreatePagedResults({
143+
results:tiles
144+
})
145+
}
146+
147+
asyncgetHomePageSections(sectionCallback:(section:HomeSection)=>void):Promise<void>{
148+
149+
// Send the empty homesection back so the app can preload the section
150+
varhomeSection=createHomeSection({id:"all_guya",title:"ALL GUYA"})
151+
sectionCallback(homeSection)
152+
153+
constrequest=createRequestObject({
154+
url:`${this.baseUrl}/api/get_all_series/`,
155+
method:"GET"
156+
})
157+
158+
constdata=awaitthis.requestManager.schedule(request,1)
159+
160+
letresult=typeofdata.data==="string" ?JSON.parse(data.data) :data.data
161+
162+
letmangas=[]
163+
for(letseriesinresult){
164+
letseriesDetails=result[series]
165+
mangas.push(
166+
createMangaTile({
167+
id:seriesDetails["slug"],
168+
image:`${this.baseUrl}/${seriesDetails["cover"]}`,
169+
title:createIconText({text:series}),
170+
})
171+
)
172+
}
173+
homeSection.items=mangas
174+
175+
sectionCallback(homeSection)
176+
}
177+
178+
asyncfilterUpdatedManga(mangaUpdatesFoundCallback:(updates:MangaUpdates)=>void,time:Date,ids:string[]):Promise<void>{
179+
180+
constrequest=createRequestObject({
181+
url:`${this.baseUrl}/api/get_all_series/`,
182+
method:"GET"
183+
})
184+
185+
constdata=awaitthis.requestManager.schedule(request,1)
186+
187+
letresult=typeofdata.data==="string" ?JSON.parse(data.data) :data.data
188+
189+
letfoundIds:string[]=[]
190+
191+
for(letseriesinresult){
192+
constseriesDetails=result[series]
193+
constseriesUpdated=newDate(seriesDetails["last_updated"]*1000)
194+
constid=seriesDetails["slug"];
195+
if(seriesUpdated>=time&&ids.includes(id)){
196+
foundIds.push(id);
197+
}
198+
}
199+
mangaUpdatesFoundCallback(createMangaUpdates({ids:foundIds}))
200+
}
201+
202+
getMangaShareUrl(mangaId:string){
203+
return`${this.baseUrl}/read/manga/${mangaId}/`
204+
}
205+
}

‎src/MahouShoujoBu/MahouShoujoBu.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import{SourceInfo}from"paperback-extensions-common"
2+
import{GuyaTemplate}from"../GuyaTemplate";
3+
4+
constBASE="https://mahoushoujobu.com/"
5+
6+
exportconstMahouShoujoBuInfo:SourceInfo={
7+
icon:"icon.png",
8+
version:"1.0.0",
9+
name:"MahouShoujoBu",
10+
author:"PythonCoderAS",
11+
authorWebsite:"https://github.com/PythonCoderAS",
12+
description:"Extension that pulls manga from MahouShoujoBu",
13+
language:"en",
14+
hentaiSource:false,
15+
websiteBaseURL:BASE
16+
}
17+
18+
exportclassMahouShoujoBuextendsGuyaTemplate{
19+
readonlybaseUrl:string=BASE;
20+
}
23.1 KB
Loading

‎src/tests/DankeFurs.test.ts‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
importcheeriofrom"cheerio";
2+
import{DankeFurs}from"../DankeFurs/DankeFurs";
3+
import{APIWrapper,Source}from"paperback-extensions-common";
4+
5+
describe("DankeFurs Tests",function(){
6+
varwrapper:APIWrapper=newAPIWrapper();
7+
varsource:Source=newDankeFurs(cheerio);
8+
varchai=require("chai"),
9+
expect=chai.expect;
10+
varchaiAsPromised=require("chai-as-promised");
11+
chai.use(chaiAsPromised);
12+
13+
varmangaId="kazu-megu";
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.be.not.empty;
26+
expect(data.status,"Missing Status").to.exist;
27+
expect(data.author,"Missing Author").to.be.not.empty;
28+
expect(data.desc,"Missing Description").to.be.not.empty;
29+
expect(data.titles,"Missing Titles").to.be.not.empty;
30+
expect(data.rating,"Missing Rating").to.exist;
31+
});
32+
33+
it("Get Chapters",async()=>{
34+
letdata=awaitwrapper.getChapters(source,mangaId);
35+
36+
expect(data,"No chapters present for: ["+mangaId+"]").to.not.be.empty;
37+
38+
letentry=data[0];
39+
expect(entry.id,"No ID present").to.not.be.empty;
40+
expect(entry.time,"No date present").to.exist;
41+
expect(entry.name,"No title available").to.not.be.empty;
42+
expect(entry.chapNum,"No chapter number present").to.exist;
43+
expect(entry.volume,"No volume data available").to.not.be.empty;
44+
});
45+
46+
it("Get Chapter Details",async()=>{
47+
letchapters=awaitwrapper.getChapters(source,mangaId);
48+
letdata=awaitwrapper.getChapterDetails(source,mangaId,chapters[0].id);
49+
50+
expect(data,"No server response").to.exist;
51+
expect(data,"Empty server response").to.not.be.empty;
52+
53+
expect(data.id,"Missing ID").to.be.not.empty;
54+
expect(data.mangaId,"Missing MangaID").to.be.not.empty;
55+
expect(data.pages,"No pages present").to.be.not.empty;
56+
});
57+
58+
it("Testing search",async()=>{
59+
lettestSearch=createSearchRequest({
60+
title:"kazu",
61+
});
62+
63+
letsearch=awaitwrapper.searchRequest(source,testSearch);
64+
letresult=search.results[0];
65+
66+
expect(result,"No response from server").to.exist;
67+
68+
expect(result.id,"No ID found for search query").to.be.not.empty;
69+
expect(result.image,"No image found for search").to.be.not.empty;
70+
expect(result.title,"No title").to.be.not.null;
71+
expect(result.subtitleText,"No subtitle text").to.be.not.null;
72+
});
73+
74+
it("Testing Home-Page aquisition",async()=>{
75+
lethomePages=awaitwrapper.getHomePageSections(source);
76+
expect(homePages,"No response from server").to.exist;
77+
});
78+
79+
it("Testing Notifications",async()=>{
80+
constupdates=awaitwrapper.filterUpdatedManga(source,newDate("2021-03-26"),[mangaId]);
81+
82+
expect(updates,"No server response").to.exist;
83+
expect(updates,"Empty server response").to.not.be.empty;
84+
expect(updates[0].ids,"No updates").to.not.be.empty;
85+
});
86+
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp