h3poteto/megalodon-rs

Unable to connect to Mastodon streams

Closed this issue · 4 comments

I'm trying to connect to a streaming endpoint for Mastodon (mastodon.social specifically) and I'm unable to get it to work successfully. My code is almost exactly as the example for streaming is:

async fn start(token: String, url: String) -> Result<(), Box<dyn std::error::Error>>
{
    let client = megalodon::generator(
        megalodon::SNS::Mastodon,
        url.to_string(),
        Some(token),
        None,
    );
    let account = client.verify_account_credentials().await?.json;
    println!("Connected as {}", account.display_name);

    println!("Connecting stream {}", url);
    let streaming = client.local_streaming(url.to_string());
    streaming
        .listen(Box::new(|message| match message
        {
            Message::Update(status) =>
            {
                println!("status {:#?}", status);
            }
            Message::Notification(notification) =>
            {
                println!("notification {:#?}", notification);
            }
            Message::Conversation(conversation) =>
            {
                println!("conversation {:#?}", conversation);
            }
            Message::Delete(status) =>
            {
                println!("status {:#?}", status);
            }
            Message::StatusUpdate(status) =>
            {
                println!("status {:#?}", status);
            }
            Message::Heartbeat() =>
            {
                println!("Heartbeat");
            }
        }))
        .await;

    return Ok(());
}

url is "https://mastodon.social" and the token I use has complete read and write access to the account. When using "https://mastodon.social" I get the error [ERROR megalodon::mastodon::web_socket] Failed to connect: URL error: URL scheme not supported. I also tried manually setting the local_streaming URL specifically to "wss://mastodon.social" and I get the error: [ERROR megalodon::mastodon::web_socket] Failed to connect: HTTP error: 301 Moved Permanently.

I also tried to the example verbatim in a new project and encountered the same issues. I'd imagine I'm just using the wrong URLs or something? Is there a reason the streaming URL can't be inferred from the client? I'm relatively new to Rust, so I could also just be missing something obvious. Thanks!

As a sidenote, it wasn't immediately clear to me that I needed to use and call env_logger::init(); to get any logging, so it was very frustrating trying to figure out what was going on before I took a look at the examples because it would just silently fail. Either noting this requirement in the README or using some sort of default log method to stdout if env_logger isn't initialized would be nice.

Please get streaming endpoint from https://mastodon.social/api/v1/instance
In your example, please pass wss://streaming.mastodon.social to url in generator method.

Great, thanks! I figured it was just the wrong URL.

Is there a reason why that couldn't be assumed from within the local_streaming function (and the other streaming functions)? Like:

    async fn local_streaming(&self) -> Box<dyn Streaming + Send + Sync> {
        let params = Vec::<String>::new();
        let instance = self.get_instance().await;
        let mut streaming_url = self.base_url.clone();
        if let Ok(instance) = instance {
            match instance.json.urls {
                Some(urls) => streaming_url = urls.streaming_api.clone(),
                _ => {}
            };
        }

        let c = WebSocket::new(
            streaming_url + "/api/v1/streaming",
            String::from("public:local"),
            Some(params),
            self.access_token.clone(),
            self.user_agent.clone(),
        );

        Box::new(c)
    }

Hmm, that's good too.

If it's a reasonable change, I created a PR with it here: #204

I'll close this issue since the problem is solved either way