filwiesner / TmiK

Twitch messaging in Kotlin - Simple DSL for interacting with Twitch chat
MIT License
8 stars 1 forks source link

What is the proper way of making the app join a channel later #3

Closed mkpazon closed 4 years ago

mkpazon commented 4 years ago

First off, I think you've done a really good job in this library. I'd really like to see this to be somewhat of a standard for TMI on Kotlin.

My use case is that I start the server but do not join a channel in onConnected right away. Another event triggers the joining of the channel (eg. an API call). What I have been doing is to store a reference of the mainscope so that later on I can use it to join a channel.

What if tmi(token) { ... } returns an object which exposes an API to join a channel?

 var mainScope: MainScope? = null

.
.
.

tmi(token) {
     mainScope = this <--------------
    + Reconnect(5) // Tries to reconnect for five times if network fails (and re-joins all channels)

     onUserJoin {
         printlnWithThread("onUserJoin ${this.channel}: ${this.username}")
     }

    onMessage {
         println("Message from channel $channel received: $text")
    }

    onConnected {
          // Do no thing.    <------------------ notice that I don't join the channel yet                           
    }
}
.
.
.
  suspend fun joinChannel(channel: String) = coroutineScope {
        launch {
            mainScope?.join(channel)
        }
    }
filwiesner commented 4 years ago

I created this library as a way to learn Kotlin DSL (and for fun) and I am not actively maintaining it anymore. I am still using it for my own Twitch chatbot but I am not planning on adding new features in near future.

EDIT: That does not mean I am not interested in maintaining this lib anymore. I just don't have the time right now. With that said, I am really grateful that someone is using my work and I am willing to help with anything if you have any other questions.

To your issue:
Interesting use case. I guess I never thought about using this with another service.
I think that what you are doing is valid and should work. Just be sure to join channels after the TmiClient is connected and initialized.

Maybe the tmi() function could return reference to MainScope that was created but it would be basically the same as what are you doing right now. Just a little prettier syntax without nullable mainScope variable. But you can initialize MainScope on your own and hold reference to it. Just look at tmi() implementation:

MainScope(
   TmiClient(token, username, secure, context)
      .also(TmiClient::connect)
).apply(block) // block is the "lambda" of tmi function

So you could do something like this:

val tmiClient = TmiClient(token)
val mainScope = MainScope(tmiClient)
tmiClient.connect()
mainScope.apply {
  // This is the same body as with the tmi() function
}
mkpazon commented 4 years ago

And I was about to ask you if you've got plans to make a lib for Twitch's WebSocket PubSub. Lol. I am no Kotlin expert but I do enjoy the language. Heck, every time I think I already know coroutines... the more I use it the more stuff I discover. I've tried other TMI libs and this is my favourite.

Right, thanks for the alternative.

filwiesner commented 4 years ago

PubSub would be different project entirely. I don't think there is some code I could share between TMI and PubSub implementation apart from WebSocket lib dependencies. And I know there are some other Java or JS TMI libraries but all of them feel so boring. They are just bunch of event listeners. I feel like this scope approach is a little bit more elegant