diff --git a/src/it/animegdrclub/AndroidManifest.xml b/src/it/animegdrclub/AndroidManifest.xml
new file mode 100644
index 000000000..30deb7f79
--- /dev/null
+++ b/src/it/animegdrclub/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/it/animegdrclub/build.gradle b/src/it/animegdrclub/build.gradle
new file mode 100644
index 000000000..19682490e
--- /dev/null
+++ b/src/it/animegdrclub/build.gradle
@@ -0,0 +1,11 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'Anime GDR Club'
+ pkgNameSuffix = 'it.animegdrclub'
+ extClass = '.AnimeGDRClub'
+ extVersionCode = 1
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/it/animegdrclub/res/mipmap-hdpi/ic_launcher.png b/src/it/animegdrclub/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..c3096a6f6
Binary files /dev/null and b/src/it/animegdrclub/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/it/animegdrclub/res/mipmap-mdpi/ic_launcher.png b/src/it/animegdrclub/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..a681aba02
Binary files /dev/null and b/src/it/animegdrclub/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/it/animegdrclub/res/mipmap-xhdpi/ic_launcher.png b/src/it/animegdrclub/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..7701405e8
Binary files /dev/null and b/src/it/animegdrclub/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/it/animegdrclub/res/mipmap-xxhdpi/ic_launcher.png b/src/it/animegdrclub/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..15a180ae3
Binary files /dev/null and b/src/it/animegdrclub/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/it/animegdrclub/res/mipmap-xxxhdpi/ic_launcher.png b/src/it/animegdrclub/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..1b11200c3
Binary files /dev/null and b/src/it/animegdrclub/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/it/animegdrclub/res/web_hi_res_512.png b/src/it/animegdrclub/res/web_hi_res_512.png
new file mode 100644
index 000000000..413f7f8af
Binary files /dev/null and b/src/it/animegdrclub/res/web_hi_res_512.png differ
diff --git a/src/it/animegdrclub/src/eu/kanade/tachiyomi/extension/it/animegdrclub/AnimeGDRClub.kt b/src/it/animegdrclub/src/eu/kanade/tachiyomi/extension/it/animegdrclub/AnimeGDRClub.kt
new file mode 100644
index 000000000..dc9358974
--- /dev/null
+++ b/src/it/animegdrclub/src/eu/kanade/tachiyomi/extension/it/animegdrclub/AnimeGDRClub.kt
@@ -0,0 +1,218 @@
+package eu.kanade.tachiyomi.extension.it.animegdrclub
+
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.source.model.Filter
+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.online.ParsedHttpSource
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+
+class AnimeGDRClub : ParsedHttpSource() {
+ override val name = "Anime GDR Club"
+ override val baseUrl = "http://www.agcscanlation.it/"
+ override val lang = "it"
+ override val supportsLatest = true
+ override val client: OkHttpClient = network.cloudflareClient
+
+ //region REQUESTS
+
+ override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/serie.php", headers)
+ override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/", headers)
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+ val url = "$baseUrl/".toHttpUrlOrNull()!!.newBuilder()
+
+ if (query.isNotEmpty()) {
+ url.addEncodedPathSegment("serie.php")
+ return GET("$url#$query", headers)
+ } else {
+ url.addEncodedPathSegment("listone.php")
+
+ var status = ""
+ var filtertype = ""
+
+ (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
+ when (filter) {
+ is SelezType -> {
+ filtertype = filter.values[filter.state]
+ }
+ is GenreSelez -> {
+ if (filtertype == "Genere") {
+ url.addQueryParameter("genere", filter.values[filter.state])
+ }
+ }
+ is StatusList -> {
+ if (filtertype == "Stato") {
+ var i = 0
+ filter.state.forEach {
+ if (it.state) {
+ status += "${if (i != 0) "-" else ""}${it.id}"
+ i++
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return GET("${if (status.isNotEmpty()) "$baseUrl/serie.php#stati=$status" else url}", headers)
+ }
+ }
+ //endregion
+
+ //region CONTENTS INFO
+ private fun mangasParse(response: Response, selector: String, num: Int): MangasPage {
+ val document = response.asJsoup()
+ var sele = selector
+ var nume = num
+
+ val encFrags = response.request.url.encodedFragment.toString().split('-')
+
+ if ((encFrags[0].isNotEmpty()) and (encFrags[0] != "null")) {
+ nume = 1
+ if (encFrags[0].startsWith("stati=")) {
+ sele = encFrags.map {
+ ".${it.replace("stati=", "")} > .manga"
+ }.joinToString(", ")
+ } else {
+ sele = "div.manga:contains(${encFrags.joinToString("-")})"
+ }
+ }
+
+ val mangas = document.select(sele).map { element ->
+ when (nume) {
+ 1 -> popularMangaFromElement(element)
+ 2 -> latestUpdatesFromElement(element)
+ else -> searchMangaFromElement(element)
+ }
+ }
+ return MangasPage(mangas, false)
+ }
+ override fun popularMangaParse(response: Response): MangasPage = mangasParse(response, popularMangaSelector(), 1)
+ override fun latestUpdatesParse(response: Response): MangasPage = mangasParse(response, latestUpdatesSelector(), 2)
+ override fun searchMangaParse(response: Response): MangasPage = mangasParse(response, searchMangaSelector(), 3)
+
+ override fun popularMangaSelector() = "div.manga"
+ override fun latestUpdatesSelector() = ".containernews > a"
+ override fun searchMangaSelector() = ".listonegen > a"
+
+ override fun popularMangaFromElement(element: Element): SManga {
+ val manga = SManga.create()
+
+ manga.thumbnail_url = "$baseUrl/${element.selectFirst("img").attr("src")}"
+ manga.url = element.selectFirst("a.linkalmanga").attr("href")
+ manga.title = element.selectFirst("div.nomeserie > span").text()
+
+ return manga
+ }
+ override fun latestUpdatesFromElement(element: Element): SManga {
+ val manga = SManga.create()
+
+ manga.setUrlWithoutDomain("http://www.agcscanlation.it/progetto.php?nome=${element.attr("href").toHttpUrlOrNull()!!.queryParameter("nome")}")
+ manga.title = element.selectFirst(".titolo").text()
+ manga.thumbnail_url = "$baseUrl/${element.selectFirst("img").attr("src")}"
+
+ return manga
+ }
+ override fun searchMangaFromElement(element: Element): SManga = latestUpdatesFromElement(element)
+
+ override fun mangaDetailsParse(document: Document): SManga {
+ val infoElement = document.select(".tabellaalta")
+ val manga = SManga.create()
+
+ manga.status = when {
+ infoElement.text().contains("In Corso") -> SManga.ONGOING
+ infoElement.text().contains("Concluso") -> SManga.COMPLETED
+ infoElement.text().contains("Interrotto") -> SManga.ON_HIATUS
+ else -> SManga.UNKNOWN
+ }
+ manga.genre = infoElement.select("span.generi > a").map {
+ it.text()
+ }.joinToString(", ")
+ manga.description = document.select("span.trama")?.text()?.substringAfter("Trama: ")
+
+ return manga
+ }
+ //endregion
+
+ //region NEXT SELECTOR - Not used
+
+ override fun popularMangaNextPageSelector(): String? = null
+ override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
+ override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
+ //endregion
+
+ //region CHAPTER in CONTENTS INFO
+
+ override fun chapterListParse(response: Response): List {
+ val document = response.asJsoup()
+ val chapters = mutableListOf()
+
+ document.select(chapterListSelector()).forEach {
+ chapters.add(
+ SChapter.create().apply {
+ setUrlWithoutDomain(it.attr("href").replace("reader", "readerr"))
+ name = it.text()
+ chapter_number = it.text().filter { it.isDigit() }.toFloat()
+ }
+ )
+ }
+
+ chapters.reverse()
+ return chapters
+ }
+
+ override fun chapterListSelector() = ".capitoli_cont > a"
+ override fun chapterFromElement(element: Element) = throw Exception("Not Used")
+ //endregion
+
+ //region PAGE loading
+
+ override fun pageListParse(document: Document): List {
+ val pages = mutableListOf()
+ document.select("img.corrente").forEachIndexed { i, it ->
+ pages.add(Page(i, "", baseUrl + it.attr("src")))
+ }
+
+ return pages
+ }
+
+ override fun imageUrlParse(document: Document) = ""
+ override fun imageRequest(page: Page): Request {
+ val imgHeader = Headers.Builder().apply {
+ add("Referer", baseUrl)
+ }.build()
+ return GET(page.imageUrl!!, imgHeader)
+ }
+ //endregion
+
+ //region FILTERS
+ private class SelezType(options: List) : Filter.Select("Scegli quale usare", options.toTypedArray(), 1)
+ private class GenreSelez(genres: List) : Filter.Select("Genere", genres.toTypedArray(), 0)
+ private class Status(name: String, val id: String = name) : Filter.CheckBox(name, true)
+ private class StatusList(statuses: List) : Filter.Group("Stato", statuses)
+
+ override fun getFilterList() = FilterList(
+ Filter.Header("La ricerca non accetta i filtri e viceversa"),
+ SelezType(listOf("Stato", "Genere")),
+ StatusList(getStatusList()),
+ GenreSelez(getGenreList())
+ )
+
+ private fun getStatusList() = listOf(
+ Status("In corso", "progettiincorso"),
+ Status("Finito", "progetticonclusi-progettioneshot"),
+ Status("Interrotto", "progettiinterrotti")
+ )
+ private fun getGenreList() = listOf("Avventura", "Azione", "Comico", "Commedia", "Drammatico", "Ecchi", "Fantascienza", "Fantasy", "Guerra", "Harem", "Horror", "Isekai", "Mecha", "Mistero", "Musica", "Psicologico", "Scolastico", "Sentimentale", "Slice of Life", "Sovrannaturale", "Sperimentale", "Storico", "Thriller")
+ //endregion
+}