tywil04 / slavartdl

Simple tool written in Go(lang) to download music using the SlavArt Divolt server
GNU General Public License v3.0
17 stars 1 forks source link

Avoid large REST payloads #22

Closed dxbednarczyk closed 11 months ago

dxbednarczyk commented 1 year ago

I've been spying on this project for a bit after I learned about it while developing my own Slavart downloader. I think I could share something I did differently that could help:

Repeatedly requesting large amounts of previous messages (e.g.) is wasteful and includes messages not related to the current user. It would be more efficient to use websockets and filter incoming messages instead. My implementation could be used as a reference if needed.

tywil04 commented 1 year ago

Thank you for this, I could never find any documentation on the websocket so I decided I would stick to plain old http requests because the documentation was clear and thorough.

I have for the past week been working on rewriting my internal slavart library to make it as generic as possible, so its being renamed to divolt and it will use a session architecture to work, the benefits of this approch means I will in the future be able to add other services that are on divolt. Plus having a session architecture makes my life easier for my in-progress desktop app. I think I will include a similar approch as Limestone in regards to scanning for from divolt.

tywil04 commented 1 year ago

I was just looking at your code, in your GetUploadMessage function you check if message.Type is either Message or MessageUpdate with the switch statement. Your struct for MessageUpdate appears to be incorrect, if this documentation on the event system is correct.

Is the documentation I am using wrong and your code is correct or is it the other way around?

Either way if you have found some documentation on the websocket communication can you share it with me?

dxbednarczyk commented 1 year ago

I eventually got rid of MessageUpdate in later commits, maybe I forgot to push them because I never finished it 😄 It should be the same as the one in the documentation...

struct MessageUpdate {
    type    string  `json:"type"`
    id      string  `json:"id"`
    channel string  `json:"channel"`
    data    Message `json:"data"`
}

In this case the API doesn't send a full Message object, but the data that we need from MessageUpdate's data field should be there.

tywil04 commented 12 months ago

I did end up figuring out the structure of the MessageUpdate data, its a shame that it doesn't provide the message author but it isn't really required to determine if the updated message was the reply to the original command.

I am curious as to why you removed the MessageUpdate handler? It was present so it could detect if an error was thrown by the bot and I don't seem to see any other code that handles this?

dxbednarczyk commented 12 months ago

I never really got past the early stages of getting it to work (farthest I got was just getting it to log the updated message), and eventually I gave up on it, since the error rate at least for me is very minimal. By all means, if you can get it to work it'd be a good change.

tywil04 commented 11 months ago

I have gotten the error handling to work. There are two types of errors that are returned. The first type of error is a reply to the request message, this needs to be caught by the MessageCreate handler. The second type of error message is an edited reply to the request message which needs to handled by the MessageUpdate handler. In both cases, making the string lowercase and checking for the presence of "error" is enough to capture the errors returned by the bot.

tywil04 commented 11 months ago

I have made some large changes and now it uses a websocket instead of making many requests hoping for a reply to be in the response. The bot is now more efficient and quicker.