From bdfe9bf535c31b1f4b081ed5139005c8d951e41d Mon Sep 17 00:00:00 2001 From: Sravan Balaji Date: Tue, 9 Jul 2024 18:15:14 -0400 Subject: [PATCH] Custom Mangal Sources - Add custom mangal lua scrapers - Change download filepath to use tilde - Remove list of default sources to use (ask every time instead) --- README.org | 4 +- mangal/.config/mangal/mangal.toml | 4 +- mangal/.config/mangal/sources/AsuraScans.lua | 99 +++++++++++ mangal/.config/mangal/sources/ComicK.lua | 158 ++++++++++++++++++ mangal/.config/mangal/sources/FlameScans.lua | 129 ++++++++++++++ .../.config/mangal/sources/LuminousScans.lua | 103 ++++++++++++ .../.config/mangal/sources/MangaKakalot.lua | 115 +++++++++++++ mangal/.config/mangal/sources/MangaKatana.lua | 109 ++++++++++++ mangal/.config/mangal/sources/Manganelo.lua | 103 ++++++++++++ mangal/.config/mangal/sources/Mangasee.lua | 148 ++++++++++++++++ mangal/.config/mangal/sources/Mangatoto.lua | 113 +++++++++++++ mangal/.config/mangal/sources/ManhuaUs.lua | 107 ++++++++++++ mangal/.config/mangal/sources/Readmanga.lua | 141 ++++++++++++++++ mangal/.config/mangal/sources/Toonily.lua | 105 ++++++++++++ 14 files changed, 1434 insertions(+), 4 deletions(-) create mode 100755 mangal/.config/mangal/sources/AsuraScans.lua create mode 100755 mangal/.config/mangal/sources/ComicK.lua create mode 100755 mangal/.config/mangal/sources/FlameScans.lua create mode 100755 mangal/.config/mangal/sources/LuminousScans.lua create mode 100755 mangal/.config/mangal/sources/MangaKakalot.lua create mode 100755 mangal/.config/mangal/sources/MangaKatana.lua create mode 100755 mangal/.config/mangal/sources/Manganelo.lua create mode 100755 mangal/.config/mangal/sources/Mangasee.lua create mode 100755 mangal/.config/mangal/sources/Mangatoto.lua create mode 100755 mangal/.config/mangal/sources/ManhuaUs.lua create mode 100755 mangal/.config/mangal/sources/Readmanga.lua create mode 100755 mangal/.config/mangal/sources/Toonily.lua diff --git a/README.org b/README.org index 1ea4bf5..b8bbb9a 100644 --- a/README.org +++ b/README.org @@ -8041,7 +8041,7 @@ create_volume_dir = false # Default sources to use. (string array) # Will prompt if not set. # Type "mangal sources list" to show available sources -default_sources = [ "Mangadex", "Manganelo", "Manganato", "Mangapill", "AsuraScans", "FlameScans", "LuminousScans", "Manganelo", "Mangasee", "Readmanga" ] +default_sources = [] # Whether to download manga cover or not (bool) download_cover = true @@ -8050,7 +8050,7 @@ download_cover = true # Absolute or relative. # You can also use tilde (~) to refer to your home directory or use env variables. # Examples: ~/... or $HOME/... or ${MANGA_PATH}-mangal -path = "/home/sravan/Downloads" +path = "~/Downloads" # If chapter is already downloaded, read it instead of downloading it to temp (bool) read_downloaded = false diff --git a/mangal/.config/mangal/mangal.toml b/mangal/.config/mangal/mangal.toml index 13aa7a3..f6e1757 100644 --- a/mangal/.config/mangal/mangal.toml +++ b/mangal/.config/mangal/mangal.toml @@ -40,7 +40,7 @@ create_volume_dir = false # Default sources to use. (string array) # Will prompt if not set. # Type "mangal sources list" to show available sources -default_sources = [ "Mangadex", "Manganelo", "Manganato", "Mangapill", "AsuraScans", "FlameScans", "LuminousScans", "Manganelo", "Mangasee", "Readmanga" ] +default_sources = [] # Whether to download manga cover or not (bool) download_cover = true @@ -49,7 +49,7 @@ download_cover = true # Absolute or relative. # You can also use tilde (~) to refer to your home directory or use env variables. # Examples: ~/... or $HOME/... or ${MANGA_PATH}-mangal -path = "/home/sravan/Downloads" +path = "~/Downloads" # If chapter is already downloaded, read it instead of downloading it to temp (bool) read_downloaded = false diff --git a/mangal/.config/mangal/sources/AsuraScans.lua b/mangal/.config/mangal/sources/AsuraScans.lua new file mode 100755 index 0000000..998ba8b --- /dev/null +++ b/mangal/.config/mangal/sources/AsuraScans.lua @@ -0,0 +1,99 @@ +-------------------------------------- +-- @name AsuraScans +-- @url https://www.asurascans.com +-- @author metafates +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Headless = require('headless') +Time = require("time") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Browser = Headless.browser() +Page = Browser:page() +Base = "https://www.asurascans.com" +Delay = 1 -- seconds +--- END VARIABLES --- + + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + local url = Base .. "/?s=" .. query + Page:navigate(url) + Time.sleep(Delay) + + local mangas = {} + + for i, v in ipairs(Page:elements(".bsx > a")) do + local manga = { url = v:attribute('href'), name = v:attribute('title') } + mangas[i + 1] = manga + end + + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + Page:navigate(mangaURL) + Time.sleep(Delay) + + local chapters = {} + + for _, v in ipairs(Page:elements("#chapterlist > ul li")) do + local n = tonumber(v:attribute("data-num")) + local elem = Html.parse(v:html()) + local link = elem:find("a"):first() + + local chapter = { url = link:attr("href"), name = link:find("span"):first():text() } + + if n ~= nil then + chapters[n] = chapter + end + end + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + Page:navigate(chapterURL) + Time.sleep(Delay) + + local pages = {} + for i, v in ipairs(Page:elements("#readerarea p img")) do + local p = { index = i, url = v:attribute("src") } + pages[i + 1] = p + end + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/ComicK.lua b/mangal/.config/mangal/sources/ComicK.lua new file mode 100755 index 0000000..526c973 --- /dev/null +++ b/mangal/.config/mangal/sources/ComicK.lua @@ -0,0 +1,158 @@ +------------------------------ +-- @name ComicK +-- @url https://comick.io +-- @author Sravan Balaji +-- @license MIT +------------------------------ + + + + +----- IMPORTS ----- +Http = require('http') +Json = require('json') +-- inspect = require('inspect') +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Debug = false +Client = Http.client({ timeout = 20, insecure_ssl = true, debug=Debug }) +ApiBase = 'https://api.comick.fun' +ImageBase = 'https://meo.comick.pictures' +Limit = 50 +Lang = 'en' -- Language: en = english, fr = french, etc. +Order = 1 -- Chapter Order: 0 = descending, 1 = ascending +--- END VARIABLES --- + + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + local request_url = ApiBase .. '/v1.0/search/?tachiyomi=true&q=' .. query + local request = Http.request('GET', request_url) + local result = Client:do_request(request) + local result_body = Json.decode(result['body']) + + local mangas = {} + local i = 1 + + for _, val in pairs(result_body) do + local title = val['title'] + + if title ~= nil then + local hid = val['hid'] + local link = ApiBase .. '/comic/' .. tostring(hid) .. '/chapters' + local manga = { url = link, name = title } + + mangas[i] = manga + i = i + 1 + end + end + + return mangas +end + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request_url = mangaURL .. '?tachiyomi=true&lang=' .. Lang .. '&limit=' .. Limit .. '&chap-order=' .. Order + local chapters = {} + local i = 1 + + local request = Http.request('GET', request_url) + local result = Client:do_request(request) + local result_body = Json.decode(result['body']) + local num_chapters = result_body['total'] + local num_pages = math.ceil(num_chapters / Limit) + + for j = 1, num_pages do + request = Http.request('GET', request_url .. '&page=' .. j) + result = Client:do_request(request) + result_body = Json.decode(result['body']) + + for _, val in pairs(result_body['chapters']) do + local hid = val['hid'] + local num = val['chap'] + if num == nil then + num = 0 + end + + local volume = tostring(val['vol']) + if volume ~= "nil" then + volume = "Vol." .. volume + else + volume = "" + end + local title = val['title'] + local chap = 'Chapter ' .. tostring(num) + local group_name = val['group_name'] + + if title then + chap = chap .. ': ' .. tostring(title) + end + + if group_name then + chap = chap .. ' [' + for key, group in pairs(group_name) do + if key ~= 1 then + chap = chap .. ', ' + end + + chap = chap .. tostring(group) + end + chap = chap .. ']' + end + + local link = ApiBase .. '/chapter/' .. tostring(hid) + local chapter = { url = link, name = chap, volume = volume } + + chapters[i] = chapter + i = i + 1 + end + end + + return chapters +end + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request('GET', chapterURL) + local result = Client:do_request(request) + local result_body = Json.decode(result['body']) + local chapter_table = result_body['chapter'] + + local pages = {} + local i = 1 + + for key, val in pairs(chapter_table['md_images']) do + local ind = key + local link = ImageBase .. '/' .. val['b2key'] + local page = { url = link, index = ind } + + pages[i] = page + i = i + 1 + end + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua + diff --git a/mangal/.config/mangal/sources/FlameScans.lua b/mangal/.config/mangal/sources/FlameScans.lua new file mode 100755 index 0000000..f91cd86 --- /dev/null +++ b/mangal/.config/mangal/sources/FlameScans.lua @@ -0,0 +1,129 @@ +-------------------------------------- +-- @name FlameScans +-- @url https://www.flamescans.org +-- @author metafates & belphemur +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Headless = require('headless') +Time = require("time") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Browser = Headless.browser() +Page = Browser:page() +Base = "https://flamescans.org" +Delay = 1 -- seconds +--- END VARIABLES --- + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = string.gsub(query, "’s", "") + query = string.gsub(query, "'s", "") + local url = Base .. "/?s=" .. query + Page:navigate(url) + Time.sleep(Delay) + + local mangas = {} + + for _, v in ipairs(Page:elements(".bsx > a")) do + local manga = { url = v:attribute('href'), name = v:attribute('title'), translator = "FlameScans" } + table.insert(mangas, manga) + end + + return mangas +end + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + Page:navigate(mangaURL) + Time.sleep(Delay) + + local chapters = {} + local date_pattern = "(%w+)%s+(%d+),%s+(%d+)" + local month_names = { + January = "01", February = "02", March = "03", April = "04", + May = "05", June = "06", July = "07", August = "08", + September = "09", October = "10", November = "11", December = "12", + } + + for _, v in ipairs(Page:elements("#chapterlist > ul li")) do + local n = tonumber(v:attribute("data-num")) + local elem = Html.parse(v:html()) + local link = elem:find("a"):first() + local chapter_date = link:find(".chapterdate"):first():text() + local iso_date = "" + + if chapter_date ~= nil then + local month_name, day, year = chapter_date:match(date_pattern) + local month = month_names[month_name] + + local timestamp = os.time({year=year, month=month, day=day}) + iso_date = os.date("%Y-%m-%d", timestamp) + end + + local chapter = { url = link:attr("href"), name = string.gsub(link:find("span"):first():text():sub(2),"\n"," "), chapter_date=iso_date } + + repeat + -- Skip this chapter if the number is nil + if n == nil then + break + end + + -- Skip this chapter if the number is a floating-point number + if math.floor(n) ~= n then + break + end + + -- Skip this chapter if the number is negative + if n < 1 then + break + end + + -- Add this chapter to the list of chapters + chapters[n] = chapter + until true + end + + return chapters +end + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + Page:navigate(chapterURL) + Time.sleep(Delay) + + local pages = {} + for i, v in ipairs(Page:elements("#readerarea p img")) do + local p = { index = i, url = v:attribute("src") } + pages[i + 1] = p + end + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/LuminousScans.lua b/mangal/.config/mangal/sources/LuminousScans.lua new file mode 100755 index 0000000..08ed719 --- /dev/null +++ b/mangal/.config/mangal/sources/LuminousScans.lua @@ -0,0 +1,103 @@ +------------------------------------- +-- @name LuminousScans +-- @url https://luminousscans.com +-- @author metafates +-- @license MIT +------------------------------------- + + + + +----- IMPORTS ----- +Http = require("http") +Headless = require("headless") +Html = require("html") +Time = require("time") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Browser = Headless.browser() +Page = Browser:page() +Base = "https://luminousscans.com" +--- END VARIABLES --- + + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + local request = Http.request("GET", Base .. "/?s=" .. query) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local mangas = {} + + doc:find(".bsx > a"):each(function(i, s) + local manga = { url = s:attr("href"), name = s:attr("title") } + mangas[i+1] = manga + end) + + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + + doc:find("#chapterlist ul li"):each(function(_, s) + local n, _ = s:attr("data-num") + local index = tonumber(n) + local url = s:find("a"):first():attr("href") + local name = s:find("span"):first():text() + + local chapter = { url = url, name = name } + if index == nil then + return + end + + chapters[index] = chapter + end) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + Page:navigate(chapterURL) + Time.sleep(1) + + local pages = {} + + for i, v in ipairs(Page:elements("#readerarea p > img")) do + pages[i+1] = { index = i, url = v:attribute("src") } + end + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/MangaKakalot.lua b/mangal/.config/mangal/sources/MangaKakalot.lua new file mode 100755 index 0000000..ce09ba9 --- /dev/null +++ b/mangal/.config/mangal/sources/MangaKakalot.lua @@ -0,0 +1,115 @@ +-------------------------------------- +-- @name MangaKakalot +-- @url https://www.mangakakalot.is/ +-- @author mpiva +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Time = require("time") +Http = require("http") +HttpUtil = require("http_util") + +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Base = "https://www.mangakakalot.is" +Delay = 1 -- seconds +--- END VARIABLES --- + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = query:gsub("’","'") + local url = Base .. "/ajax/manga/search-suggest?keyword=" .. HttpUtil.query_escape(query) + local request = Http.request("GET", url) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local mangas = {} + doc:find(".ss-item"):each(function (i, r) + local url = r:attr("href") + local s = r:find(".manga-name"):first() + local chaps = Base .. "/ajax/manga/list-chapter-volume?id=" .. basename(url) + local manga = { name = trim(s:text():gsub("’","'")), url = chaps } + mangas[i+1] = manga + end) + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + local doc2 = doc:find("#list-chapter-en"):first() + doc2:find("a"):each(function (i, s) + local chapter = { name = trim(s:text()), url = Base .. s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request("GET", chapterURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local pages = {} + local element = doc:find("#reading"):first() + local id = element:attr("data-reading-id") + local chap = element:attr("data-reading-type") + + request = Http.request("GET", Base .. "/ajax/manga/images?id=" .. id .. "&type=" .. chap) + result = Client:do_request(request) + doc = Html.parse(result.body) + doc:find(".card-wrap"):each(function (i, s) + local p = { index = i, url = trim(s:attr("data-url"):gsub("[\n\r\t]","")) } + pages[i + 1] = p + end) + + return pages +end + + + +----- HELPERS ----- +function basename(path) + return path:sub(path:find("-[^-]*$") + 1) + end +function trim(s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +function Reverse(t) + + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end diff --git a/mangal/.config/mangal/sources/MangaKatana.lua b/mangal/.config/mangal/sources/MangaKatana.lua new file mode 100755 index 0000000..6143356 --- /dev/null +++ b/mangal/.config/mangal/sources/MangaKatana.lua @@ -0,0 +1,109 @@ +-------------------------------------- +-- @name MangaKatana +-- @url https://mangakatana.com +-- @author mpiva +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Time = require("time") +Http = require("http") +HttpUtil = require("http_util") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Base = "https://mangakatana.com" +Delay = 1 -- seconds +--- END VARIABLES --- + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = query:gsub("’","'") + local forms = "s=" .. HttpUtil.query_escape(query) .. "&search_by=book_name"; + local request = Http.request("POST", Base, forms) + request:header_set("Content-Type", "application/x-www-form-urlencoded") + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local mangas = {} + + doc:find(".text > a"):each(function (i, s) + local manga = { name = s:text():gsub("’","'"), url = s:attr("href") } + mangas[i+1] = manga + end) + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + local doc2 = doc:find(".uk-table"):first() + doc2:find(".chapter > a"):each(function (i, s) + local chapter = { name = s:text(), url = s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request("GET", chapterURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local pages = {} + local text= doc:find("body"):first():text() + local v1 = text:find("thzq=") + local v2 = text:find(";function", v1) + local list = string.sub(text, v1+6, v2-2) + local cnt = 0; + for word in string.gmatch(list, '([^,]+)') do + local p = { index = cnt, url = string.sub(word,2,word:len()-1) } + pages[cnt + 1] = p + cnt = cnt +1 + end + + return pages +end + + + + + +----- HELPERS ----- + + +function Reverse(t) + + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end diff --git a/mangal/.config/mangal/sources/Manganelo.lua b/mangal/.config/mangal/sources/Manganelo.lua new file mode 100755 index 0000000..ace3ea9 --- /dev/null +++ b/mangal/.config/mangal/sources/Manganelo.lua @@ -0,0 +1,103 @@ +---------------------------------------- +-- @name Manganelo +-- @url https://m.manganelo.com/wwww +-- @author metafates +-- @license MIT +---------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Http = require("http") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Base = "https://ww5.manganelo.tv" +--- END VARIABLES --- + + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + local request = Http.request("GET", Base .. "/search/" .. query) + local result = Client:do_request(request) + + local doc = Html.parse(result.body) + local mangas = {} + + doc:find(".item-title"):each(function (i, s) + local manga = { name = s:text(), url = Base .. s:attr("href") } + mangas[i+1] = manga + end) + + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + + doc:find(".chapter-name"):each(function (i, s) + local chapter = { name = s:text(), url = Base .. s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request("GET", chapterURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local pages = {} + + doc:find(".container-chapter-reader img"):each(function (i, s) + local page = { index = i, url = s:attr("data-src") } + pages[i+1] = page + end) + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +function Reverse(t) + local n = #t + local i = 1 + while i < n do + t[i],t[n] = t[n],t[i] + i = i + 1 + n = n - 1 + end +end +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/Mangasee.lua b/mangal/.config/mangal/sources/Mangasee.lua new file mode 100755 index 0000000..ac64295 --- /dev/null +++ b/mangal/.config/mangal/sources/Mangasee.lua @@ -0,0 +1,148 @@ +------------------------------------ +-- @name Mangasee +-- @url https://mangasee123.com/ +-- @author alperen +-- @license MIT +------------------------------------ + + + + +----- IMPORTS ----- +Html = require("html") +Http = require("http") +HttpUtil = require("http_util") +Headless = require("headless") +Strings = require("strings") +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Browser = Headless.browser() +Base = "https://mangasee123.com" +--- END VARIABLES --- + + + +----- MAIN ----- + +--- Searches for manga with given query. +--[[ +Manga fields: + name - string, required + url - string, required + author - string, optional + genres - string (multiple genres are divided by comma ','), optional + summary - string, optional +--]] +-- @param query Query to search for +-- @return Table of mangas +function SearchManga(query) + local page = Browser:page() + page:navigate(Base .. "/search/?name=" .. HttpUtil.query_escape(query)) + page:waitLoad() + + local doc = Html.parse(page:html()) + local mangas = {} + + doc:find(".top-15.ng-scope"):each(function(i, s) + local manga = { name = s:find('.SeriesName[ng-bind-html="Series.s"]'):first():text(), + url = Base .. s:find('.SeriesName[ng-bind-html="Series.s"]'):first():attr("href") } + mangas[i + 1] = manga + end) + + return mangas +end + +--- Gets the list of all manga chapters. +--[[ +Chapter fields: + name - string, required + url - string, required + volume - string, optional + manga_summary - string, optional (in case you can't get it from search page) + manga_author - string, optional + manga_genres - string (multiple genres are divided by comma ','), optional +--]] +-- @param mangaURL URL of the manga +-- @return Table of chapters +function MangaChapters(mangaURL) + local page = Browser:page() + page:navigate(mangaURL) + page:waitLoad() + if page:has('.ShowAllChapters') == true then + page:element('.ShowAllChapters'):click() + end + + local doc = Html.parse(page:html()) + + local chapters = {} + + doc:find(".ChapterLink"):each(function(i, s) + local name = s:find('span'):first():text() + name = Strings.trim(name:gsub("[\r\t\n]+", " "), " ") + local chapter = { name = name, url = Base .. s:attr("href") } + chapters[i + 1] = chapter + end) + + Reverse(chapters) + + return chapters +end + +--- Gets the list of all pages of a chapter. +--[[ +Page fields: + url - string, required + index - uint, required +--]] +-- @param chapterURL URL of the chapter +-- @return Table of pages +function ChapterPages(chapterURL) + local page = Browser:page() + page:navigate(chapterURL) + page:waitLoad() + page:element('.DesktopNav > div > div:nth-child(4) > button'):click() + local doc = Html.parse(page:html()) + + local pages = {} + + local images = {} + doc:find('.img-fluid'):each(function(i, s) + images[i+1] = tostring(s:attr('src')) + end) + + local modal = doc:find("#PageModal"):first() + modal:find('button[ng-click="vm.GoToPage(Page)"]'):each(function(i, s) + + local index = tonumber(Strings.trim(s:text():gsub("[\r\t\n]+", " "), " ")) + if index ~= nil then + local chapterPage = { index = index, url = images[index] } + pages[index] = chapterPage + end + end) + + return pages +end + +--- END MAIN --- + + + + +----- HELPERS ----- +function Reverse(t) + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end +--- END HELPERS --- + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/Mangatoto.lua b/mangal/.config/mangal/sources/Mangatoto.lua new file mode 100755 index 0000000..142ddd5 --- /dev/null +++ b/mangal/.config/mangal/sources/Mangatoto.lua @@ -0,0 +1,113 @@ +-------------------------------------- +-- @name Mangatoto / Bato.to +-- @url https://mangatoto.com/ +-- @author mpiva +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Time = require("time") +Http = require("http") +HttpUtil = require("http_util") +Headless = require("headless") + + +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Browser = Headless.browser() +Base = "https://mangatoto.com" +Delay = 3 -- seconds +--- END VARIABLES --- + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = query:gsub("’","'") + local url = Base .. "/search?word=" .. HttpUtil.query_escape(query) + local request = Http.request("GET", url) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local mangas = {} + local doc2 = doc:find("#series-list"):first() + local cnt = 0 + doc2:find(".no-flag"):each(function (i, r) + local s = r:find(".item-title"):first() + local manga = { name = trim(s:text():gsub("’","'"):gsub(" %[𝙾𝚏𝚏𝚒𝚌𝚒𝚊𝚕%]","")), url = Base .. s:attr("href") } + mangas[cnt+1] = manga + cnt = cnt + 1 + end) + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + local doc2 = doc:find(".main"):first() + doc2:find(".chapt"):each(function (i, s) + local chapter = { name = trim(s:text()), url = Base .. s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local page = Browser:page() + page:navigate(chapterURL) + page:waitLoad() + Time.sleep(Delay) + local element = page:has("div[id='viewer'] > div > img") + local doc = Html.parse(page:html()) + local pages = {} + doc:find("#viewer > div"):each(function (i, s) + local img = s:find("img"):first(); + local p = { index = i, url = trim(img:attr("src"):gsub("[\n\r\t]","")) } + pages[i + 1] = p + end) + return pages +end + + + +----- HELPERS ----- + +function trim(s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +function Reverse(t) + + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end diff --git a/mangal/.config/mangal/sources/ManhuaUs.lua b/mangal/.config/mangal/sources/ManhuaUs.lua new file mode 100755 index 0000000..4c272d8 --- /dev/null +++ b/mangal/.config/mangal/sources/ManhuaUs.lua @@ -0,0 +1,107 @@ +-------------------------------------- +-- @name ManhuaUs +-- @url https://manhuaus.com/ +-- @author mpiva +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Time = require("time") +Http = require("http") +HttpUtil = require("http_util") + +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Base = "https://manhuaus.com/" +Delay = 1 -- seconds +--- END VARIABLES --- + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = query:gsub("’","'") + local url = Base .. "?s=" .. HttpUtil.query_escape(query) .. "&post_type=wp-manga&op=&author=&artist=&release=&adult="; + local request = Http.request("GET", url) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local mangas = {} + local doc2 = doc:find(".c-tabs-item"):first() + doc2:find(".row"):each(function (i, r) + local s = r:find(".post-title"):first() + s = s:find("a"):first() + local manga = { name = trim(s:text():gsub("’","'")), url = s:attr("href") } + mangas[i+1] = manga + end) + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + local doc2 = doc:find(".listing-chapters_wrap"):first() + doc2:find("a"):each(function (i, s) + local chapter = { name = trim(s:text()), url = s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request("GET", chapterURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local pages = {} + doc:find(".reading-content > div"):each(function (i, s) + local img = s:find("img"):first(); + local p = { index = i, url = trim(img:attr("data-src"):gsub("[\n\r\t]","")) } + pages[i + 1] = p + end) + + return pages +end + + + +----- HELPERS ----- + +function trim(s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +function Reverse(t) + + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end diff --git a/mangal/.config/mangal/sources/Readmanga.lua b/mangal/.config/mangal/sources/Readmanga.lua new file mode 100755 index 0000000..974e735 --- /dev/null +++ b/mangal/.config/mangal/sources/Readmanga.lua @@ -0,0 +1,141 @@ +-------------------------- +-- @name Readmanga +-- @url https://readmanga.live/ +-- @author ts-vadim (https://github.com/ts-vadim) +-- @license MIT +-------------------------- + + +---@alias manga { name: string, url: string, author: string|nil, genres: string|nil, summary: string|nil } +---@alias chapter { name: string, url: string, volume: string|nil, manga_summary: string|nil, manga_author: string|nil, manga_genres: string|nil } +---@alias page { url: string, index: number } + + +----- IMPORTS ----- +html = require("html") +http = require("http") +time = require("time") +HttpUtil = require("http_util") +inspect = require("inspect") +strings = require("strings") +json = require("json") +--- END IMPORTS --- + + +----- VARIABLES ----- +DEBUG = true +URL_BASE = "https://readmanga.live/" +client = http.client() +--- END VARIABLES --- + + +----- HELPERS ----- +function reverse(t) + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end +--- END HELPERS --- + + +----- MAIN ----- +--- Searches for manga with given query. +-- @param query string Query to search for +-- @return manga[] Table of mangas +function SearchManga(query) + function parse_page_n(page_offset, mangas) + local request = http.request("POST", URL_BASE .. "search/?q=" .. HttpUtil.query_escape(query)) + local result = client:do_request(request) + local doc = html.parse(result.body) + + start = #mangas + + doc:find(".leftContent .tiles .tile .desc"):each(function(i,s) + title = strings.trim_space(s:find("h3"):text()) + url = s:find("h3 a"):attr("href") + + -- 1. There will be mangas from unrelated sources like mintmanga.live + -- 2. Sometimes it will recieve broken entries with a link to an author (cause idk what im doing) + if strings.contains(url, "https://") or strings.contains(url, "/list/person") then + return + end + + mangas[start+i+1] = { + name = title, + url = URL_BASE .. strings.trim(url, "/"), + } + end) + end + + mangas = {} + -- Seems like the step is always 50 + parse_page_n(50, mangas) + -- parse_page_n(100, mangas) + + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL string URL of the manga +-- @return chapter[] Table of chapters +function MangaChapters(mangaURL) + local request = http.request("GET", mangaURL) + local result = client:do_request(request) + local doc = html.parse(result.body) + + chapters = {} + doc:find(".chapters-link a.chapter-link"):each(function(i,s) + chapters[i+1] = { + name = strings.trim_space(s:text()), + url = URL_BASE .. strings.trim(s:attr("href"), "/"), + } + end) + + reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL string URL of the chapter +-- @return page[] +function ChapterPages(chapterURL) + local request = http.request("GET", chapterURL) + local result = client:do_request(request) + h = result.body + + -- For some reason image URLs are passed to readerInit() function in bare HTML + -- with some other arguments. So I'm trying to get just the urls here. + json_start = h:find("rm_h.readerInit%(") + json_start = h:find("%[", json_start) + s = h:sub(json_start) + s = s:sub(1, s:find("%)")) + s = s:sub(1, #s - s:reverse():find("%]") + 1) + s = "[" .. s:gsub("'", "\"") .. "]" + j, e = json.decode(s) + if e then + error(e) + end + + pages = {} + for i,v in ipairs(j[1]) do + url = v[1] .. v[3] + url = url:sub(1, url:find("?") - 1) + pages[i] = { + url = url, + index = i, + } + end + + return pages +end +--- END MAIN --- + + +-- ex: ts=4 sw=4 et filetype=lua diff --git a/mangal/.config/mangal/sources/Toonily.lua b/mangal/.config/mangal/sources/Toonily.lua new file mode 100755 index 0000000..02a63e2 --- /dev/null +++ b/mangal/.config/mangal/sources/Toonily.lua @@ -0,0 +1,105 @@ +-------------------------------------- +-- @name Toonily +-- @url https://toonily.com/ +-- @author mpiva +-- @license MIT +-------------------------------------- + + + + +----- IMPORTS ----- +Html = require("html") +Time = require("time") +Http = require("http") +HttpUtil = require("http_util") + +--- END IMPORTS --- + + + + +----- VARIABLES ----- +Client = Http.client() +Base = "https://toonily.com" +Delay = 1 -- seconds +--- END VARIABLES --- + + +----- MAIN ----- + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url +function SearchManga(query) + query = query:gsub("’","'") + local forms = "action=ajaxsearchpro_search&aspp=" .. HttpUtil.query_escape(query) .. "&asid=1&asp_inst_id=1_1&options=" .. HttpUtil.query_escape("filters_initials=0&filters_changed=0&qtranslate_lang=0¤t_page_id=12") + local request = Http.request("POST", Base .. "/wp-admin/admin-ajax.php", forms) + request:header_set("Content-Type", "application/x-www-form-urlencoded") + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local mangas = {} + + doc:find(".asp_res_url"):each(function (i, s) + local manga = { name = trim(s:text():gsub("’","'")), url = s:attr("href") } + mangas[i+1] = manga + end) + return mangas +end + + +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function MangaChapters(mangaURL) + local request = Http.request("GET", mangaURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + + local chapters = {} + doc:find(".wp-manga-chapter > a"):each(function (i, s) + local chapter = { name = trim(s:text()), url = s:attr("href") } + chapters[i+1] = chapter + end) + + Reverse(chapters) + + return chapters +end + + +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function ChapterPages(chapterURL) + local request = Http.request("GET", chapterURL) + local result = Client:do_request(request) + local doc = Html.parse(result.body) + local pages = {} + doc:find(".reading-content > div"):each(function (i, s) + local img = s:find("img"):first(); + local p = { index = i, url = trim(img:attr("data-src"):gsub("[\n\r\t]","")) } + pages[i + 1] = p + end) + + return pages +end + + + +----- HELPERS ----- + +function trim(s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +function Reverse(t) + + local n = #t + local i = 1 + while i < n do + t[i], t[n] = t[n], t[i] + i = i + 1 + n = n - 1 + end +end