fix voting api (#544)

This commit is contained in:
Cloudburst 2023-08-09 23:44:17 +02:00 committed by GitHub
parent bbbb7c4982
commit 44a2146c12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 112 deletions

View File

@ -8,22 +8,14 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.R
import java.security.MessageDigest
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.main
import kotlinx.coroutines.delay
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
object VotingApi { // please do not cheat the votes lol
private const val LOGKEY = "VotingApi"
enum class VoteType(val value: Int) {
UPVOTE(1),
DOWNVOTE(-1),
NONE(0)
}
private val apiDomain = "https://api.countapi.xyz"
private const val apiDomain = "https://counterapi.com/api"
private fun transformUrl(url: String): String = // dont touch or all votes get reset
MessageDigest
@ -35,12 +27,12 @@ object VotingApi { // please do not cheat the votes lol
return getVotes(url)
}
suspend fun SitePlugin.vote(requestType: VoteType): Int {
return vote(url, requestType)
fun SitePlugin.hasVoted(): Boolean {
return hasVoted(url)
}
fun SitePlugin.getVoteType(): VoteType {
return getVoteType(url)
suspend fun SitePlugin.vote(): Int {
return vote(url)
}
fun SitePlugin.canVote(): Boolean {
@ -50,28 +42,31 @@ object VotingApi { // please do not cheat the votes lol
// Plugin url to Int
private val votesCache = mutableMapOf<String, Int>()
suspend fun getVotes(pluginUrl: String): Int {
val url = "${apiDomain}/get/cs3-votes/${transformUrl(pluginUrl)}"
private fun getRepository(pluginUrl: String) = pluginUrl
.split("/")
.drop(2)
.take(3)
.joinToString("-")
private suspend fun readVote(pluginUrl: String): Int {
var url = "${apiDomain}/cs-${getRepository(pluginUrl)}/vote/${transformUrl(pluginUrl)}?readOnly=true"
Log.d(LOGKEY, "Requesting: $url")
return votesCache[pluginUrl] ?: app.get(url).parsedSafe<Result>()?.value?.also {
votesCache[pluginUrl] = it
} ?: (0.also {
ioSafe {
createBucket(pluginUrl)
return app.get(url).parsedSafe<Result>()?.value ?: 0
}
private suspend fun writeVote(pluginUrl: String): Boolean {
var url = "${apiDomain}/cs-${getRepository(pluginUrl)}/vote/${transformUrl(pluginUrl)}"
Log.d(LOGKEY, "Requesting: $url")
return app.get(url).parsedSafe<Result>()?.value != null
}
suspend fun getVotes(pluginUrl: String): Int =
votesCache[pluginUrl] ?: readVote(pluginUrl).also {
votesCache[pluginUrl] = it
}
})
}
fun getVoteType(pluginUrl: String): VoteType {
return getKey("cs3-votes/${transformUrl(pluginUrl)}") ?: VoteType.NONE
}
private suspend fun createBucket(pluginUrl: String) {
val url =
"${apiDomain}/create?namespace=cs3-votes&key=${transformUrl(pluginUrl)}&value=0&update_lowerbound=-2&update_upperbound=2&enable_reset=0"
Log.d(LOGKEY, "Requesting: $url")
app.get(url)
}
fun hasVoted(pluginUrl: String) =
getKey("cs3-votes/${transformUrl(pluginUrl)}") ?: false
fun canVote(pluginUrl: String): Boolean {
if (!PluginManager.urlPlugins.contains(pluginUrl)) return false
@ -79,7 +74,7 @@ object VotingApi { // please do not cheat the votes lol
}
private val voteLock = Mutex()
suspend fun vote(pluginUrl: String, requestType: VoteType): Int {
suspend fun vote(pluginUrl: String): Int {
// Prevent multiple requests at the same time.
voteLock.withLock {
if (!canVote(pluginUrl)) {
@ -90,33 +85,21 @@ object VotingApi { // please do not cheat the votes lol
return getVotes(pluginUrl)
}
val savedType: VoteType =
getKey("cs3-votes/${transformUrl(pluginUrl)}") ?: VoteType.NONE
val newType = if (requestType == savedType) VoteType.NONE else requestType
val changeValue = if (requestType == savedType) {
-requestType.value
} else if (savedType == VoteType.NONE) {
requestType.value
} else if (savedType != requestType) {
-savedType.value + requestType.value
} else 0
// Pre-emptively set vote key
setKey("cs3-votes/${transformUrl(pluginUrl)}", newType)
val url =
"${apiDomain}/update/cs3-votes/${transformUrl(pluginUrl)}?amount=${changeValue}"
Log.d(LOGKEY, "Requesting: $url")
val res = app.get(url).parsedSafe<Result>()?.value
if (res == null) {
// "Refund" key if the response is invalid
setKey("cs3-votes/${transformUrl(pluginUrl)}", savedType)
} else {
votesCache[pluginUrl] = res
if (hasVoted(pluginUrl)) {
main {
Toast.makeText(context, R.string.already_voted, Toast.LENGTH_SHORT)
.show()
}
return getVotes(pluginUrl)
}
return res ?: 0
if (writeVote(pluginUrl)) {
setKey("cs3-votes/${transformUrl(pluginUrl)}", true)
votesCache[pluginUrl] = votesCache[pluginUrl]?.plus(1) ?: 1
}
return getVotes(pluginUrl)
}
}

View File

@ -13,10 +13,9 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.FragmentPluginDetailsBinding
import com.lagradost.cloudstream3.plugins.PluginManager
import com.lagradost.cloudstream3.plugins.VotingApi
import com.lagradost.cloudstream3.plugins.VotingApi.canVote
import com.lagradost.cloudstream3.plugins.VotingApi.getVoteType
import com.lagradost.cloudstream3.plugins.VotingApi.getVotes
import com.lagradost.cloudstream3.plugins.VotingApi.hasVoted
import com.lagradost.cloudstream3.plugins.VotingApi.vote
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.main
@ -106,7 +105,6 @@ class PluginDetailsFragment(val data: PluginViewData) : BottomSheetDialogFragmen
}
if (!metadata.canVote()) {
downvote.alpha = .6f
upvote.alpha = .6f
}
@ -137,19 +135,11 @@ class PluginDetailsFragment(val data: PluginViewData) : BottomSheetDialogFragmen
upvote.setOnClickListener {
ioSafe {
metadata.vote(VotingApi.VoteType.UPVOTE).main {
metadata.vote().main {
updateVoting(it)
}
}
}
downvote.setOnClickListener {
ioSafe {
metadata.vote(VotingApi.VoteType.DOWNVOTE).main {
updateVoting(it)
}
}
}
ioSafe {
metadata.getVotes().main {
@ -163,33 +153,14 @@ class PluginDetailsFragment(val data: PluginViewData) : BottomSheetDialogFragmen
val metadata = data.plugin.second
binding?.apply {
pluginVotes.text = value.toString()
when (metadata.getVoteType()) {
VotingApi.VoteType.UPVOTE -> {
upvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.colorPrimary) ?: R.color.colorPrimary
)
downvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.white) ?: R.color.white
)
}
VotingApi.VoteType.DOWNVOTE -> {
downvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.colorPrimary) ?: R.color.colorPrimary
)
upvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.white) ?: R.color.white
)
}
VotingApi.VoteType.NONE -> {
upvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.white) ?: R.color.white
)
downvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.white) ?: R.color.white
)
}
if (metadata.hasVoted()) {
upvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.colorPrimary) ?: R.color.colorPrimary
)
} else {
upvote.imageTintList = ColorStateList.valueOf(
context?.colorFromAttribute(R.attr.colorOnSurface) ?: R.color.white
)
}
}
}

View File

@ -284,23 +284,10 @@
android:layout_gravity="center"
android:gravity="center_horizontal|center_vertical">
<ImageView
android:id="@+id/downvote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_thumb_down_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/plugin_votes"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/plugin_votes"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="32dp"
@ -308,7 +295,7 @@
android:text="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/upvote"
app:layout_constraintStart_toEndOf="@+id/downvote"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView

View File

@ -687,4 +687,5 @@
<string name="tv_no_focus_tag" translatable="false">tv_no_focus_tag</string>
<string name="already_voted">You have already voted</string>
</resources>