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

Seen, Playtime Commands + 2b2t queue API update #524

Merged
merged 3 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.lambda.client.command.commands

import com.google.gson.JsonParser
import com.lambda.client.command.ClientCommand
import com.lambda.client.commons.utils.ConnectionUtils
import com.lambda.client.commons.utils.grammar
import com.lambda.client.manager.managers.UUIDManager
import com.lambda.client.util.text.MessageSendHelper
import kotlin.time.DurationUnit
import kotlin.time.toDuration

object PlaytimeCommand: ClientCommand(
name = "playtime",
alias = arrayOf("pt"),
description = "Check a player's playtime on 2b2t"
) {
private val parser = JsonParser()

init {
string("playerName") { playerName ->
executeAsync("Check a player's playtime on 2b2t") {
UUIDManager.getByName(playerName.value)?.let outer@ { profile ->
ConnectionUtils.requestRawJsonFrom("https://api.2b2t.vc/playtime?uuid=${profile.uuid}") {
MessageSendHelper.sendChatMessage("Failed querying playtime data for player: ${it.message}")
}?.let {
if (it.isEmpty()) {
MessageSendHelper.sendChatMessage("No data found for player: ${profile.name}")
return@outer
}
val jsonElement = parser.parse(it)
val playtimeSeconds = jsonElement.asJsonObject["playtimeSeconds"].asDouble
MessageSendHelper.sendChatMessage("${profile.name} has played for ${
playtimeSeconds.toDuration(DurationUnit.SECONDS)
}")
}

return@executeAsync
}

MessageSendHelper.sendChatMessage("Failed to find player with name ${playerName.value}")
}
}
}
}
45 changes: 45 additions & 0 deletions src/main/kotlin/com/lambda/client/command/commands/SeenCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.lambda.client.command.commands

import com.google.gson.JsonParser
import com.lambda.client.command.ClientCommand
import com.lambda.client.commons.utils.ConnectionUtils
import com.lambda.client.manager.managers.UUIDManager
import com.lambda.client.util.text.MessageSendHelper
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

object SeenCommand : ClientCommand(
name = "seen",
alias = arrayOf("lastseen"),
description = "Check when a player was last seen"
) {

private val parser = JsonParser()

init {
string("playerName") { playerName ->
executeAsync("Check when a player was last seen") {
UUIDManager.getByName(playerName.value)?.let outer@ { profile ->
ConnectionUtils.requestRawJsonFrom("https://api.2b2t.vc/seen?uuid=${profile.uuid}") {
MessageSendHelper.sendChatMessage("Failed querying seen data for player: ${it.message}")
}?.let {
if (it.isEmpty()) {
MessageSendHelper.sendChatMessage("No data found for player: ${profile.name}")
return@outer
}
val jsonElement = parser.parse(it)
val dateRaw = jsonElement.asJsonObject["time"].asString
val parsedDate = ZonedDateTime.parse(dateRaw).withZoneSameInstant(ZoneId.systemDefault())
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.LONG)
MessageSendHelper.sendChatMessage("${profile.name} was last seen on ${parsedDate.format(dateFormatter)}")
}

return@executeAsync
}

MessageSendHelper.sendChatMessage("Failed to find player with name ${playerName.value}")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package com.lambda.client.commons.utils

import com.lambda.client.module.modules.client.Plugins
import java.net.HttpURLConnection
import java.net.URL
import javax.net.ssl.HttpsURLConnection

object ConnectionUtils {

fun requestRawJsonFrom(url: String, catch: (Exception) -> Unit = { it.printStackTrace() }): String? {
return runConnection(url, { connection ->
connection.setRequestProperty("User-Agent", "LambdaClient")
connection.setRequestProperty("Connection", "close")
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8")
if (Plugins.token.isNotBlank()) connection.setRequestProperty("Authorization", "token ${Plugins.token}")
connection.requestMethod = "GET"
connection.inputStream.readBytes().toString(Charsets.UTF_8)
}, catch)
}

fun <T> runConnection(url: String, block: (HttpsURLConnection) -> T?, catch: (Exception) -> Unit = { it.printStackTrace() }): T? {
(URL(url).openConnection() as HttpsURLConnection).run {
fun <T> runConnection(url: String, block: (HttpURLConnection) -> T?, catch: (Exception) -> Unit = { it.printStackTrace() }): T? {
(URL(url).openConnection() as HttpURLConnection).run {
return try {
doOutput = true
doInput = true
Expand All @@ -29,5 +31,4 @@ object ConnectionUtils {
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package com.lambda.client.gui.hudgui.elements.misc

import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.lambda.client.LambdaMod
import com.lambda.client.commons.utils.ConnectionUtils
import com.lambda.client.commons.utils.grammar
import com.lambda.client.event.SafeClientEvent
import com.lambda.client.gui.hudgui.LabelHud
import com.lambda.client.manager.managers.NetworkManager
import com.lambda.client.util.CachedValue
import com.lambda.client.util.TickTimer
import com.lambda.client.util.TimeUnit
import com.lambda.client.util.WebUtils
import com.lambda.client.util.text.MessageSendHelper
import com.lambda.client.util.threads.defaultScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.time.Instant
import java.time.ZonedDateTime

internal object Queue2B2T : LabelHud(
name = "2B2T Queue",
Expand All @@ -22,22 +24,26 @@ internal object Queue2B2T : LabelHud(
) {
private val hasShownWarning = setting("Has Shown Warning", false, { false })
private val show by setting("Show", Show.BOTH)
private val showUpdatedTime by setting("Show Updated Time", true)

private enum class Show {
BOTH, PRIORITY, REGULAR
}

private const val apiUrl = "https://2bqueue.info/queue"
private const val apiUrl = "https://api.2b2t.vc/queue"

private val gson = Gson()
private val dataUpdateTimer = TickTimer(TimeUnit.SECONDS)
private var hasInitialized = false

private var queueData = QueueData(0, 0, 0, 0)
private var queueData = QueueData(0, 0, ZonedDateTime.now().toString())
private val lastUpdate by CachedValue(1L, TimeUnit.SECONDS) {
val difference = System.currentTimeMillis() - queueData.lastUpdated
val dateRaw = queueData.time
val parsedDate = ZonedDateTime.parse(dateRaw)
val difference = Instant.now().epochSecond - parsedDate.toEpochSecond()

val minuteAmt = (difference / 60000L % 60L).toInt()
val secondAmt = (difference / 1000L % 60L).toInt()
val minuteAmt = (difference / 60L % 60L).toInt()
val secondAmt = (difference % 60L).toInt()
val minutes = grammar(minuteAmt, "minute", "minutes")
val seconds = grammar(secondAmt, "second", "seconds")

Expand All @@ -53,44 +59,54 @@ internal object Queue2B2T : LabelHud(
sendWarning()
}

if (dataUpdateTimer.tick(15L)) {
if (dataUpdateTimer.tick(300L) // API caches queue data for 5 minutes
|| !hasInitialized) {
hasInitialized = true
updateQueueData()
}

if (NetworkManager.isOffline) {
displayText.addLine("Cannot connect to 2bqueue.info", primaryColor)
displayText.addLine("Cannot connect to api.2b2t.vc", primaryColor)
displayText.add("Make sure your internet is working!", primaryColor)
} else {
if (showPriority) {
displayText.add("Priority: ", primaryColor)
displayText.add("${queueData.priority}", secondaryColor)
}
return
}

if (showRegular) {
displayText.add("Regular: ", primaryColor)
displayText.add("${queueData.regular}", secondaryColor)
}
if (showPriority) {
displayText.add("Priority: ", primaryColor)
displayText.add("${queueData.prio}", secondaryColor)
}

if (showRegular) {
displayText.add("Regular: ", primaryColor)
displayText.add("${queueData.regular}", secondaryColor)
}
if (showUpdatedTime) {
displayText.addLine("", primaryColor)
displayText.add("Last updated $lastUpdate ago", primaryColor)
}
}

private fun sendWarning() {
MessageSendHelper.sendWarningMessage(
"This module uses an external API, 2bqueue.info, which is operated by tycrek#0001." +
"If you do not trust this external API / have not verified the safety yourself, disable this HUD component."
"This module uses an external API, api.2b2t.vc, which is operated by rfresh#2222." +
" If you do not trust this external API / have not verified the safety yourself, disable this HUD component."
)
hasShownWarning.value = true
}

private fun updateQueueData() {
defaultScope.launch(Dispatchers.IO) {
runCatching {
val json = WebUtils.getUrlContents(apiUrl)
gson.fromJson(json, QueueData::class.java)
}.getOrNull()?.let {
queueData = it
ConnectionUtils.requestRawJsonFrom(apiUrl) {
LambdaMod.LOG.error("Failed querying queue data", it)
}?.let {
gson.fromJson(it, QueueData::class.java)?.let { data ->
queueData = data
return@runCatching
}

LambdaMod.LOG.error("No queue data received. Is 2b2t down?")
}
}
}
}
Expand All @@ -99,11 +115,8 @@ internal object Queue2B2T : LabelHud(
private val showRegular get() = show == Show.BOTH || show == Show.REGULAR

private class QueueData(
@SerializedName("prio")
val priority: Int,
val prio: Int,
val regular: Int,
val total: Int,
@SerializedName("timems")
val lastUpdated: Long
val time: String
)
}