diff --git a/src/en/kickassanime/AndroidManifest.xml b/src/en/kickassanime/AndroidManifest.xml
new file mode 100644
index 000000000..acb4de356
--- /dev/null
+++ b/src/en/kickassanime/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/en/kickassanime/build.gradle b/src/en/kickassanime/build.gradle
new file mode 100644
index 000000000..8d3088578
--- /dev/null
+++ b/src/en/kickassanime/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'KickAssAnime'
+ pkgNameSuffix = 'en.kickassanime'
+ extClass = '.KickAssAnime'
+ extVersionCode = 1
+ libVersion = '13'
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/en/kickassanime/res/mipmap-hdpi/ic_launcher.png b/src/en/kickassanime/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..530ac20b7
Binary files /dev/null and b/src/en/kickassanime/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/en/kickassanime/res/mipmap-mdpi/ic_launcher.png b/src/en/kickassanime/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..13c03bea4
Binary files /dev/null and b/src/en/kickassanime/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/en/kickassanime/res/mipmap-xhdpi/ic_launcher.png b/src/en/kickassanime/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..a21923eba
Binary files /dev/null and b/src/en/kickassanime/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/en/kickassanime/res/mipmap-xxhdpi/ic_launcher.png b/src/en/kickassanime/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..6e2555103
Binary files /dev/null and b/src/en/kickassanime/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/en/kickassanime/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/kickassanime/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..5458d4434
Binary files /dev/null and b/src/en/kickassanime/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/en/kickassanime/res/web_hi_res_512.png b/src/en/kickassanime/res/web_hi_res_512.png
new file mode 100644
index 000000000..0c3866109
Binary files /dev/null and b/src/en/kickassanime/res/web_hi_res_512.png differ
diff --git a/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/JSONUtil.java b/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/JSONUtil.java
new file mode 100644
index 000000000..11d506f47
--- /dev/null
+++ b/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/JSONUtil.java
@@ -0,0 +1,88 @@
+package eu.kanade.tachiyomi.animeextension.en.kickassanime;
+
+public class JSONUtil {
+ public static String escape(String input) {
+ StringBuilder output = new StringBuilder();
+
+ for(int i=0; i= 0x10000) {
+ assert false : "Java stores as u16, so it should never give us a character that's bigger than 2 bytes. It literally can't.";
+ } else if(chx > 127) {
+ output.append(String.format("\\u%04x", chx));
+ } else {
+ output.append(ch);
+ }
+ }
+
+ return output.toString();
+ }
+
+ public static String unescape(String input) {
+ StringBuilder builder = new StringBuilder();
+
+ int i = 0;
+ while (i < input.length()) {
+ char delimiter = input.charAt(i); i++; // consume letter or backslash
+
+ if(delimiter == '\\' && i < input.length()) {
+
+ // consume first after backslash
+ char ch = input.charAt(i); i++;
+
+ if(ch == '\\' || ch == '/' || ch == '"' || ch == '\'') {
+ builder.append(ch);
+ }
+ else if(ch == 'n') builder.append('\n');
+ else if(ch == 'r') builder.append('\r');
+ else if(ch == 't') builder.append('\t');
+ else if(ch == 'b') builder.append('\b');
+ else if(ch == 'f') builder.append('\f');
+ else if(ch == 'u') {
+
+ StringBuilder hex = new StringBuilder();
+
+ // expect 4 digits
+ if (i+4 > input.length()) {
+ throw new RuntimeException("Not enough unicode digits! ");
+ }
+ for (char x : input.substring(i, i + 4).toCharArray()) {
+ if(!Character.isLetterOrDigit(x)) {
+ throw new RuntimeException("Bad character in unicode escape.");
+ }
+ hex.append(Character.toLowerCase(x));
+ }
+ i+=4; // consume those four digits.
+
+ int code = Integer.parseInt(hex.toString(), 16);
+ builder.append((char) code);
+ } else {
+ throw new RuntimeException("Illegal escape sequence: \\"+ch);
+ }
+ } else { // it's not a backslash, or it's the last character.
+ builder.append(delimiter);
+ }
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/KickAssAnime.kt b/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/KickAssAnime.kt
new file mode 100644
index 000000000..dd2566523
--- /dev/null
+++ b/src/en/kickassanime/src/eu/kanade/tachiyomi/animeextension/en/kickassanime/KickAssAnime.kt
@@ -0,0 +1,326 @@
+package eu.kanade.tachiyomi.animeextension.en.kickassanime
+
+import android.app.Application
+import android.content.SharedPreferences
+import android.net.Uri
+import androidx.preference.ListPreference
+import androidx.preference.PreferenceScreen
+import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
+import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
+import eu.kanade.tachiyomi.animesource.model.AnimesPage
+import eu.kanade.tachiyomi.animesource.model.SAnime
+import eu.kanade.tachiyomi.animesource.model.SEpisode
+import eu.kanade.tachiyomi.animesource.model.Track
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.util.asJsoup
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonArray
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.float
+import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.jsonObject
+import kotlinx.serialization.json.jsonPrimitive
+import okhttp3.Headers
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+import uy.kohesive.injekt.injectLazy
+import java.util.regex.Pattern
+
+@ExperimentalSerializationApi
+class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
+
+ override val name = "KickAssAnime"
+
+ override val baseUrl by lazy { preferences.getString("preferred_domain", "https://www2.kickassanime.ro")!! }
+
+ override val lang = "en"
+
+ override val supportsLatest = false
+
+ override val client: OkHttpClient = network.cloudflareClient
+
+ private val json: Json by injectLazy()
+
+ private val preferences: SharedPreferences by lazy {
+ Injekt.get().getSharedPreferences("source_$id", 0x0000)
+ }
+
+ override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/api/get_anime_list/all/$page")
+
+ override fun popularAnimeParse(response: Response): AnimesPage {
+ val responseObject = json.decodeFromString(response.body!!.string())
+ val data = responseObject["data"]!!.jsonArray
+ val animes = data.map { item ->
+ SAnime.create().apply {
+ setUrlWithoutDomain(item.jsonObject["slug"]!!.jsonPrimitive.content.substringBefore("/episode"))
+ thumbnail_url = "$baseUrl/uploads/" + item.jsonObject["poster"]!!.jsonPrimitive.content
+ title = item.jsonObject["name"]!!.jsonPrimitive.content
+ }
+ }
+ return AnimesPage(animes, true)
+ }
+
+ override fun episodeListParse(response: Response): List {
+ val data = getAppdata(response.asJsoup())
+ val anime = data["anime"]!!.jsonObject
+ val episodeList = anime["episodes"]!!.jsonArray
+ return episodeList.map { item ->
+ SEpisode.create().apply {
+ url = item.jsonObject["slug"]!!.jsonPrimitive.content
+ episode_number = item.jsonObject["num"]!!.jsonPrimitive.float
+ name = item.jsonObject["epnum"]!!.jsonPrimitive.content
+ }
+ }
+ }
+
+ override fun latestUpdatesParse(response: Response) = throw Exception("not used")
+
+ override fun latestUpdatesRequest(page: Int) = throw Exception("not used")
+
+ override fun videoListParse(response: Response): List