diff --git a/src/en/darthsdroids/build.gradle b/src/en/darthsdroids/build.gradle new file mode 100644 index 000000000..f2f492699 --- /dev/null +++ b/src/en/darthsdroids/build.gradle @@ -0,0 +1,7 @@ +ext { + extName = 'Darths & Droids' + extClass = '.DarthsDroids' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/en/darthsdroids/res/mipmap-hdpi/ic_launcher.png b/src/en/darthsdroids/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..ecb7281d5 Binary files /dev/null and b/src/en/darthsdroids/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/en/darthsdroids/res/mipmap-mdpi/ic_launcher.png b/src/en/darthsdroids/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..e1a81df0d Binary files /dev/null and b/src/en/darthsdroids/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/en/darthsdroids/res/mipmap-xhdpi/ic_launcher.png b/src/en/darthsdroids/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..80eb1e534 Binary files /dev/null and b/src/en/darthsdroids/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/en/darthsdroids/res/mipmap-xxhdpi/ic_launcher.png b/src/en/darthsdroids/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..432ed13af Binary files /dev/null and b/src/en/darthsdroids/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/en/darthsdroids/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/darthsdroids/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..0d6450ce2 Binary files /dev/null and b/src/en/darthsdroids/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/darthsdroids/src/eu/kanade/tachiyomi/extension/en/darthsdroids/DarthsDroids.kt b/src/en/darthsdroids/src/eu/kanade/tachiyomi/extension/en/darthsdroids/DarthsDroids.kt new file mode 100644 index 000000000..18ae61411 --- /dev/null +++ b/src/en/darthsdroids/src/eu/kanade/tachiyomi/extension/en/darthsdroids/DarthsDroids.kt @@ -0,0 +1,247 @@ +package eu.kanade.tachiyomi.extension.en.darthsdroids + +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.interceptor.rateLimitHost +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.model.UpdateStrategy +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import rx.Observable +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.concurrent.TimeUnit + +// Dear Darths & Droids creators: +// I’m sorry if this extension causes too much traffic for your site. +// Unfortunately we can’t just download and use your Zip downloads. +// Shall problems arise, we’ll reduce the rate limit. +class DarthsDroids : HttpSource() { + override val name = "Darths & Droids" + override val baseUrl = "https://www.darthsanddroids.net" + override val lang = "en" + override val supportsLatest = false + override val client = network.cloudflareClient.newBuilder() + .rateLimitHost(baseUrl.toHttpUrl(), 10, 1, TimeUnit.SECONDS) + .build() + + // Picks a thumbnail from the profile pictures of the »cast« pages: + // https://www.darthsanddroids.net/cast/ + // + // Where possible, pick a thumbnail from the corresponding book’s + // cast page. Try to avoid having a character appear more than once + // as thumbnail, giving all main characters equal amounts of spotlight. + // Pick a character people would intuïtively associate with the + // corresponding film, like Qui-Gon for Phantom Menace or Leia for + // A New Hope. + // + // If a book doesn’t have its own cast page, try source a fitting + // profile picture from a different page. Avoid sourcing thumbnails + // from a different website. + private fun dndThumbnailUrlForTitle(nthManga: Int): String = when (nthManga) { + // The numbers are assigned in order of appearance of a book on the archive page. + 0 -> "$baseUrl/cast/QuiGon.jpg" // D&D1 + 1 -> "$baseUrl/cast/Anakin2.jpg" // D&D2 + 2 -> "$baseUrl/cast/ObiWan3.jpg" // D&D3 + 3 -> "$baseUrl/cast/JarJar2.jpg" // JJ + 4 -> "$baseUrl/cast/Leia4.jpg" // D&D4 + 5 -> "$baseUrl/cast/Han5.jpg" // D&D5 + 6 -> "$baseUrl/cast/Luke6.jpg" // D&D6 + 7 -> "$baseUrl/cast/Cassian.jpg" // R1 + 8 -> "$baseUrl/cast/C3PO4.jpg" // Muppets + 9 -> "$baseUrl/cast/Finn7.jpg" // D&D7 + 10 -> "$baseUrl/cast/Han4.jpg" // Solo + 11 -> "$baseUrl/cast/Hux8.jpg" // D&D8 + // Just some nonsense fallback that screams »Star Wars« but is also so recognisably + // OT that one can understand it’s a mere fallback. Better thumbnails require an + // extension update. + else -> "$baseUrl/cast/Vader4.jpg" + } + + private fun dndManga(archiveUrl: String, mangaTitle: String, mangaStatus: Int, nthManga: Int): SManga = SManga.create().apply { + setUrlWithoutDomain(archiveUrl) + thumbnail_url = dndThumbnailUrlForTitle(nthManga) + title = mangaTitle + author = "David Morgan-Mar & Co." + artist = "David Morgan-Mar & Co." + description = """What if Star Wars as we know it didn't exist, but instead the + |plot of the movies was being made up on the spot by players of + |a Tabletop Game? + | + |Well, for one, the results might actually make a lot more sense, + |from an out-of-story point of view… + """.trimMargin() + genre = "Campaign Comic, Comedy, Space Opera, Science Fiction" + status = mangaStatus + update_strategy = when (mangaStatus) { + SManga.COMPLETED -> UpdateStrategy.ONLY_FETCH_ONCE + else -> UpdateStrategy.ALWAYS_UPDATE + } + initialized = true + } + + override fun popularMangaRequest(page: Int): Request = + GET("$baseUrl/archive.html", headers) + + // The book and page archive feeds are rather special for this webcomic. + // The main archive page `/archive.html` is a combined feed for both, + // all previous and finished books, as well as all pages of the book that + // is currently releasing. Every finished book gets its own archive page + // like `/archive4.html` or `/archiveJJ.html` into which all page links + // are moved. So whatever book is currently releasing in `/archive.html` + // will eventually be moved into its own archive, and it’ll instead + // appear as a book-archive link in `/archive.html`. + // + // This means a few things: + // • The currently releasing book eventually changes its `url`! + // • The URL of the currently releasing book will be taken over by + // whichever new book comes next. + // • There is no deterministic way of guessing a book’s future + // archive name. + // ◦ This is especially apparent with the »Solo« book, which’s + // archive page is `/solo/`, while all others are `/archiveX.html`. + // + // So eventually, Tachiyomi & Co. will glitch out once a currently + // releasing book finishes. People will find the current book’s page + // feed to be empty. Even worse, they may find it starting anew with + // different pages. A manual refresh *should* change the book’s `url` + // to its new archive page, and all reading progress should be preserved. + // Then the user will have to manually add the new book to their library. + // + // The alternative would be to have a pseudo book »