changes
This commit is contained in:
parent
f67be1d367
commit
c12b4787ca
3 changed files with 258 additions and 183 deletions
73
src/actions.rs
Normal file
73
src/actions.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::structs::{IsPlayingResponse, NowPlayingResponse};
|
||||
|
||||
pub fn get_now_playing() -> Result<NowPlayingResponse, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/now-playing";
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = reqwest::blocking::get(URL)?;
|
||||
|
||||
let data: NowPlayingResponse = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn toggle_playpause() -> Result<serde_json::Value, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/playpause";
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = client.post(URL).send()?;
|
||||
|
||||
let data = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn skip() -> Result<serde_json::Value, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/next";
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = client.post(URL).send()?;
|
||||
|
||||
let data = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn like() -> Result<serde_json::Value, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/set-rating";
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct RatingBody {
|
||||
rating: i32,
|
||||
}
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = client
|
||||
.post(URL)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&RatingBody { rating: 1 }).unwrap())
|
||||
.send()?;
|
||||
|
||||
let data = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn get_is_playing() -> Result<IsPlayingResponse, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/is-playing";
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = reqwest::blocking::get(URL)?;
|
||||
|
||||
let data: IsPlayingResponse = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
207
src/main.rs
207
src/main.rs
|
|
@ -6,168 +6,15 @@ use std::{
|
|||
use clap::{Parser, Subcommand};
|
||||
use crossbeam_channel::unbounded;
|
||||
use rust_socketio::{ClientBuilder, Payload};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, info};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlaybackUpdate {
|
||||
pub data: Data,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
}
|
||||
use crate::{
|
||||
actions::{get_is_playing, get_now_playing, like, skip, toggle_playpause},
|
||||
structs::{PlaybackUpdate, StatusUpdate},
|
||||
};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
#[serde(rename = "currentPlaybackDuration")]
|
||||
pub current_playback_duration: Option<f64>,
|
||||
#[serde(rename = "currentPlaybackTime")]
|
||||
pub current_playback_time: Option<f64>,
|
||||
#[serde(rename = "currentPlaybackTimeRemaining")]
|
||||
pub current_playback_time_remaining: Option<f64>,
|
||||
#[serde(rename = "isPlaying")]
|
||||
pub is_playing: Option<bool>,
|
||||
#[serde(rename = "albumName")]
|
||||
pub album_name: Option<String>,
|
||||
#[serde(rename = "artistName")]
|
||||
pub artist_name: Option<String>,
|
||||
pub artwork: Option<Artwork>,
|
||||
#[serde(rename = "audioLocale")]
|
||||
pub audio_locale: Option<String>,
|
||||
#[serde(rename = "audioTraits")]
|
||||
pub audio_traits: Option<Vec<String>>,
|
||||
#[serde(rename = "composerName")]
|
||||
pub composer_name: Option<String>,
|
||||
#[serde(rename = "discNumber")]
|
||||
pub disc_number: Option<i64>,
|
||||
#[serde(rename = "durationInMillis")]
|
||||
pub duration_in_millis: Option<i64>,
|
||||
#[serde(rename = "genreNames")]
|
||||
#[serde(default)]
|
||||
pub genre_names: Vec<String>,
|
||||
#[serde(rename = "hasLyrics")]
|
||||
pub has_lyrics: Option<bool>,
|
||||
#[serde(rename = "hasTimeSyncedLyrics")]
|
||||
pub has_time_synced_lyrics: Option<bool>,
|
||||
#[serde(rename = "isAppleDigitalMaster")]
|
||||
pub is_apple_digital_master: Option<bool>,
|
||||
#[serde(rename = "isMasteredForItunes")]
|
||||
pub is_mastered_for_itunes: Option<bool>,
|
||||
#[serde(rename = "isVocalAttenuationAllowed")]
|
||||
pub is_vocal_attenuation_allowed: Option<bool>,
|
||||
pub isrc: Option<String>,
|
||||
pub name: Option<String>,
|
||||
#[serde(rename = "playParams")]
|
||||
pub play_params: Option<PlayParams>,
|
||||
#[serde(default)]
|
||||
pub previews: Vec<Preview>,
|
||||
#[serde(rename = "releaseDate")]
|
||||
pub release_date: Option<String>,
|
||||
#[serde(rename = "remainingTime")]
|
||||
pub remaining_time: Option<f64>,
|
||||
#[serde(rename = "trackNumber")]
|
||||
pub track_number: Option<i64>,
|
||||
pub url: Option<String>,
|
||||
pub attributes: Option<Attributes>,
|
||||
pub state: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Artwork {
|
||||
pub height: i64,
|
||||
pub url: String,
|
||||
pub width: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlayParams {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Preview {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Attributes {
|
||||
#[serde(rename = "albumName")]
|
||||
pub album_name: String,
|
||||
#[serde(rename = "artistName")]
|
||||
pub artist_name: String,
|
||||
pub artwork: Artwork2,
|
||||
#[serde(rename = "audioLocale")]
|
||||
pub audio_locale: String,
|
||||
#[serde(rename = "audioTraits")]
|
||||
pub audio_traits: Vec<String>,
|
||||
#[serde(rename = "composerName")]
|
||||
pub composer_name: String,
|
||||
#[serde(rename = "currentPlaybackTime")]
|
||||
pub current_playback_time: f64,
|
||||
#[serde(rename = "discNumber")]
|
||||
pub disc_number: i64,
|
||||
#[serde(rename = "durationInMillis")]
|
||||
pub duration_in_millis: i64,
|
||||
#[serde(rename = "genreNames")]
|
||||
pub genre_names: Vec<String>,
|
||||
#[serde(rename = "hasLyrics")]
|
||||
pub has_lyrics: bool,
|
||||
#[serde(rename = "hasTimeSyncedLyrics")]
|
||||
pub has_time_synced_lyrics: bool,
|
||||
#[serde(rename = "isAppleDigitalMaster")]
|
||||
pub is_apple_digital_master: bool,
|
||||
#[serde(rename = "isMasteredForItunes")]
|
||||
pub is_mastered_for_itunes: bool,
|
||||
#[serde(rename = "isVocalAttenuationAllowed")]
|
||||
pub is_vocal_attenuation_allowed: bool,
|
||||
pub isrc: String,
|
||||
pub name: String,
|
||||
#[serde(rename = "playParams")]
|
||||
pub play_params: PlayParams2,
|
||||
pub previews: Vec<Preview2>,
|
||||
#[serde(rename = "releaseDate")]
|
||||
pub release_date: String,
|
||||
#[serde(rename = "remainingTime")]
|
||||
pub remaining_time: f64,
|
||||
#[serde(rename = "trackNumber")]
|
||||
pub track_number: i64,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Artwork2 {
|
||||
pub height: i64,
|
||||
pub url: String,
|
||||
pub width: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlayParams2 {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Preview2 {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct NowPlayingResponse {
|
||||
info: Data,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct IsPlayingResponse {
|
||||
is_playing: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
struct StatusUpdate {
|
||||
text: String,
|
||||
tooltip: String,
|
||||
class: Vec<String>,
|
||||
}
|
||||
mod actions;
|
||||
mod structs;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
|
|
@ -178,6 +25,13 @@ struct Cli {
|
|||
|
||||
#[derive(Subcommand, Clone, Debug)]
|
||||
enum Commands {
|
||||
/// Like the current song.
|
||||
Like,
|
||||
/// Skip the current song.
|
||||
Skip,
|
||||
/// Toggle play/pause.
|
||||
PlayPause,
|
||||
|
||||
/// Monitor song changes from Cider
|
||||
Monitor,
|
||||
}
|
||||
|
|
@ -261,35 +115,22 @@ fn setup_ctrlc_handler() -> crossbeam_channel::Receiver<()> {
|
|||
receiver
|
||||
}
|
||||
|
||||
fn get_now_playing() -> Result<NowPlayingResponse, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/now-playing";
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = reqwest::blocking::get(URL)?;
|
||||
|
||||
let data: NowPlayingResponse = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn get_is_playing() -> Result<IsPlayingResponse, reqwest::Error> {
|
||||
const URL: &str = "http://localhost:10767/api/v1/playback/is-playing";
|
||||
|
||||
// This call blocks until the request is complete.
|
||||
let response = reqwest::blocking::get(URL)?;
|
||||
|
||||
let data: IsPlayingResponse = response.json()?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
tracing_subscriber::fmt().pretty().init();
|
||||
// color_eyre::install()?;
|
||||
// tracing_subscriber::fmt().pretty().init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
match &cli.command {
|
||||
Some(Commands::Like) => {
|
||||
like()?;
|
||||
}
|
||||
Some(Commands::Skip) => {
|
||||
skip()?;
|
||||
}
|
||||
Some(Commands::PlayPause) => {
|
||||
toggle_playpause()?;
|
||||
}
|
||||
Some(Commands::Monitor) => {
|
||||
let ctrlc_receiver = setup_ctrlc_handler();
|
||||
|
||||
|
|
|
|||
161
src/structs.rs
Normal file
161
src/structs.rs
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlaybackUpdate {
|
||||
pub data: Data,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
#[serde(rename = "currentPlaybackDuration")]
|
||||
pub current_playback_duration: Option<f64>,
|
||||
#[serde(rename = "currentPlaybackTime")]
|
||||
pub current_playback_time: Option<f64>,
|
||||
#[serde(rename = "currentPlaybackTimeRemaining")]
|
||||
pub current_playback_time_remaining: Option<f64>,
|
||||
#[serde(rename = "isPlaying")]
|
||||
pub is_playing: Option<bool>,
|
||||
#[serde(rename = "albumName")]
|
||||
pub album_name: Option<String>,
|
||||
#[serde(rename = "artistName")]
|
||||
pub artist_name: Option<String>,
|
||||
pub artwork: Option<Artwork>,
|
||||
#[serde(rename = "audioLocale")]
|
||||
pub audio_locale: Option<String>,
|
||||
#[serde(rename = "audioTraits")]
|
||||
pub audio_traits: Option<Vec<String>>,
|
||||
#[serde(rename = "composerName")]
|
||||
pub composer_name: Option<String>,
|
||||
#[serde(rename = "discNumber")]
|
||||
pub disc_number: Option<i64>,
|
||||
#[serde(rename = "durationInMillis")]
|
||||
pub duration_in_millis: Option<i64>,
|
||||
#[serde(rename = "genreNames")]
|
||||
#[serde(default)]
|
||||
pub genre_names: Vec<String>,
|
||||
#[serde(rename = "hasLyrics")]
|
||||
pub has_lyrics: Option<bool>,
|
||||
#[serde(rename = "hasTimeSyncedLyrics")]
|
||||
pub has_time_synced_lyrics: Option<bool>,
|
||||
#[serde(rename = "isAppleDigitalMaster")]
|
||||
pub is_apple_digital_master: Option<bool>,
|
||||
#[serde(rename = "isMasteredForItunes")]
|
||||
pub is_mastered_for_itunes: Option<bool>,
|
||||
#[serde(rename = "isVocalAttenuationAllowed")]
|
||||
pub is_vocal_attenuation_allowed: Option<bool>,
|
||||
pub isrc: Option<String>,
|
||||
pub name: Option<String>,
|
||||
#[serde(rename = "playParams")]
|
||||
pub play_params: Option<PlayParams>,
|
||||
#[serde(default)]
|
||||
pub previews: Vec<Preview>,
|
||||
#[serde(rename = "releaseDate")]
|
||||
pub release_date: Option<String>,
|
||||
#[serde(rename = "remainingTime")]
|
||||
pub remaining_time: Option<f64>,
|
||||
#[serde(rename = "trackNumber")]
|
||||
pub track_number: Option<i64>,
|
||||
pub url: Option<String>,
|
||||
pub attributes: Option<Attributes>,
|
||||
pub state: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Artwork {
|
||||
pub height: i64,
|
||||
pub url: String,
|
||||
pub width: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlayParams {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Preview {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Attributes {
|
||||
#[serde(rename = "albumName")]
|
||||
pub album_name: String,
|
||||
#[serde(rename = "artistName")]
|
||||
pub artist_name: String,
|
||||
pub artwork: Artwork2,
|
||||
#[serde(rename = "audioLocale")]
|
||||
pub audio_locale: String,
|
||||
#[serde(rename = "audioTraits")]
|
||||
pub audio_traits: Vec<String>,
|
||||
#[serde(rename = "composerName")]
|
||||
pub composer_name: String,
|
||||
#[serde(rename = "currentPlaybackTime")]
|
||||
pub current_playback_time: f64,
|
||||
#[serde(rename = "discNumber")]
|
||||
pub disc_number: i64,
|
||||
#[serde(rename = "durationInMillis")]
|
||||
pub duration_in_millis: i64,
|
||||
#[serde(rename = "genreNames")]
|
||||
pub genre_names: Vec<String>,
|
||||
#[serde(rename = "hasLyrics")]
|
||||
pub has_lyrics: bool,
|
||||
#[serde(rename = "hasTimeSyncedLyrics")]
|
||||
pub has_time_synced_lyrics: bool,
|
||||
#[serde(rename = "isAppleDigitalMaster")]
|
||||
pub is_apple_digital_master: bool,
|
||||
#[serde(rename = "isMasteredForItunes")]
|
||||
pub is_mastered_for_itunes: bool,
|
||||
#[serde(rename = "isVocalAttenuationAllowed")]
|
||||
pub is_vocal_attenuation_allowed: bool,
|
||||
pub isrc: String,
|
||||
pub name: String,
|
||||
#[serde(rename = "playParams")]
|
||||
pub play_params: PlayParams2,
|
||||
pub previews: Vec<Preview2>,
|
||||
#[serde(rename = "releaseDate")]
|
||||
pub release_date: String,
|
||||
#[serde(rename = "remainingTime")]
|
||||
pub remaining_time: f64,
|
||||
#[serde(rename = "trackNumber")]
|
||||
pub track_number: i64,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Artwork2 {
|
||||
pub height: i64,
|
||||
pub url: String,
|
||||
pub width: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PlayParams2 {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Preview2 {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct NowPlayingResponse {
|
||||
pub info: Data,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct IsPlayingResponse {
|
||||
pub is_playing: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct StatusUpdate {
|
||||
pub text: String,
|
||||
pub tooltip: String,
|
||||
pub class: Vec<String>,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue