diff --git a/src/en/xkcd/build.gradle b/src/en/xkcd/build.gradle new file mode 100644 index 000000000..1be9ff04f --- /dev/null +++ b/src/en/xkcd/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +ext { + appName = 'Tachiyomi: xkcd' + pkgNameSuffix = "en.xkcd" + extClass = '.Xkcd' + extVersionCode = 1 + extVersionSuffix = 0 + libVersion = '1.2' +} + +dependencies { + provided project(':duktape-stub') + provided "com.google.code.gson:gson:2.8.0" + provided "com.github.salomonbrys.kotson:kotson:2.5.0" +} + +apply from: "$rootDir/common.gradle" \ No newline at end of file diff --git a/src/en/xkcd/src/eu/kanade/tachiyomi/extension/en/xkcd/Xkcd.kt b/src/en/xkcd/src/eu/kanade/tachiyomi/extension/en/xkcd/Xkcd.kt new file mode 100644 index 000000000..62d061228 --- /dev/null +++ b/src/en/xkcd/src/eu/kanade/tachiyomi/extension/en/xkcd/Xkcd.kt @@ -0,0 +1,136 @@ +package eu.kanade.tachiyomi.extension.en.xkcd + +import com.github.salomonbrys.kotson.string +import com.google.gson.JsonParser +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable +import java.text.SimpleDateFormat + +class Xkcd : ParsedHttpSource() { + + override val name = "xkcd" + + override val baseUrl = "https://xkcd.com" + + override val lang = "en" + + override val supportsLatest = false + + + override fun fetchPopularManga(page: Int): Observable { + val manga = SManga.create() + manga.setUrlWithoutDomain("/archive") + manga.title = "xkcd" + manga.artist = "Randall Munroe" + manga.author = "Randall Munroe" + manga.status = SManga.ONGOING + manga.description = "A webcomic of romance, sarcasm, math and language" + manga.thumbnail_url = thumbnailUrl + + return Observable.just(MangasPage(arrayListOf(manga), false)) + } + + override fun fetchMangaDetails(manga: SManga): Observable { + return Observable.just(manga) + } + + + override fun chapterListSelector() = "div#middleContainer.box a" + + override fun chapterFromElement(element: Element): SChapter { + + val chapter = SChapter.create() + chapter.url = element.attr("href") + val number = chapter.url.removeSurrounding("/") + chapter.chapter_number = number.toFloat() + chapter.name = number + " - " + element.text() + chapter.date_upload = element.attr("title").let { + SimpleDateFormat("yyyy-MM-dd").parse(it).time + } + return chapter + } + + override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url + "info.0.json") + + override fun pageListParse(response: Response): List { + var jsonData = response.body()!!.string() + jsonData = jsonData.replace("\\u00e2\\u0080\\u0094", "\\u2014").replace("\\u00c3\\u00a9", "\\u00e9").replace("\\u00e2\\u0080\\u0093", "\\u2014").replace("\\u00c3\\u00b3", "\\u00F3") + val json = JsonParser().parse(jsonData).asJsonObject + val imageUrl = json["img"].string + val pages = mutableListOf() + pages.add(Page(0, "", imageUrl)) + var titleWords = json["safe_title"].string.splitToSequence(" ") + var altTextWords = json["alt"].string.splitToSequence(" ") + + var builder = StringBuilder() + var count = 0 + + for (i in titleWords) { + if (count != 0 && count.rem(6) == 0) { + builder.append("%0A") + } + builder.append(i).append("+") + count++ + } + builder.append("%0A%0A") + + var charCount = 0 + + for (i in altTextWords) { + if (charCount > 25) { + builder.append("%0A") + charCount = 0 + } + builder.append(i).append("+") + charCount += i.length + 1 + } + + pages.add(Page(1, "", baseAltTextUrl + builder.toString() + baseAltTextPostUrl)) + return pages + } + + override fun pageListParse(document: Document): List = throw Exception("Not used") + + override fun imageUrlRequest(page: Page) = GET(page.url) + + override fun imageUrlParse(document: Document) = throw Exception("Not used") + + override fun popularMangaSelector(): String = throw Exception("Not used") + + override fun searchMangaFromElement(element: Element): SManga = throw Exception("Not used") + + override fun searchMangaNextPageSelector(): String? = throw Exception("Not used") + + override fun searchMangaSelector(): String = throw Exception("Not used") + + override fun popularMangaRequest(page: Int): Request = throw Exception("Not used") + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw Exception("Not used") + + override fun popularMangaNextPageSelector(): String? = throw Exception("Not used") + + override fun popularMangaFromElement(element: Element): SManga = throw Exception("Not used") + + override fun mangaDetailsParse(document: Document): SManga = throw Exception("Not used") + + override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used") + + override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not used") + + override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used") + + override fun latestUpdatesSelector(): String = throw Exception("Not used") + + companion object { + const val thumbnailUrl = "https://fakeimg.pl/550x780/ffffff/6E7B91/?text=xkcd&font=museo" + const val baseAltTextUrl = "https://fakeimg.pl/1500x2126/ffffff/000000/?text=" + const val baseAltTextPostUrl = "&font_size=64&font=museo" + } + +}