mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 19:01:15 +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