diff --git a/src/en/oots/AndroidManifest.xml b/src/en/oots/AndroidManifest.xml
new file mode 100644
index 000000000..0d7e33d58
--- /dev/null
+++ b/src/en/oots/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/en/oots/build.gradle b/src/en/oots/build.gradle
new file mode 100644
index 000000000..fe8dfe50a
--- /dev/null
+++ b/src/en/oots/build.gradle
@@ -0,0 +1,13 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'oots'
+ pkgNameSuffix = 'en.oots'
+ extClass = '.oots'
+ extVersionCode = 1
+ libVersion = '1.2'
+ containsNsfw = false
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/en/oots/res/mipmap-hdpi/ic_launcher.png b/src/en/oots/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..5941db06d
Binary files /dev/null and b/src/en/oots/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/en/oots/res/mipmap-mdpi/ic_launcher.png b/src/en/oots/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..af48fcd32
Binary files /dev/null and b/src/en/oots/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/en/oots/res/mipmap-xhdpi/ic_launcher.png b/src/en/oots/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..bd6f51dff
Binary files /dev/null and b/src/en/oots/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/en/oots/res/mipmap-xxhdpi/ic_launcher.png b/src/en/oots/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..3f6d341fd
Binary files /dev/null and b/src/en/oots/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/en/oots/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/oots/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..ff7d924bb
Binary files /dev/null and b/src/en/oots/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/en/oots/res/web_hi_res_512.png b/src/en/oots/res/web_hi_res_512.png
new file mode 100644
index 000000000..60242139d
Binary files /dev/null and b/src/en/oots/res/web_hi_res_512.png differ
diff --git a/src/en/oots/src/eu/kanade/tachiyomi/extension/en/oots/oots.kt b/src/en/oots/src/eu/kanade/tachiyomi/extension/en/oots/oots.kt
new file mode 100644
index 000000000..150bac58d
--- /dev/null
+++ b/src/en/oots/src/eu/kanade/tachiyomi/extension/en/oots/oots.kt
@@ -0,0 +1,122 @@
+package eu.kanade.tachiyomi.extension.en.oots
+
+import android.app.Application
+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 okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import rx.Observable
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class oots : ParsedHttpSource() {
+ override val name = "The Order Of The Stick (OOTS)"
+
+ override val baseUrl = "https://www.giantitp.com"
+
+ override val lang = "en"
+
+ override val supportsLatest = false
+
+ override fun fetchPopularManga(page: Int): Observable {
+ val manga = SManga.create().apply {
+ title = "The Order Of The Stick"
+ artist = "Rich Burlew"
+ author = "Rich Burlew"
+ status = SManga.ONGOING
+ url = "/comics/oots.html"
+ description = "Having fun with games."
+ thumbnail_url = "https://i.giantitp.com/redesign/Icon_Comics_OOTS.gif"
+ }
+
+ manga.initialized = true
+ return Observable.just(MangasPage(listOf(manga), false))
+ }
+
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = Observable.just(MangasPage(emptyList(), false))
+
+ override fun fetchMangaDetails(manga: SManga): Observable = Observable.just(manga)
+
+ override fun chapterListParse(response: Response): List {
+ val chapterList = super.chapterListParse(response).distinct()
+ return chapterList.mapIndexed {
+ i, ch ->
+ ch.apply { chapter_number = chapterList.size.toFloat() - i }
+ }
+ }
+
+ override fun chapterListSelector() = "p.ComicList a"
+
+ override fun chapterFromElement(element: Element): SChapter {
+
+ val seriesPrefs = Injekt.get().getSharedPreferences("source_${id}_time_found", 0)
+ val seriesPrefsEditor = seriesPrefs.edit()
+
+ val chapter = SChapter.create()
+ chapter.url = element.attr("href")
+ chapter.name = element.text()
+
+ val numberRegex = """oots(\d+)\.html""".toRegex()
+ val number = numberRegex.find(chapter.url)!!.groupValues[1]
+
+ // Save current time when a chapter is found for the first time, and reuse it on future checks to
+ // prevent manga entry without any new chapter bumped to the top of "Latest chapter" list
+ // when the library is updated.
+ val currentTimeMillis = System.currentTimeMillis()
+ if (!seriesPrefs.contains(number)) {
+ seriesPrefsEditor.putLong(number, currentTimeMillis)
+ }
+
+ chapter.date_upload = seriesPrefs.getLong(number, currentTimeMillis)
+
+ seriesPrefsEditor.apply()
+
+ return chapter
+ }
+
+ override fun pageListParse(document: Document): List {
+ val pages = mutableListOf()
+
+ fun addPage(document: Document) {
+ pages.add(Page(pages.size, "", document.select("td[align='center'] > img").attr("src")))
+ }
+
+ addPage(document)
+
+ return pages
+ }
+
+ 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")
+}