Compare commits

..

No commits in common. "api" and "main" have entirely different histories.
api ... main

14 changed files with 17 additions and 511 deletions

279
Cargo.lock generated
View File

@ -236,61 +236,6 @@ dependencies = [
"paste",
]
[[package]]
name = "axum"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http 1.1.0",
"http-body 1.0.1",
"http-body-util",
"hyper 1.4.1",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.1",
"tokio",
"tower 0.5.1",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http 1.1.0",
"http-body 1.0.1",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 1.0.1",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "backtrace"
version = "0.3.74"
@ -707,7 +652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.5",
"hashbrown",
"lock_api",
"once_cell",
"parking_lot_core",
@ -1306,7 +1251,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http 0.2.12",
"indexmap 2.5.0",
"indexmap",
"slab",
"tokio",
"tokio-util",
@ -1325,7 +1270,7 @@ dependencies = [
"futures-core",
"futures-sink",
"http 1.1.0",
"indexmap 2.5.0",
"indexmap",
"slab",
"tokio",
"tokio-util",
@ -1338,16 +1283,10 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f"
dependencies = [
"hashbrown 0.14.5",
"hashbrown",
"serde",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.5"
@ -1657,19 +1596,6 @@ dependencies = [
"webpki-roots 0.26.6",
]
[[package]]
name = "hyper-timeout"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
dependencies = [
"hyper 1.4.1",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.9"
@ -1738,16 +1664,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.5.0"
@ -1755,7 +1671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
dependencies = [
"equivalent",
"hashbrown 0.14.5",
"hashbrown",
]
[[package]]
@ -2192,12 +2108,6 @@ dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "maybe-async"
version = "0.2.10"
@ -2607,7 +2517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset",
"indexmap 2.5.0",
"indexmap",
]
[[package]]
@ -2843,7 +2753,7 @@ checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d"
dependencies = [
"autocfg",
"equivalent",
"indexmap 2.5.0",
"indexmap",
]
[[package]]
@ -2855,59 +2765,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "prost"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-build"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15"
dependencies = [
"bytes",
"heck 0.5.0",
"itertools",
"log",
"multimap",
"once_cell",
"petgraph",
"prettyplease",
"prost",
"prost-types",
"regex",
"syn 2.0.79",
"tempfile",
]
[[package]]
name = "prost-derive"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn 2.0.79",
]
[[package]]
name = "prost-types"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670"
dependencies = [
"prost",
]
[[package]]
name = "protobuf"
version = "3.5.1"
@ -2941,7 +2798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b0e9b447d099ae2c4993c0cbb03c7a9d6c937b17f2d56cfc0b1550e6fcfdb76"
dependencies = [
"anyhow",
"indexmap 2.5.0",
"indexmap",
"log",
"protobuf",
"protobuf-support",
@ -4119,8 +3976,6 @@ dependencies = [
"rustls 0.23.13",
"serenity",
"songbird",
"spoticord_api",
"spoticord_api_grpc",
"spoticord_config",
"spoticord_database",
"spoticord_player",
@ -4128,35 +3983,6 @@ dependencies = [
"spoticord_stats",
"spoticord_utils",
"tokio",
"tonic",
]
[[package]]
name = "spoticord_api"
version = "0.1.0"
dependencies = [
"axum",
"env_logger",
"log",
"prost",
"spoticord_api_grpc",
"spoticord_database",
"spoticord_player",
"spoticord_session",
"thiserror",
"tokio",
"tonic",
]
[[package]]
name = "spoticord_api_grpc"
version = "0.1.0"
dependencies = [
"bytes",
"prost",
"tokio",
"tonic",
"tonic-build",
]
[[package]]
@ -4199,7 +4025,6 @@ dependencies = [
"hex",
"librespot",
"log",
"rand",
"songbird",
"spoticord_audio",
"spoticord_utils",
@ -4820,92 +4645,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "tonic"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
dependencies = [
"async-stream",
"async-trait",
"axum",
"base64 0.22.1",
"bytes",
"h2 0.4.6",
"http 1.1.0",
"http-body 1.0.1",
"http-body-util",
"hyper 1.4.1",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost",
"socket2",
"tokio",
"tokio-stream",
"tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic-build"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11"
dependencies = [
"prettyplease",
"proc-macro2",
"prost-build",
"prost-types",
"quote",
"syn 2.0.79",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand",
"slab",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper 0.1.2",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.3"
@ -5131,7 +4870,7 @@ checksum = "5dece5c06268af6a9ff4541788601e560a4284ffebfb357f713d676f13b964db"
dependencies = [
"chrono",
"dashmap",
"hashbrown 0.14.5",
"hashbrown",
"mini-moka",
"parking_lot",
"secrecy",

View File

@ -17,8 +17,6 @@ members = [
"spoticord_session",
"spoticord_utils",
"spoticord_stats",
"spoticord_api",
"spoticord_api_grpc",
]
[features]
@ -32,8 +30,6 @@ spoticord_player = { path = "./spoticord_player" }
spoticord_session = { path = "./spoticord_session" }
spoticord_utils = { path = "./spoticord_utils" }
spoticord_stats = { path = "./spoticord_stats", optional = true }
spoticord_api = { path = "./spoticord_api"}
spoticord_api_grpc = { path = "./spoticord_api_grpc"}
anyhow = "1.0.86"
dotenvy = "0.15.7"
@ -44,7 +40,6 @@ serenity = "0.12.2"
songbird = { version = "0.4.3", features = ["simd-json"] }
tokio = { version = "1.39.3", features = ["full"] }
rustls = { version = "0.23.13", features = ["aws-lc-rs"] }
tonic = "0.12.3"
[profile.release]
opt-level = 3

View File

@ -1,17 +0,0 @@
[package]
name = "spoticord_api"
version = "0.1.0"
edition = "2021"
[dependencies]
spoticord_database = { path = "../spoticord_database" }
spoticord_session = { path = "../spoticord_session" }
spoticord_api_grpc = { path = "../spoticord_api_grpc"}
spoticord_player = { path = "../spoticord_player"}
prost = "0.13.3"
tokio = {version = "1.38.0", features = ["io-util", "net", "rt-multi-thread"]}
axum = "0.7.5"
env_logger = "0.11.3"
log = "0.4.21"
thiserror = "1.0.61"
tonic = "0.12.3"

View File

@ -1,52 +0,0 @@
use log::info;
use spoticord_api_grpc::spoticord_api::service::{PlayModes, PlayPlaylistRequest};
use spoticord_player::playback_control::{PlayPlaylist, StartAt};
use spoticord_session::manager::{SessionManager, SessionQuery};
use tonic::{Request, Response, Status};
pub struct SpoticordApi {
pub session: SessionManager,
}
#[tonic::async_trait]
impl spoticord_api_grpc::spoticord_api::service::spoticord_api_server::SpoticordApi
for SpoticordApi
{
async fn play_playlist(
&self,
request: Request<PlayPlaylistRequest>,
) -> Result<Response<spoticord_api_grpc::spoticord_api::service::Response>, Status> {
let playlist = request.into_inner();
info!(
"Playing {} for {}",
playlist.playlist_uri, playlist.discord_user_id
);
let session = self
.session
.get_session(SessionQuery::Owner(playlist.discord_user_id.into()))
.unwrap();
let shuffle = match playlist.order() {
PlayModes::Shuffle => true,
PlayModes::InOrder => false,
};
let play_playlist = PlayPlaylist {
uri: playlist.playlist_uri,
shuffle,
repeat: true,
start_at: StartAt::FirstSong,
};
session.queue_playlist(play_playlist).await.unwrap();
let response = spoticord_api_grpc::spoticord_api::service::Response {
resp: Option::from(
spoticord_api_grpc::spoticord_api::service::response::Resp::Success(true),
),
};
Ok(Response::new(response))
}
}

View File

@ -1,13 +0,0 @@
[package]
name = "spoticord_api_grpc"
version = "0.1.0"
edition = "2021"
[dependencies]
bytes = "1.6.0"
tonic = "0.12.3"
prost = "0.13.3"
tokio = {version = "1.38.0", features = ["io-util", "test-util"]}
[build-dependencies]
tonic-build = "0.12.3"

View File

@ -1,6 +0,0 @@
use std::io::Result;
fn main() -> Result<()> {
tonic_build::configure().compile_protos(&["src/service.proto"], &["src/"])?;
Ok(())
}

View File

@ -1,21 +0,0 @@
pub mod spoticord_api {
pub mod service {
include!(concat!(env!("OUT_DIR"), "/spoticord_api.service.rs"));
}
}
#[cfg(test)]
mod test {
use crate::spoticord_api::service::{PlayModes, PlayPlaylistRequest};
#[test]
fn test_build_play_playlist() {
let play_playlist = PlayPlaylistRequest {
order: PlayModes::InOrder.into(),
playlist_uri: "test".to_string(),
};
assert_eq!(play_playlist.playlist_uri, "test");
assert_eq!(play_playlist.order, PlayModes::InOrder.into());
}
}

View File

@ -1,32 +0,0 @@
syntax = "proto3";
package spoticord_api.service;
enum PlayModes {
SHUFFLE = 0;
IN_ORDER = 1;
}
message PlayPlaylistRequest {
uint64 discord_user_id = 1;
PlayModes order = 2;
string playlist_uri = 3;
}
enum Error {
SpotifyError = 0;
BotError = 1;
UserNotRegistered = 2;
}
message Response {
oneof resp {
bool success = 1;
Error error = 2;
}
}
service SpoticordApi {
rpc PlayPlaylist(PlayPlaylistRequest) returns (Response);
}

View File

@ -35,4 +35,8 @@ diesel::table! {
diesel::joinable!(account -> user (user_id));
diesel::joinable!(link_request -> user (user_id));
diesel::allow_tables_to_appear_in_same_query!(account, link_request, user,);
diesel::allow_tables_to_appear_in_same_query!(
account,
link_request,
user,
);

View File

@ -16,4 +16,3 @@ anyhow = "1.0.86"
log = "0.4.22"
symphonia = { version = "0.5.4", default-features = false, features = ["pcm"] }
hex = "0.4.3"
rand = "0.8.5"

View File

@ -1,13 +1,7 @@
pub mod info;
pub mod playback_control;
use crate::playback_control::{PlayPlaylist, StartAt};
use anyhow::Result;
use info::PlaybackInfo;
use librespot::connect::spirc::SpircLoadCommand;
use librespot::core::SpotifyId;
use librespot::metadata::{Metadata, Playlist};
use librespot::protocol::spirc::TrackRef;
use librespot::{
connect::{config::ConnectConfig, spirc::Spirc},
core::{http_client::HttpClientError, Session as SpotifySession, SessionConfig},
@ -20,7 +14,6 @@ use librespot::{
},
};
use log::{error, trace};
use rand::{thread_rng, Rng};
use songbird::{input::RawAdapter, tracks::TrackHandle, Call};
use spoticord_audio::{
sink::{SinkEvent, StreamSink},
@ -41,7 +34,6 @@ enum PlayerCommand {
GetPlaybackInfo(oneshot::Sender<Option<PlaybackInfo>>),
GetLyrics(oneshot::Sender<Option<Lyrics>>),
QueuePlaylist(PlayPlaylist),
Shutdown,
}
@ -221,7 +213,6 @@ impl Player {
PlayerCommand::GetLyrics(tx) => self.get_lyrics(tx).await,
PlayerCommand::Shutdown => self.commands.close(),
PlayerCommand::QueuePlaylist(play_playlist) => self.queue_playlist(play_playlist).await,
};
}
@ -309,42 +300,6 @@ impl Player {
_ = tx.send(Some(lyrics));
}
async fn queue_playlist(&self, playlist_control: PlayPlaylist) {
let playlist = Playlist::get(
&self.session,
&SpotifyId::from_uri(&playlist_control.uri).unwrap(),
)
.await
.unwrap();
let tracks: Vec<_> = playlist
.tracks()
.map(|track_id| {
let mut track = TrackRef::new();
track.set_gid(Vec::from(track_id.to_raw()));
track
})
.collect();
self.spirc.activate().unwrap();
let start_ndx = match playlist_control.start_at {
StartAt::FirstSong => 0u32,
StartAt::Random => thread_rng().gen_range(0..tracks.len()) as u32,
};
self.spirc
.load(SpircLoadCommand {
context_uri: playlist_control.uri,
start_playing: true,
shuffle: playlist_control.shuffle,
repeat: playlist_control.repeat,
playing_track_index: start_ndx,
tracks,
})
.unwrap();
}
}
impl Drop for Player {
@ -399,11 +354,4 @@ impl PlayerHandle {
pub async fn shutdown(&self) {
_ = self.commands.send(PlayerCommand::Shutdown).await;
}
pub async fn queue_playlist(&self, play_playlist: PlayPlaylist) {
self.commands
.send(PlayerCommand::QueuePlaylist(play_playlist))
.await
.unwrap()
}
}

View File

@ -1,13 +0,0 @@
#[derive(Debug, Clone)]
pub enum StartAt {
FirstSong,
Random,
}
#[derive(Debug, Clone)]
pub struct PlayPlaylist {
pub uri: String,
pub shuffle: bool,
pub repeat: bool,
pub start_at: StartAt,
}

View File

@ -17,7 +17,6 @@ use serenity::{
};
use songbird::{model::payload::ClientDisconnect, Call, CoreEvent, Event, EventContext};
use spoticord_database::Database;
use spoticord_player::playback_control::PlayPlaylist;
use spoticord_player::{Player, PlayerEvent, PlayerHandle};
use spoticord_utils::{discord::Colors, spotify};
use std::{ops::ControlFlow, sync::Arc, time::Duration};
@ -43,7 +42,6 @@ pub enum SessionCommand {
ShutdownPlayer,
Disconnect,
DisconnectTimedOut,
QueuePlaylist(PlayPlaylist),
}
pub struct Session {
@ -238,6 +236,7 @@ impl Session {
SessionCommand::GetOwner(sender) => _ = sender.send(self.owner),
SessionCommand::GetPlayer(sender) => _ = sender.send(self.player.clone()),
SessionCommand::GetActive(sender) => _ = sender.send(self.active),
SessionCommand::CreatePlaybackEmbed(handle, interaction, behavior) => {
match PlaybackEmbed::create(self, handle, interaction, behavior).await {
Ok(opt_handle) => {
@ -291,9 +290,6 @@ impl Session {
return ControlFlow::Break(());
}
SessionCommand::QueuePlaylist(play_playlist) => {
self.player.queue_playlist(play_playlist).await;
}
};
ControlFlow::Continue(())
@ -555,14 +551,6 @@ impl SessionHandle {
error!("Failed to send command: {why}");
}
}
pub async fn queue_playlist(&self, play_playlist: PlayPlaylist) -> Result<()> {
self.commands
.send(SessionCommand::QueuePlaylist(play_playlist))
.await?;
Ok(())
}
}
#[async_trait]

View File

@ -4,7 +4,6 @@ use anyhow::{anyhow, Result};
use log::{debug, info};
use poise::{serenity_prelude, Framework, FrameworkContext, FrameworkOptions};
use serenity::all::{ActivityData, FullEvent, Ready, ShardManager};
use spoticord_api::SpoticordApi;
use spoticord_database::Database;
use spoticord_session::manager::SessionManager;
@ -85,7 +84,7 @@ async fn event_handler(
ctx: &serenity_prelude::Context,
event: &FullEvent,
_framework: FrameworkContext<'_, Data, anyhow::Error>,
data: &Data,
_data: &Data,
) -> Result<()> {
if let FullEvent::Ready { data_about_bot } = event {
if let Some(shard) = data_about_bot.shard {
@ -96,19 +95,7 @@ async fn event_handler(
}
ctx.set_activity(Some(ActivityData::listening(spoticord_config::MOTD)));
let api_server = SpoticordApi {
session: data.clone(),
};
tokio::spawn(async move {
tonic::transport::Server::builder()
.add_service(spoticord_api_grpc::spoticord_api::service::spoticord_api_server::SpoticordApiServer::new(api_server))
.serve("127.0.0.1:8080".parse().unwrap())
.await
.unwrap();
});
};
}
Ok(())
}