Hopefully fix some hang situations
parent
3deb9be06f
commit
71750ce584
|
@ -41,6 +41,91 @@ pub fn run(ctx: Context, command: ApplicationCommandInteraction) -> CommandOutpu
|
|||
}
|
||||
};
|
||||
|
||||
// Check for Voice Channel permissions
|
||||
{
|
||||
let channel = match ctx.cache.guild_channel(channel_id) {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
respond_message(
|
||||
&ctx,
|
||||
&command,
|
||||
EmbedBuilder::new()
|
||||
.title("Cannot join voice channel")
|
||||
.description("The voice channel you are in is not available")
|
||||
.status(Status::Error)
|
||||
.build(),
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(permissions) =
|
||||
channel.permissions_for_user(&ctx.cache, &ctx.cache.current_user_id())
|
||||
{
|
||||
if !permissions.view_channel() || !permissions.connect() || !permissions.speak() {
|
||||
respond_message(
|
||||
&ctx,
|
||||
&command,
|
||||
EmbedBuilder::new()
|
||||
.title("Cannot join voice channel")
|
||||
.description("I do not have the permissions to connect to that voice channel")
|
||||
.status(Status::Error)
|
||||
.build(),
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Text Channel permissions
|
||||
{
|
||||
let channel = match ctx.cache.guild_channel(&command.channel_id) {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
respond_message(
|
||||
&ctx,
|
||||
&command,
|
||||
EmbedBuilder::new()
|
||||
.title("Cannot join voice channel")
|
||||
.description("The text channel you are in is not available")
|
||||
.status(Status::Error)
|
||||
.build(),
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(permissions) =
|
||||
channel.permissions_for_user(&ctx.cache, &ctx.cache.current_user_id())
|
||||
{
|
||||
if !permissions.view_channel() || !permissions.send_messages() || !permissions.embed_links()
|
||||
{
|
||||
respond_message(
|
||||
&ctx,
|
||||
&command,
|
||||
EmbedBuilder::new()
|
||||
.title("Cannot join voice channel")
|
||||
.description("I do not have the permissions to speak in this text channel")
|
||||
.status(Status::Error)
|
||||
.build(),
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let data = ctx.data.read().await;
|
||||
let mut session_manager = data.get::<SessionManager>().unwrap().clone();
|
||||
|
||||
|
|
|
@ -63,10 +63,6 @@ impl Client {
|
|||
.map_err(IpcError::Bincode)
|
||||
}
|
||||
|
||||
pub fn recv(&self) -> Result<IpcPacket, IpcError> {
|
||||
self.rx.lock().unwrap().recv()
|
||||
}
|
||||
|
||||
pub fn try_recv(&self) -> Result<IpcPacket, TryRecvError> {
|
||||
self.rx.lock().unwrap().try_recv()
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use ipc_channel::ipc::{IpcError, TryRecvError};
|
||||
use librespot::{
|
||||
connect::spirc::Spirc,
|
||||
core::{
|
||||
|
@ -11,7 +14,7 @@ use librespot::{
|
|||
player::{Player, PlayerEvent},
|
||||
},
|
||||
};
|
||||
use log::{debug, error, trace, warn};
|
||||
use log::{debug, error, warn};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
|
@ -56,8 +59,6 @@ impl SpoticordPlayer {
|
|||
session.shutdown();
|
||||
}
|
||||
|
||||
trace!("Creating Spotify session...");
|
||||
|
||||
// Connect the session
|
||||
let (session, _) = match Session::connect(session_config, credentials, None, false).await {
|
||||
Ok((session, credentials)) => (session, credentials),
|
||||
|
@ -106,8 +107,6 @@ impl SpoticordPlayer {
|
|||
let device_id = session.device_id().to_owned();
|
||||
let ipc = self.client.clone();
|
||||
|
||||
trace!("Successfully created Spotify session");
|
||||
|
||||
// IPC Handler
|
||||
tokio::spawn(async move {
|
||||
let client = reqwest::Client::new();
|
||||
|
@ -129,8 +128,6 @@ impl SpoticordPlayer {
|
|||
if resp.status() == 202 {
|
||||
debug!("Successfully switched to device");
|
||||
break;
|
||||
} else {
|
||||
trace!("Device switch failed with status {}", resp.status());
|
||||
}
|
||||
|
||||
retries -= 1;
|
||||
|
@ -219,7 +216,7 @@ impl SpoticordPlayer {
|
|||
});
|
||||
|
||||
self.spirc = Some(spirc);
|
||||
session.spawn(spirc_task);
|
||||
tokio::spawn(spirc_task);
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) {
|
||||
|
@ -242,9 +239,21 @@ pub async fn main() {
|
|||
let mut player = SpoticordPlayer::create(client.clone());
|
||||
|
||||
loop {
|
||||
let message = match client.recv() {
|
||||
let message = match client.try_recv() {
|
||||
Ok(message) => message,
|
||||
Err(why) => {
|
||||
if let TryRecvError::Empty = why {
|
||||
// No message, wait a bit and try again
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
|
||||
continue;
|
||||
} else if let TryRecvError::IpcError(why) = &why {
|
||||
if let IpcError::Disconnected = why {
|
||||
debug!("IPC connection closed, goodbye");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
error!("Failed to receive message: {}", why);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -187,6 +187,7 @@ impl SpoticordSession {
|
|||
continue;
|
||||
} else if let TryRecvError::IpcError(why) = &why {
|
||||
if let IpcError::Disconnected = why {
|
||||
trace!("IPC connection closed, exiting IPC handler");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -457,15 +458,25 @@ impl SpoticordSession {
|
|||
|
||||
/// Called when the player must stop, but not leave the call
|
||||
async fn player_stopped(&mut self) {
|
||||
if let Err(why) = self.track.pause() {
|
||||
error!("Failed to pause track: {:?}", why);
|
||||
}
|
||||
|
||||
// Disconnect from Spotify
|
||||
if let Err(why) = self.client.send(IpcPacket::Disconnect) {
|
||||
error!("Failed to send disconnect packet: {:?}", why);
|
||||
}
|
||||
|
||||
/* So this is really annoying, but necessary.
|
||||
* If we pause songbird too quickly, the player would still have
|
||||
* some audio to write to stdout. Because songbird is paused,
|
||||
* the audio is never read, and the player process will hang.
|
||||
*
|
||||
* So yeah we just blatanly wait a second, and hope that's enough.
|
||||
* Most likely causes issues when the system is a bit slow.
|
||||
*/
|
||||
tokio::time::sleep(Duration::from_millis(1000)).await;
|
||||
|
||||
if let Err(why) = self.track.pause() {
|
||||
error!("Failed to pause track: {:?}", why);
|
||||
}
|
||||
|
||||
// Clear owner
|
||||
let mut owner = self.owner.write().await;
|
||||
if let Some(owner_id) = owner.take() {
|
||||
|
|
|
@ -68,6 +68,7 @@ pub async fn get_username(token: impl Into<String>) -> Result<String, String> {
|
|||
}
|
||||
|
||||
if response.status() != 200 {
|
||||
error!("Failed to get username: {}", response.status());
|
||||
return Err(
|
||||
format!(
|
||||
"Failed to get track info: Invalid status code: {}",
|
||||
|
|
Loading…
Reference in New Issue