Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Archive of our own Provider #173

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# QuickNovel
Adfree FOSS Android app for downloading novels. It also functions as an Epub reader.
Ad-free FOSS Android app for downloading novels. It also functions as an Epub reader.

**Discord:** https://discord.gg/5Hus6fM

Expand Down Expand Up @@ -45,7 +45,7 @@ Adfree FOSS Android app for downloading novels. It also functions as an Epub rea

- https://readnovelfull.com

**Screenshoots:**
**Screenshots:**

<img src="./.github/home.jpg" height="400"/><img src="./.github/search.jpg" height="400"/><img src="./.github/downloads.jpg" height="400"/><img src="./.github/result.jpg" height="400"/><img src="./.github/reader.jpg" height="400"/>

Expand All @@ -59,5 +59,5 @@ The app is purely for educational and personal use.

QuickNovel does not host any content on the app, and has no control over what media is put up or taken down. QuickNovel functions like any other search engine, such as Google. QuickNovel does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface.

It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use QuickNovel at your own risk.
It merely scrapes 3rd-party websites that are publicly accessible via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use QuickNovel at your own risk.

Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package com.lagradost.quicknovel.providers

import android.annotation.SuppressLint
import com.lagradost.quicknovel.*
import com.lagradost.quicknovel.MainActivity.Companion.app
import com.lagradost.quicknovel.mvvm.debugWarning
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import java.lang.Exception
import java.util.*
import kotlin.collections.ArrayList

class ArchiveOfOurOwnProvider : MainAPI() {
override val name = "Archive of Our Own"
override val mainUrl = "https://archiveofourown.org"

override val hasMainPage = true

override val iconId = R.drawable.ic_archive_of_our_own

override val iconBackgroundId = R.color.royalRoadColor
PrecociouslyDigital marked this conversation as resolved.
Show resolved Hide resolved

override val orderBys = listOf(
Pair("Latest", "latest"),
)
val searchFilters = listOf(
PrecociouslyDigital marked this conversation as resolved.
Show resolved Hide resolved
Pair("Best Match", "_score"),
Pair("Author", "authors_to_sort_on"),
Pair("Title", "title_to_sort_on"),
Pair("Date Posted", "created_at"),
Pair("Date Updated", "revised_at"),
Pair("Word Count", "word_count"),
Pair("Hits", "hits"),
Pair("Kudos", "kudos_count"),
Pair("Comments", "comments_count"),
Pair("Bookmarks", "bookmarks_count")

)


override val tags = listOf(
"Creator Chose Not To Use Archive Warnings",
"Graphic Depictions Of Violence",
"Major Character Death",
"Rape/Non-con",
"Underage",
"Creator Chose Not To Use Archive Warnings"
).map { Pair(it, java.net.URLEncoder.encode(it.replace("/","*s*"), "utf-8")) }


override suspend fun loadMainPage(
page: Int,
mainCategory: String?,
orderBy: String?,
tag: String?,
PrecociouslyDigital marked this conversation as resolved.
Show resolved Hide resolved
): HeadMainPageResponse {
val url =
"$mainUrl/works"
if (page > 1) return HeadMainPageResponse(
url,
ArrayList()
) // Latest ONLY HAS 1 PAGE

val response = app.get(url)

val document = Jsoup.parse(response.text)
val works = document.select("li.work")
if (works.size <= 0) return HeadMainPageResponse(url, ArrayList())

val returnValue: ArrayList<SearchResponse> = ArrayList()
for (h in works) {
val workLink = h?.selectFirst("div.header.module > h4.heading > a")
if (workLink == null){
debugWarning { "Ao3 work has no actual work?" }
continue
}
val name = workLink.text()
val url = workLink.attr("href")

val authorLink = h?.selectFirst("div.header.module > h4.heading > a[rel=\"author\"]")
if (authorLink == null){
debugWarning { "Ao3 work has no actual author?" }
continue
}
val author = authorLink.attr("href")

//val tags = ArrayList(h.select("span.tags > a").map { t -> t.text() })
returnValue.add(
SearchResponse(
name,
fixUrl(url),
fixUrlNull(author),
apiName = this.name
)
)
//tags))
}
return HeadMainPageResponse(url, returnValue)
}


override suspend fun search(query: String): List<SearchResponse> {
val response = app.get("$mainUrl/works/search?work_search[query]=$query")

val document = Jsoup.parse(response.text)
val works = document.select("li.work")
if (works.size <= 0) return ArrayList()
val returnValue: ArrayList<SearchResponse> = ArrayList()
for (h in works) {
val workLink = h?.selectFirst("div.header.module > h4.heading > a")
if (workLink == null){
debugWarning { "Ao3 work has no actual work?" }
continue
}
val name = workLink.text()
val url = workLink.attr("href")

val authorLink = h?.selectFirst("div.header.module > h4.heading > a[rel=\"author\"]")
if (authorLink == null){
debugWarning { "Ao3 work has no actual author?" }
continue
}
val author = authorLink.attr("href")

//val tags = ArrayList(h.select("span.tags > a").map { t -> t.text() })
returnValue.add(
SearchResponse(
name,
fixUrl(url),
fixUrlNull(author),
apiName = this.name
)
)
//tags))
}
return returnValue
}

override suspend fun load(url: String): LoadResponse? {
val response = app.get("$url/?view_adult=true")

val document = Jsoup.parse(response.text)

val name = document.selectFirst("h2.title.heading")?.text().toString()
val author = document.selectFirst("h3.byline.heading > a[rel=\"author\"]")
val peopleVoted = document.selectFirst("dd.kudos")?.text()?.replace(",","")?.toInt()
val views = document.selectFirst("dd.hits")?.text()?.replace(",","")?.toInt()
val synopsis = document.selectFirst("div.summary.module > blockquote.userstuff")
?.children()?.joinToString("\n", transform = Element::text)

val tags = document.select("a.tag")?.map(org.jsoup.nodes.Element::text)

val chaptersResponse = app.get("$url/navigate?view_adult=true")
val chapterDocument = Jsoup.parse(chaptersResponse.text)

val chapters = chapterDocument.selectFirst("ol.chapter.index.group[role=\"navigation\"]")

val data = chapters?.children()?.map {
val link = it.child(0)
val date = it.child(1)
ChapterData(
name = link.text().toString(),
url = link.attr("href").toString(),
PrecociouslyDigital marked this conversation as resolved.
Show resolved Hide resolved
dateOfRelease = date.text()
)
}


return LoadResponse(
url,
name,
data ?: ArrayList(),
author = author?.text(),
posterUrl = fixUrlNull(author?.attr("href")),
peopleVoted,
views,
synopsis = synopsis,
tags = tags
)
}

override suspend fun loadHtml(url: String): String? {
val response = app.get(url)
val document = Jsoup.parse(response.text)
return document.selectFirst("div.chapter")?.html()
}
}
1 change: 1 addition & 0 deletions app/src/main/java/com/lagradost/quicknovel/util/Apis.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Apis {
IndoWebNovelProvider(),
SakuraNovelProvider(),
WattpadProvider(),
ArchiveOfOurOwnProvider(),
)

fun getApiFromName(name: String): APIRepository {
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/ic_archive_of_our_own.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="600dp"
android:height="415dp"
android:viewportWidth="600"
android:viewportHeight="415">

<path
android:fillColor="#900"
android:pathData="M370.16 10.811c-54.019 0-97.816 42.648-97.816 95.266 0 52.608 43.797 95.244 97.816 95.244s97.816-42.636 97.816-95.244c0-52.618-43.797-95.266-97.816-95.266zm-355.28 4.582c-2.9356 0.1201-4.0242 0.92857-4.8105 1.7188 0 0-1.2608 5.0412 7.9844 6.7148 9.2351 1.6837 62.165 17.231 134.85 74.355 72.671 57.135 112.16 107.96 140.3 137.79 0 0-85.697 30.246-186.09 96.615 0 0 35.286-42.426 49.148-147.87 2.0265-15.415 5.7679-34.651 7.5625-52.93 0 0 2.0969-14.699-3.3574-14.699-5.4644 0-14.287 73.517-29.41 119.3-8.237 24.933-18.48 55.875-47.889 96.203-18.188 24.953-36.366 43.665-32.344 52.094 8.8217 18.48 27.303 0.41407 27.303 0.41407s117.63-77.712 241.13-115.94c0 0 30.074 32.897 35.428 39.229 16.121 19.055 27.686 40.117 41.438 39.754 11.171-0.30246 15.124-6.3012 21.012-38.654 5.8778-32.343 18.902-64.273 18.902-64.273s74.033-3.5589 77.713 20.164c2.46 15.849-8.549 24.016-17.32 26.93-4.2748 1.4316-17.432 5.2615-22.896 6.8242-10.223 2.9137-12.834 18.44 4.0938 25.9 27.625 12.169 55.945 18.229 53.344 39.492-2.5205 20.577-36.588 30.852-60.492 25.619-44.109-9.6586-46.226-30.206-53.768-27.303-5.4644 2.097 10.082 18.903 18.48 24.367 8.4084 5.4544 70.161 36.549 102.5-2.1055 36.557-43.675-33.604-70.988-33.604-70.988s43.262-19.328 35.287-55.875c-7.985-36.547-55.039-42.011-89.902-44.945 0 0 15.123-38.23 49.986-78.135 18.127-20.749 46.75-44.3 63.859-57.135 16.797-12.602 29.743-14.851 26.043-22.262-4.2042-8.3983-72.258 40.752-85.273 52.508-13.026 11.766-50.834 48.726-82.34 105.02 0 0-50.824 2.5208-89.479 11.756 0 0-55.028-59.644-119.3-109.64-64.273-49.987-124.34-80.234-160.89-91.576-22.287-6.9188-32.309-8.6338-37.201-8.4336zm355.28 20.654c39.713 0 71.904 31.345 71.904 70.029 0 38.664-32.191 70.02-71.904 70.02s-71.904-31.355-71.904-70.02c0-38.685 32.191-70.029 71.904-70.029zm34.158 212.75s-10.688 21.141-15.709 42.031c-8.8419-11.191-29.621-33.824-29.621-33.824s15.77-4.0532 45.33-8.207z" />
</vector>
1 change: 1 addition & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<color name="novelPassionColor">#FFF</color>
<color name="wuxiaWorldOnlineColor">#24242B</color>
<color name="royalRoadColor">@color/darkBackground</color>
<color name="archiveOfOurOwnColor">?attr/boxItemBackground</color>
<color name="wuxiaWorldSiteColor">#1670bf</color>
<color name="readLightNovelColor">#FFF</color>
<color name="boxNovelColor">#eb3349</color>
Expand Down