Kotlin discord jda cannot get message by id - kotlin

I am trying to get the message by entering the id of the message. I saw this being done in an example but it used the old discordjda, when I tried now I get this wierd error and i dont know how to solve it. I tried casting it to different values with no succes
e.channel.history.getMessageById(userMessageFunction.b) {
m ->
if (e.message.timeCreated.isAfter(m.creationTime)) {
userMessageFunction.c.accept(e.message)
messageInteractivesQueue.remove(interactive)
}
}
This is the error

In your code, that brace after userMessageFunction.b is consideredas lambda expression, so your code is same as this code.
e.channel.history.getMessageById(userMessageFunction.b, m -> {
if (e.message.timeCreated.isAfter(m.creationTime)) {
userMessageFunction.c.accept(e.message)
messageInteractivesQueue.remove(interactive)
}
})
If you want to get message, use channel#retrieveMessageById.
So you can change your code like this.
e.channel.retrieveMessageById(userMessageFunction.b).queue {
if (e.message.timeCreated.isAfter(it.creationTime)) {
userMessageFunction.c.accept(e.message)
messageInteractivesQueue.remove(interactive)
}
}
Or this
e.channel.history.getMessageById(userMessageFunction.b).let {
if (e.message.timeCreated.isAfter(it.creationTime)) {
userMessageFunction.c.accept(e.message)
messageInteractivesQueue.remove(interactive)
}
}

Related

Why is the value not entering the list?

At 'urichecking2' log, I can see there is value. But in 'uriChecking' the uriList is null.
why the uriList.add not work??
private fun getPhotoList() {
val fileName = intent.getStringExtra("fileName")
Log.d("fileNameChecking", "$fileName")
val listRef = FirebaseStorage.getInstance().reference.child("image").child(fileName!!)
var tmpUrl:Uri = Uri.parse(fileName)
Log.d("firstTmpUri","$tmpUrl")
listRef.listAll()
.addOnSuccessListener { listResult ->
for (item in listResult.items) {
item.downloadUrl.addOnCompleteListener { task ->
if (task.isSuccessful) {
tmpUrl = task.result
Log.d("secondTmpUri","$tmpUrl")
Log.d("urichecking2","$task.result")
uriList.add(task.result)
} else {
}
}.addOnFailureListener {
// Uh-oh, an error occurred!
}
}
}
Log.d("thirdTmpUri","$tmpUrl")
Log.d("urichecking", "$uriList")
}
If I do this, the log is output in the order of first, third, and second, and the desired value is in second, but when third comes out, it returns to the value of first.
The listAll method (like most cloud APIs these days, including downloadUrl which you also use) is asynchronous, since it needs to make a call to the server - which may take time. This means the code executes in a different order than you may expect, which is easiest to see if you add some logging:
Log.d("Firebase","Before starting listAll")
listRef.listAll()
.addOnSuccessListener { listResult ->
Log.d("Firebase","Got listResult")
}
Log.d("Firebase","After starting listAll")
When you run this code it outputs:
Before starting listAll
After starting listAll
Got listResult
This is probably not the order you expected, but it perfectly explains why you can't see the list result. By the time your Log.d("urichecking", "$uriList") runs, none of the uriList.add(task.result) has been called yet.
The solution for this is always the same: any code that needs the list result, has to be inside the addOnCompleteListener callback, be called from there, or be otherwise synchronized.
So in its simplest way:
listRef.listAll()
.addOnSuccessListener { listResult ->
for (item in listResult.items) {
item.downloadUrl.addOnCompleteListener { task ->
if (task.isSuccessful) {
uriList.add(task.result)
Log.d("urichecking", "$uriList")
}
}
}
}
This is an incredibly common mistake to make if you're new to programming with asynchronous APIs, so I recommend checking out
Asynchronous programming techniques in the Kotlin language guide
How to get URL from Firebase Storage getDownloadURL
Can someone help me with logic of the firebase on success listener
Why does my function that calls an API or launches a coroutine return an empty or null value?

Implement retry logic with Mutiny

I'm just learning Mutiny and I need to implement retry logic.
I have this code:
fun main() {
getResult()
.onFailure().invoke { t -> println("Got error: $t") }
.onFailure().retry().atMost(2)
.subscribe().with(
{ result -> println(result) },
{ t -> t.printStackTrace() }
)
}
fun getResult(): Uni<String?> {
println("Preparing result...")
return Uni.createFrom().failure(Exception("Some error happened"))
}
So, the getResult() is a function that may misbehave and needs to be called multiple times on failure.
When I run this program, this is what's happening:
Preparing result...
Got error: java.lang.Exception: Some error happened
Got error: java.lang.Exception: Some error happened
Got error: java.lang.Exception: Some error happened
java.lang.Exception: Some error happened
at MainKt.getResult(Main.kt:16)
at MainKt.main(Main.kt:4)
Obiously, the getResult() function is called only once, while the onFailure() stages actually executed three times.
Is there anything that Mutiny could help me to execute getResult() function on each failure? I sure can implement this with a simple loop, but I feel like Mutiny should already have something like this.
Unfortunately, I didn't find anything suitable in the docs.
Your Uni in getResult is created with an "immediate" item, which is cached and never computed again.
Use Uni.createFrom().failure(() -> Exception("Some error happened"))
In this case, it's a supplier, so it won't be cached but called on every attempt.
So, the right solution for this is actually using the Uni.deferred() method like this:
fun main() {
Uni.createFrom().deferred { getResult() }
.onFailure().invoke { t -> println("Got error: $t") }
.onFailure().retry().atMost(2)
.subscribe().with(
{ result -> println(result) },
{ t -> t.printStackTrace() }
)
}
Thanks to Boris the Spider, who suggested to use the deferred(), and to Clement, who clarified its use with null values.
Initially, I misinterpreted the deferred() documentation thinking it's not allowed to return a null value, but actually it's OK for a Supplier to return a Uni of null:
Uni.createFrom.deferred { Uni.createFrom().nullItem() }
What the docs really are prohibiting is returning a null instead of a Uni:
Uni.createFrom().deferred { null }

Kotlin ConflatedBroadcastChannel.offer() doesn't work?

I am sending a value via MyRepository.myConflatedChannel.offer(myvalue).
I then expect to receive it in collect { } or onEach { } blocks in my ViewModel. However, neither function is invoked. It is as if nothing is passed down the ConflatedBroadcastChannel.
Has anybody seen a similar problem?
Make sure you properly work with receiving values.
If you use the ConflatedBroadcastChannel, you can use either OpenSubscription to get a ReceiveChannel or you can represent it as flow (with asFlow).
Note that consume and consumeEach are terminal, they perform an action and then cancel the channel after the execution of the block. See this.
First case:
val receivingChannel = MyRepository.myConflatedChannel.openSubscription()
// then you can consume values using for example a for loop, e.g.:
launch {
for (value in receivingChannel) {
// do something
}
}
Second case:
val receivingFlow = MyRepository.myConflatedChannel.asFlow()
launch {
receivingFlow.collect {
// do something
}
}

Add onClick to Button in Ktor with Kotlinx

I am currently trying out Ktor. But it already fails on registering a onClickListener to the button.
I am just wondering because the onClick extends from String. If I click on the onClick the Code I get is this one:
var CommonAttributeGroupFacade.onClick : String
get() = attributeStringString.get(this, "onclick")
set(newValue) {attributeStringString.set(this, "onclick", newValue)}
So I think onClick has a getter and setter but not more. I installed location and FreeMarker so this is my route:
get<CharityRoute> {
val id = it.id
call.respondHtml {
body {
h1 { +"${it.id}" }
ul {
for (n in it.list) {
li { +"$n" }
}
}
button {
text("Run function")
onClick = "Hello"
}
}
}
}
Maybe someone has more experience with Ktor and especially with Kotlinx.
Problem
It depends which module you are working in.
On the server-side (JVM) you can not write Javascript-Code in Kotlin and assign it to a function like that.
To find a solution, I have to further know, what exactly it is you want to achieve.
Here are two of many possibilities, what you could do:
Solution 1
You can assign a javascript-code as string. You did just that by assigning the code "Hello".
Maybe you want to call a function, which was globally made available in the window object?
Solution 2
In client-side JS code, you can import kotlinx.html.js.onClickFunction and simply write
button{
onClickFunction = { println("clicked") }
}
to execute code written in Kotlin.

Kotlin: lambda run alternative scenario

I have userDto, contains programs, which contains actual field. Actual program can be only one. I need to get it. Than, I run this:
userDto.programs.sortedBy { it.created }.findLast { it.actual }?
Okay, but I want to foresee case, when findLast returns null, & throw exception. Please, advice, how to do it?
UPD:
ProgramType.valueOf(userDto.programs
.sortedBy { it.created }
.findLast { it.actual }
//check here
!!.programType!!).percentage
You are pretty close actually :)! What you could do is:
userDto.programs.sortedBy { it.created }.findLast { it.actual } ?: throw RuntimeException()
Or if you're trying to actually avoid throwing an error(couldn't really tell with the way question is asked), you could just do an error check like this:
userDto.programs.sortedBy { it.created }.findLast { it.actual }?.let{
//rest of your code goes here
}
Hope this helps, cheers!