mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
fix voting api (#544)
This commit is contained in:
parent
bbbb7c4982
commit
44a2146c12
4 changed files with 54 additions and 112 deletions
|
@ -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 {
|
||||
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
|
||||
} ?: (0.also {
|
||||
ioSafe {
|
||||
createBucket(pluginUrl)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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 res ?: 0
|
||||
return getVotes(pluginUrl)
|
||||
}
|
||||
|
||||
|
||||
if (writeVote(pluginUrl)) {
|
||||
setKey("cs3-votes/${transformUrl(pluginUrl)}", true)
|
||||
votesCache[pluginUrl] = votesCache[pluginUrl]?.plus(1) ?: 1
|
||||
}
|
||||
|
||||
return getVotes(pluginUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,34 +153,15 @@ class PluginDetailsFragment(val data: PluginViewData) : BottomSheetDialogFragmen
|
|||
val metadata = data.plugin.second
|
||||
binding?.apply {
|
||||
pluginVotes.text = value.toString()
|
||||
when (metadata.getVoteType()) {
|
||||
VotingApi.VoteType.UPVOTE -> {
|
||||
if (metadata.hasVoted()) {
|
||||
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
|
||||
)
|
||||
} else {
|
||||
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
|
||||
context?.colorFromAttribute(R.attr.colorOnSurface) ?: R.color.white
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue