mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 02:41:39 +00:00
Merge pull request #212 from Swakshan/anime/dramacool
New Source: Dramacool
This commit is contained in:
353
javascript/anime/src/all/dramacool.js
Normal file
353
javascript/anime/src/all/dramacool.js
Normal file
@@ -0,0 +1,353 @@
|
||||
const mangayomiSources = [{
|
||||
"name": "Dramacool",
|
||||
"lang": "all",
|
||||
"baseUrl": "https://dramacool.com.tr",
|
||||
"apiUrl": "",
|
||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://dramacool.com.tr",
|
||||
"typeSource": "multi",
|
||||
"itemType": 1,
|
||||
"version": "1.0.0",
|
||||
"pkgPath": "anime/src/all/dramacool.js"
|
||||
}];
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
|
||||
getHeaders(url) {
|
||||
return {
|
||||
'Referer': url,
|
||||
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36"
|
||||
}
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return new SharedPreferences().get(key);
|
||||
}
|
||||
|
||||
getBaseUrl() {
|
||||
return this.source.baseUrl;
|
||||
}
|
||||
|
||||
async request(slug) {
|
||||
const baseUrl = this.getBaseUrl()
|
||||
var url = `${baseUrl}${slug}`
|
||||
var res = await new Client().get(url, this.getHeaders(baseUrl));
|
||||
var doc = new Document(res.body);
|
||||
return doc
|
||||
}
|
||||
|
||||
async getList(slug) {
|
||||
var body = await this.request(slug);
|
||||
var list = []
|
||||
var hasNextPage = body.selectFirst("a.next.page-numbers").text.length > 0 ? true : false;
|
||||
var items = body.select(".switch-block.list-episode-item > li")
|
||||
items.forEach(item => {
|
||||
var a = item.selectFirst("a")
|
||||
var link = a.getHref.replace(this.getBaseUrl(), "")
|
||||
var imageUrl = a.selectFirst("img").getSrc
|
||||
var name = a.selectFirst("h3").text
|
||||
|
||||
list.push({ name, link, imageUrl })
|
||||
|
||||
})
|
||||
|
||||
return { list, hasNextPage };
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
var slug = "/most-popular-drama"
|
||||
return await this.getList(`${slug}/page/${page}/`)
|
||||
}
|
||||
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
var slug = this.getPreference("dramacool_latest_list")
|
||||
return await this.getList(`/${slug}/page/${page}/`)
|
||||
}
|
||||
|
||||
statusFromString(status) {
|
||||
return {
|
||||
"Ongoing": 0,
|
||||
"Completed": 1,
|
||||
}[status] ?? 5;
|
||||
}
|
||||
|
||||
async search(query, page, filters) {
|
||||
var slug = `/page/${page}/?type=movies&s=${query}`
|
||||
return await this.getList(slug)
|
||||
}
|
||||
|
||||
formatReleaseDate(str) {
|
||||
var timeSplit = str.split(" ")
|
||||
var t = parseInt(timeSplit[0])
|
||||
var unit = timeSplit[1]
|
||||
|
||||
var mins = 0
|
||||
var mons = 0
|
||||
if (unit.includes('minute')) {
|
||||
mins = t;
|
||||
} else if (unit.includes('hour')) {
|
||||
mins = t * 60;
|
||||
} else if (unit.includes('day')) {
|
||||
mins = t * 60 * 24;
|
||||
} else if (unit.includes('week')) {
|
||||
mins = t * 60 * 24 * 7;
|
||||
} else if (unit.includes('month')) {
|
||||
mons = t;
|
||||
}
|
||||
var now = new Date();
|
||||
now.setMinutes(now.getMinutes() - mins)
|
||||
now.setMinutes(now.getMonth() - mons)
|
||||
var pastDate = new Date(now);
|
||||
return "" + pastDate.valueOf();
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
if (url.includes("-episode")) {
|
||||
url = '/series' + url.split("-episode")[0] + "/"
|
||||
} else if (url.includes("-full-movie")) {
|
||||
url = '/series' + url.split("-full-movie")[0] + "/"
|
||||
}
|
||||
|
||||
var body = await this.request(url);
|
||||
var infos = body.select(".info > p")
|
||||
|
||||
var name = body.selectFirst("h1").text.trim()
|
||||
var imageUrl = body.selectFirst(".img").selectFirst("img").getSrc
|
||||
var isDescription = infos[1].text.includes("Description")
|
||||
var description = isDescription ? infos[2].text.trim() : ""
|
||||
var link = `${this.getBaseUrl()}${url}`
|
||||
var statusIndex = infos.at(-3).text.includes("Status:") ? -3 : -2
|
||||
var status = this.statusFromString(infos.at(statusIndex).selectFirst("a").text)
|
||||
var genre = []
|
||||
infos.at(-1).select("a").forEach(a => genre.push(a.text.trim()))
|
||||
|
||||
var chapters = []
|
||||
var epLists = body.select("ul.list-episode-item-2.all-episode > li")
|
||||
for (var ep of epLists) {
|
||||
var a = ep.selectFirst('a')
|
||||
var epLink = a.getHref.replace(this.getBaseUrl(), "")
|
||||
var epName = a.selectFirst("h3").text.replace(name + " ", "")
|
||||
var scanlator = a.selectFirst("span.type").text
|
||||
var dateUpload = this.formatReleaseDate(a.selectFirst("span.time").text)
|
||||
chapters.push({
|
||||
name: epName,
|
||||
url: epLink,
|
||||
scanlator,
|
||||
dateUpload
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return { name, imageUrl, description, link, status, genre, chapters }
|
||||
}
|
||||
|
||||
async splitStreams(streams, server) {
|
||||
var pref = this.getPreference("dramacool_split_stream_quality");
|
||||
if (!pref) return streams
|
||||
var autoStream = streams[0]
|
||||
var autoStreamUrl = autoStream.url
|
||||
var hdr = autoStream.headers
|
||||
var hostUrl = ""
|
||||
if (server == "Asianload") {
|
||||
hostUrl = autoStreamUrl.substring(0, autoStreamUrl.indexOf("/media"))
|
||||
} else {
|
||||
hostUrl = autoStreamUrl.substring(0, autoStreamUrl.indexOf("master.m3u8"))
|
||||
}
|
||||
|
||||
|
||||
var response = await new Client().get(autoStreamUrl, hdr)
|
||||
var body = response.body;
|
||||
var lines = body.split('\n');
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('#EXT-X-STREAM-INF:')) {
|
||||
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
||||
resolution = `${server} - ${resolution}`
|
||||
var m3u8Url = lines[i + 1].trim();
|
||||
m3u8Url = hostUrl + m3u8Url
|
||||
streams.push({
|
||||
url: m3u8Url,
|
||||
originalUrl: m3u8Url,
|
||||
quality: resolution,
|
||||
headers: hdr
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return streams
|
||||
}
|
||||
|
||||
decodeBase64(f) {
|
||||
var g = {},
|
||||
b = 65,
|
||||
d = 0,
|
||||
a, c = 0,
|
||||
h, e = "",
|
||||
k = String.fromCharCode,
|
||||
l = f.length;
|
||||
for (a = ""; 91 > b;) a += k(b++);
|
||||
a += a.toLowerCase() + "0123456789+/";
|
||||
for (b = 0; 64 > b; b++) g[a.charAt(b)] = b;
|
||||
for (a = 0; a < l; a++)
|
||||
for (b = g[f.charAt(a)], d = (d << 6) + b, c += 6; 8 <= c;)((h = d >>> (c -= 8) & 255) || a < l - 2) && (e += k(h));
|
||||
return e
|
||||
};
|
||||
|
||||
async extractDramacoolEmbed(doc) {
|
||||
var streams = []
|
||||
var script = doc.select('script').at(-2)
|
||||
var unpack = unpackJs(script.text)
|
||||
|
||||
var skey = 'hls2":"'
|
||||
var eKey = '"};jwplayer'
|
||||
var start = unpack.indexOf(skey) + skey.length
|
||||
var end = unpack.indexOf(eKey, start)
|
||||
var track = unpack.substring(start, end)
|
||||
|
||||
streams.push({
|
||||
url: track,
|
||||
originalUrl: track,
|
||||
quality: "Dramacool - Auto",
|
||||
headers: this.getHeaders("https://dramacool.men/")
|
||||
});
|
||||
|
||||
streams = await this.splitStreams(streams, "Dramacool")
|
||||
|
||||
return streams
|
||||
}
|
||||
|
||||
async extractAsianLoadEmbed(doc) {
|
||||
var streams = []
|
||||
var script = doc.select('script').at(-2)
|
||||
var unpack = script.text
|
||||
|
||||
// tracks
|
||||
var skey = '|image|'
|
||||
var eKey = '|'
|
||||
var start = unpack.indexOf(skey) + skey.length
|
||||
var end = unpack.indexOf(eKey, start)
|
||||
var track = unpack.substring(start, end)
|
||||
var streamUrl = this.decodeBase64(track)
|
||||
|
||||
// subs
|
||||
eKey = "|default|"
|
||||
var end = unpack.indexOf(eKey)
|
||||
var subs = []
|
||||
if (end != -1) {
|
||||
skey = "|type|"
|
||||
var start = unpack.indexOf(skey) + skey.length
|
||||
var subTracks = unpack.substring(start, end).split("|")
|
||||
subs.push({
|
||||
file: this.decodeBase64(subTracks[1]),
|
||||
label: subTracks[0]
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
streams.push({
|
||||
url: streamUrl,
|
||||
originalUrl: streamUrl,
|
||||
quality: "Asianload - Auto",
|
||||
subtitles: subs,
|
||||
headers: this.getHeaders("https://asianload.cfd/")
|
||||
});
|
||||
|
||||
// Download url
|
||||
skey = '|_blank|'
|
||||
eKey = '|'
|
||||
start = unpack.indexOf(skey) + skey.length
|
||||
end = unpack.indexOf(eKey, start)
|
||||
track = unpack.substring(start, end)
|
||||
var downUrl = this.decodeBase64(track)
|
||||
|
||||
streams.push({
|
||||
url: downUrl,
|
||||
originalUrl: downUrl,
|
||||
quality: "Asianload - Direct download",
|
||||
headers: this.getHeaders("https://asianload.cfd/")
|
||||
});
|
||||
|
||||
|
||||
streams = await this.splitStreams(streams, "Asianload")
|
||||
|
||||
return streams
|
||||
}
|
||||
|
||||
// Sorts streams based on user preference.
|
||||
async sortStreams(streams) {
|
||||
var sortedStreams = [];
|
||||
|
||||
var copyStreams = streams.slice()
|
||||
var pref = this.getPreference("dramacool_video_resolution");
|
||||
for (var i in streams) {
|
||||
var stream = streams[i];
|
||||
if (stream.quality.indexOf(pref) > -1) {
|
||||
sortedStreams.push(stream);
|
||||
var index = copyStreams.indexOf(stream);
|
||||
if (index > -1) {
|
||||
copyStreams.splice(index, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [...sortedStreams, ...copyStreams]
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var res = await this.request(url)
|
||||
var iframe = res.selectFirst("iframe").attr("src").trim()
|
||||
if (iframe == "") {
|
||||
throw new Error("No iframe found")
|
||||
}
|
||||
|
||||
var streams = []
|
||||
|
||||
res = await new Client().get(iframe)
|
||||
var doc = new Document(res.body);
|
||||
|
||||
if (iframe.includes("//dramacool")) {
|
||||
streams = await this.extractDramacoolEmbed(doc)
|
||||
} else if (iframe.includes("//asianload")) {
|
||||
streams = await this.extractAsianLoadEmbed(doc)
|
||||
}
|
||||
|
||||
return this.sortStreams(streams)
|
||||
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: 'dramacool_latest_list',
|
||||
listPreference: {
|
||||
title: 'Preferred latest list',
|
||||
summary: 'Choose which type of content to be shown "Lastest"',
|
||||
valueIndex: 0,
|
||||
entries: ["Drama", "Movie", "KShow"],
|
||||
entryValues: ["recently-added-drama", "recently-added-movie", "recently-added-kshow"]
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'dramacool_split_stream_quality',
|
||||
switchPreferenceCompat: {
|
||||
title: 'Split stream into different quality streams',
|
||||
summary: "Split stream Auto into 360p/720p/1080p",
|
||||
value: true
|
||||
}
|
||||
}, {
|
||||
key: 'dramacool_video_resolution',
|
||||
listPreference: {
|
||||
title: 'Preferred video resolution',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Auto", "Direct download", "720p", "480", "360p"],
|
||||
entryValues: ["Auto", "download", "720", "480", "360"]
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user