Updated icarus-model (#33)

* Updated icarus-model

* Updated icarus-model

* Saving changes

* Code formatting

* Removing code

* Updated icarus-model

* Updated token secret

* Added host

* Fix build issue

* Fix build warnings

* Saving changes

* Saving changes

* Refactoring

* Migrating over icarus-model coverart

* Removed song module

* Another one

* Meta single upload is functional

* Cleanup

* More cleanup

* Added test files (#37)

* Added test files

Need to add a coverarg image file

* Updated test album file

* Added coverart

* Uploading meta is operational

* Code cleanup

* Moved function

* Added string module
This commit was merged in pull request #33.
This commit is contained in:
KD
2025-03-24 19:34:38 -04:00
committed by GitHub
parent de90b0d0a1
commit 64935ea772
16 changed files with 303 additions and 458 deletions
+4 -3
View File
@@ -20,19 +20,20 @@ jobs:
run: rustup install 1.85.0 && rustup default 1.85.0
- name: Debug secret
run: echo "${{ secrets.GITLAB_TOKEN }}" | head -c 10 ; echo "..."
run: echo "${{ secrets.MYREPO_TOKEN }}" | head -c 10 ; echo "..."
- name: Build
run: |
mkdir -p ~/.ssh
echo "$EXTREPO_KEY" > ~/.ssh/gitlab_deploy_key
chmod 600 ~/.ssh/gitlab_deploy_key
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
ssh-keyscan git.kundeng.us ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLl/OZiKVDxwnyvMxa+rjKvDpKqTxH1GWuGuDPLmENGQMbTVulajZWr9x8Q1cotoJiHZkt7DA5vczcjB/4lwgWA= >> ~/.ssh/known_hosts
eval $(ssh-agent -s)
ssh-add -v ~/.ssh/gitlab_deploy_key
cargo build --release
env:
EXTREPO_KEY: ${{ secrets.GITLAB_TOKEN }}
EXTREPO_KEY: ${{ secrets.MYREPO_TOKEN }}
- name: Run tests
run: cargo test --verbose
+1 -1
View File
@@ -16,4 +16,4 @@ serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
tokio = { version = "1.44.0", features = ["full"] }
tokio-util = { version = "0.7.13", features = ["codec"] }
icarus-models = { git = "ssh://git@gitlab.com/kdeng00/icarus-models.git", tag = "v0.1.7" }
icarus-models = { git = "ssh://git@git.kundeng.us/phoenix/icarus-models.git", tag = "v0.1.14" }
+185 -212
View File
@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
use tokio::runtime::Runtime;
use crate::managers;
use crate::models::song::Album;
use crate::models::{self};
use crate::parsers;
use crate::syncers;
@@ -29,10 +28,6 @@ enum ActionValues {
None,
}
enum _RetrieveTypes {
Songs,
}
#[derive(Clone, Debug)]
enum En {
ImageFile,
@@ -41,36 +36,47 @@ enum En {
Other,
}
impl Album {
pub fn _print_info(&self) {
println!("Album: {}", self.title);
println!("Album Artist: {}", self.album_artist);
println!("Genre: {}", self.genre);
println!("Year: {}", self.year);
println!("Track Count: {}", self.track_count);
println!("Disc Count: {}\n", self.disc_count);
pub fn retrieve_song(
album: &icarus_models::album::collection::Album,
track: i32,
disc: i32,
directory: &String,
filename: &String,
) -> Result<icarus_models::song::Song> {
let mut found = false;
let mut song = icarus_models::song::Song::default();
for song_i in &album.tracks {
if song_i.track == track && song_i.disc == disc {
let track = song_i.clone();
song.album = album.title.clone();
song.album_artist = album.artist.clone();
song.artist = track.artist.clone();
song.audio_type = String::from(icarus_models::constants::DEFAULTMUSICEXTENSION);
song.disc = track.disc.clone();
song.disc_count = album.disc_count.clone();
song.duration = track.duration as i32;
song.genre = album.genre.clone();
song.title = track.title.clone();
song.year = album.year.clone();
song.track = track.track.clone();
song.track_count = album.track_count.clone();
song.directory = directory.clone();
song.filename = filename.clone();
found = true;
break;
}
}
pub fn retrieve_song(&self, track: i32, disc: i32) -> Result<models::song::Song> {
let mut found = false;
let mut song = models::song::Song::default();
for song_i in &self.songs {
if song_i.track.unwrap() == track && song_i.disc.unwrap() == disc {
song = song_i.clone();
found = true;
}
}
if found {
return Ok(song);
}
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Song not found",
));
if found {
return Ok(song);
}
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Song not found",
));
}
impl CommitManager {
@@ -110,15 +116,17 @@ impl CommitManager {
}
fn map_actions(&self) -> HashMap<String, ActionValues> {
let mut actions: HashMap<String, ActionValues> = HashMap::new();
actions.insert("download".to_string(), ActionValues::DownloadAct);
actions.insert("upload".to_string(), ActionValues::UploadAct);
actions.insert(
"upload-meta".to_string(),
ActionValues::UploadSongWithMetadata,
);
actions.insert("retrieve".to_string(), ActionValues::RetrieveAct);
actions.insert("delete".to_string(), ActionValues::DeleteAct);
let actions: HashMap<String, ActionValues> = HashMap::from([
("download".to_string(), ActionValues::DownloadAct),
("download".to_string(), ActionValues::DownloadAct),
("upload".to_string(), ActionValues::UploadAct),
(
"upload-meta".to_string(),
ActionValues::UploadSongWithMetadata,
),
("retrieve".to_string(), ActionValues::RetrieveAct),
("delete".to_string(), ActionValues::DeleteAct),
]);
return actions;
}
@@ -135,14 +143,14 @@ impl CommitManager {
println!("Deleting song");
let mut song = models::song::Song::default();
let mut song = icarus_models::song::Song::default();
for arg in &self.ica_action.flags {
let flag = &arg.flag;
let value = &arg.value;
if flag == "-D" {
song.id = Some(value.parse::<i32>().unwrap());
song.id = value.parse::<i32>().unwrap();
}
}
@@ -165,7 +173,7 @@ impl CommitManager {
fn download_song(&self) {
println!("Deleting song");
let dwn = self.ica_action.retrieve_flag_value(&String::from("-b"));
let num: i32 = dwn.parse::<i32>().unwrap();
let id: i32 = dwn.parse::<i32>().unwrap();
let mut prsr = parsers::api_parser::APIParser {
api: models::api::API::default(),
@@ -178,27 +186,27 @@ impl CommitManager {
println!("Message: {}", token.message);
let mut dwn_loader = syncers::download::Download { api: api.clone() };
let mut song = models::song::Song::default();
song.id = Some(num);
let mut song = icarus_models::song::Song::default();
song.id = id;
let result_fut = dwn_loader.download_song(&token, &song);
let result = Runtime::new().unwrap().block_on(result_fut);
match result {
match Runtime::new().unwrap().block_on(result_fut) {
Ok(o) => {
println!("Success");
let mut filename = String::from("audio");
filename += icarus_models::constants::WAV_EXTENSION;
let filename =
String::from("audio") + icarus_models::constants::DEFAULTMUSICEXTENSION;
let data = o.as_bytes();
let mut file = std::fs::File::create(filename).expect("Failed to save");
file.write_all(&data).expect("ff");
file.write_all(&data)
.expect("Failed to save downloaded song");
}
Err(er) => {
println!("Error {:?}", er);
match er {
syncers::download::MyError::Request(r) => {
println!("Error {:?}", r)
syncers::download::MyError::Request(error) => {
println!("Error: {:?}", error);
}
syncers::download::MyError::Other(ot) => {
println!("Error {:?}", ot)
syncers::download::MyError::Other(ss) => {
println!("Error: {:?}", ss);
}
}
}
@@ -206,7 +214,7 @@ impl CommitManager {
}
fn retrieve_object(&self) {
println!("Deleting song");
println!("Retrieving song");
let rt = self.ica_action.retrieve_flag_value(&String::from("-rt"));
if rt != "songs" {
@@ -224,11 +232,13 @@ impl CommitManager {
let mut repo = syncers::retrieve_records::RetrieveRecords { api: api.clone() };
let result_fut = repo.get_all_songs(&token);
let result = Runtime::new().unwrap().block_on(result_fut);
match result {
match Runtime::new().unwrap().block_on(result_fut) {
Ok(o) => {
for son in o {
son.print_info();
for song in o {
println!("Title: {:?}", song.title);
println!("Artist: {:?}", song.artist);
println!("Album: {:?}", song.album);
println!("Year: {:?}", song.year);
}
}
Err(er) => {
@@ -315,6 +325,8 @@ impl CommitManager {
let api = prsr.retrieve_api();
let token = self.parse_token(&api);
println!("Token: {:?}", token.token);
let song_file = std::path::Path::new(&songpath);
if !song_file.exists() {
@@ -322,52 +334,43 @@ impl CommitManager {
panic!("Error");
}
let mut cover_art = models::song::CoverArt::default();
let mut song = models::song::Song::default();
let mut cover_art = icarus_models::coverart::CoverArt {
id: 0,
title: String::new(),
path: String::new(),
data: Vec::new(),
};
let mut song = icarus_models::song::Song::default();
let mut filenames = Vec::new();
let mut fp = String::new();
let mut dir = String::new();
let entry = &song_file;
let file_name = std::ffi::OsString::from(entry.file_name().unwrap());
println!("file name: {:?}", file_name);
let file_name = std::ffi::OsString::from(&song_file.file_name().unwrap());
match self.find_file_extension(&file_name) {
En::ImageFile => {}
En::MetadataFile => {}
En::SongFile => {
let fname = self.o_to_string(&file_name);
match fname {
Ok(s) => {
filenames.push(s.clone());
fp = s.clone();
dir = song_file.parent().unwrap().display().to_string();
song.filename = Some(s.clone());
song.directory = Some(dir.clone());
self.initialize_disc_and_track(&mut song);
}
Err(er) => println!("Error: {:?}", er),
En::SongFile => match utilities::string::o_to_string(&file_name) {
Ok(s) => {
println!("file name: {:?}", file_name);
filenames.push(s.clone());
song.filename = s.clone();
song.directory = song_file.parent().unwrap().display().to_string();
self.initialize_disc_and_track(&mut song);
}
}
Err(er) => println!("Error: {:?}", er),
},
_ => {}
}
cover_art.path = Some(cover_path.clone());
cover_art.path = cover_path.clone();
let album = self.retrieve_metadata(&meta_path);
let trck = i32::from_str(track_id).unwrap();
let mut s = album.retrieve_song(trck, 1).unwrap();
s.filename = Some(fp);
s.directory = Some(dir);
s.genre = Some(album.genre.clone());
s.year = Some(album.year.clone());
s.album = Some(album.title.clone());
s.data = Some(s.to_data().unwrap());
let mut s = retrieve_song(&album, trck, 1, &song.directory, &song.filename).unwrap();
println!("Directory: {:?}", s.directory);
println!("Filename: {:?}", s.filename);
println!("Path: {:?}", s.song_path());
s.data = s.to_data().unwrap();
cover_art.data = Some(cover_art.to_data().unwrap());
cover_art.data = cover_art.to_data().unwrap();
let mut up = syncers::upload::Upload::default();
let host = self.ica_action.retrieve_flag_value(&String::from("-h"));
@@ -379,13 +382,63 @@ impl CommitManager {
match &tken {
Ok(o) => {
println!("Successfully sent {:?}", o);
Ok(())
}
Err(er) => {
println!("Some error {:?}", er);
Err(std::io::Error::new(
std::io::ErrorKind::Other,
er.to_string(),
))
}
}
}
Ok(())
fn get_songs(
&self,
metadata_path: &String,
source_directory: &String,
) -> Result<Vec<icarus_models::song::Song>> {
match icarus_models::album::collection::parse_album(metadata_path) {
Ok(albums) => {
let mut songs: Vec<icarus_models::song::Song> = Vec::new();
for track in &albums.tracks {
let filename = if track.track < 10 {
"track0".to_owned()
+ &track.track.to_string()
+ icarus_models::constants::DEFAULTMUSICEXTENSION
} else {
"track".to_owned()
+ &track.track.to_string()
+ icarus_models::constants::DEFAULTMUSICEXTENSION
};
songs.push(icarus_models::song::Song {
id: -1,
title: track.title.clone(),
artist: track.artist.clone(),
disc: track.disc.clone(),
track: track.track.clone(),
duration: track.duration.clone() as i32,
year: albums.year.clone(),
album_artist: albums.artist.clone(),
genre: albums.genre.clone(),
disc_count: albums.disc_count.clone(),
track_count: albums.track_count.clone(),
album: albums.title.clone(),
audio_type: String::from("FLAC"),
directory: source_directory.clone(),
filename: filename,
user_id: -1,
data: Vec::new(),
date_created: String::new(),
});
}
Ok(songs)
}
Err(_) => Ok(Vec::new()),
}
}
fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> {
@@ -403,8 +456,12 @@ impl CommitManager {
panic!("Directory does not exist");
}
let mut cover_art = models::song::CoverArt::default();
let mut songs: Vec<models::song::Song> = Vec::new();
let mut cover_art = icarus_models::coverart::CoverArt {
id: 0,
title: String::new(),
path: String::new(),
data: Vec::new(),
};
let mut filenames: Vec<String> = Vec::new();
let mut metadatapath: String = String::new();
@@ -423,130 +480,55 @@ impl CommitManager {
match self.find_file_extension(&file_name) {
En::ImageFile => {
let directory_part = sourcepath.clone();
let fname = self.o_to_string(&file_name);
let fname = utilities::string::o_to_string(&file_name);
let fullpath = directory_part + "/" + &fname.unwrap();
cover_art.path = Some(fullpath);
cover_art.path = fullpath;
}
En::MetadataFile => {
let directory_part = sourcepath.clone();
let fname = self.o_to_string(&file_name);
let fname = utilities::string::o_to_string(&file_name);
metadatapath = directory_part + "/" + &fname.unwrap();
}
En::SongFile => {
let mut song = models::song::Song::default();
let fname = self.o_to_string(&file_name);
match fname {
Ok(s) => {
filenames.push(s.clone());
song.filename = Some(s.clone());
song.directory = Some(sourcepath.clone());
song.data = Some(song.to_data().unwrap());
self.initialize_disc_and_track(&mut song);
}
Err(er) => println!("Error: {:?}", er),
}
songs.push(song)
}
_ => {}
}
}
filenames.sort();
let mut album = self.retrieve_metadata(&metadatapath);
self.song_parsing(&mut album, &sourcepath, &filenames);
let songs = self.get_songs(&metadatapath, &sourcepath);
let album = self.retrieve_metadata(&metadatapath);
let mut up = syncers::upload::Upload::default();
let host = self.ica_action.retrieve_flag_value(&String::from("-h"));
up.set_api(&host);
cover_art.data = Some(cover_art.to_data().unwrap());
cover_art.data = cover_art.to_data().unwrap();
println!("");
for sng in &mut album.songs {
match sng.data {
Some(_) => {}
None => {
sng.data = Some(sng.to_data().unwrap());
}
};
}
for song in &album.songs {
// Upload each song
println!("Sending song...");
let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album);
let tken = Runtime::new().unwrap().block_on(res);
match &tken {
Ok(o) => {
println!("Successfully sent {:?}", o);
}
Err(er) => {
println!("Some error {:?}", er);
match songs {
Ok(sngs) => {
for song in sngs {
println!("Title: {:?}", song.title);
println!("Path: {:?}", song.song_path());
let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album);
match Runtime::new().unwrap().block_on(res) {
Ok(o) => {
println!("Response: {:?}", o);
}
Err(err) => {
println!("Error: {:?}", err);
}
};
}
}
println!("");
Err(error) => {
println!("Error: {:?}", error);
}
}
Ok(())
}
// Makes sure the elements in album.songs is populated
fn song_parsing(
&self,
album: &mut models::song::Album,
directory: &String,
filenames: &Vec<String>,
) {
// Apply directory
for song in &mut album.songs {
let dir = &song.directory;
match dir {
Some(s) => println!("{}", s),
None => {
song.directory = Some(directory.clone());
}
}
}
// Apply filename
let mut index = 0;
for song in &mut album.songs {
let filename = filenames[index].clone();
song.filename = Some(filename);
index += 1;
}
for song in &mut album.songs {
match &mut song.album {
Some(_) => {}
None => {
song.album = Some(album.title.clone());
}
}
match &mut song.genre {
Some(_) => {}
None => {
song.genre = Some(album.genre.clone());
}
}
match &mut song.year {
Some(_) => {}
None => {
song.year = Some(album.year.clone());
}
}
}
}
fn find_file_extension(&self, file_name: &std::ffi::OsString) -> En {
let file_name_str = Some(file_name.clone().into_string());
@@ -588,23 +570,14 @@ impl CommitManager {
return En::Other;
}
fn o_to_string(&self, val: &std::ffi::OsString) -> Result<std::string::String> {
let res = val.clone().into_string();
return match res {
Ok(sss) => Ok(sss),
Err(_) => Ok(String::from("Error")),
};
}
// Standards
// * track01.cdda.wav - Disc 1, Track 1
// * track02d02.cdda.wav - Disc 2, Track 2
fn initialize_disc_and_track(&mut self, song: &mut models::song::Song) {
fn initialize_disc_and_track(&mut self, song: &mut icarus_models::song::Song) {
let mut disc = 1;
let mut track = 1;
let mut mode = 0;
let filename =
&<std::option::Option<std::string::String> as Clone>::clone(&song.filename).unwrap();
let filename = &song.filename;
let trd = filename.contains("trackd");
let tr = filename.contains("track");
@@ -688,11 +661,11 @@ impl CommitManager {
_ => println!(""),
}
song.disc = Some(disc);
song.track = Some(track);
song.disc = disc;
song.track = track;
}
fn _parse_disc_and_track(&self, song: &mut models::song::Song, track_id: &String) {
fn _parse_disc_and_track(&self, song: &mut icarus_models::song::Song, track_id: &String) {
let sep = |_a: &char, _b: &char| -> bool {
return false;
};
@@ -714,11 +687,11 @@ impl CommitManager {
d_str.push(c);
}
song.disc = Some(d_str.parse::<i32>().unwrap());
song.track = Some(t_str.parse::<i32>().unwrap());
song.disc = d_str.parse::<i32>().unwrap();
song.track = t_str.parse::<i32>().unwrap();
} else {
if utilities::checks::Checks::is_numeric(track_id) {
song.track = Some(track_id.parse::<i32>().unwrap());
song.track = track_id.parse::<i32>().unwrap();
}
}
}
@@ -732,7 +705,7 @@ impl CommitManager {
return false;
}
fn retrieve_metadata(&self, path: &String) -> Album {
fn retrieve_metadata(&self, path: &String) -> icarus_models::album::collection::Album {
let content = self.retrieve_file_content(&path);
let val = content.unwrap();
-1
View File
@@ -1,5 +1,4 @@
pub mod api;
pub mod flags;
pub mod icarus_action;
pub mod song;
pub mod upload_form;
-179
View File
@@ -1,179 +0,0 @@
use std::default::Default;
use std::io::Read;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Song {
#[serde(alias = "id")]
pub id: Option<i32>,
pub title: Option<String>,
pub artist: Option<String>,
pub album: Option<String>,
pub album_artist: Option<String>,
pub genre: Option<String>,
pub year: Option<i32>,
pub duration: Option<f64>,
pub track: Option<i32>,
pub disc: Option<i32>,
pub disc_count: Option<i32>,
pub track_count: Option<i32>,
pub date_created: Option<String>,
pub filename: Option<String>,
pub user_id: Option<i32>,
pub data: Option<Vec<u8>>,
pub directory: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Album {
#[serde(alias = "album")]
pub title: String,
pub album_artist: String,
pub genre: String,
pub year: i32,
pub track_count: i32,
pub disc_count: i32,
#[serde(alias = "tracks")]
pub songs: Vec<Song>,
}
impl Default for Album {
fn default() -> Self {
Album {
title: String::new(),
album_artist: String::new(),
genre: String::new(),
year: 0,
track_count: 0,
disc_count: 0,
songs: Vec::new(),
}
}
}
impl Default for Song {
fn default() -> Self {
Song {
id: None,
title: None,
artist: None,
album: None,
album_artist: None,
genre: None,
year: None,
duration: None,
track: None,
disc: None,
disc_count: None,
track_count: None,
date_created: None,
filename: None,
user_id: None,
data: None,
directory: None,
}
}
}
impl Song {
pub fn print_info(&self) {
println!("Title: {:?}", self.title);
println!("Artist: {:?}", self.artist);
}
pub fn song_path(&self) -> String {
let directory =
&<std::option::Option<std::string::String> as Clone>::clone(&self.directory).unwrap();
let mut buffer: String = directory.to_string();
let count = buffer.len();
if buffer.chars().nth(count - 1) != Some('/') {
buffer += "/";
}
let filename =
&<std::option::Option<std::string::String> as Clone>::clone(&self.filename).unwrap();
buffer += filename;
return buffer;
}
pub fn to_data(&self) -> Result<Vec<u8>, std::io::Error> {
let path = self.song_path();
println!("Converting song to data");
println!("Path: {:?}", path);
let mut file = std::fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
if buffer.len() == 0 {
println!("Why is it empty?");
}
Ok(buffer)
}
// if 1 - wav, if 0 - mp3, anything else defaults to wav
pub fn _generate_filename_from_track(&mut self, i_type: i32) -> i32 {
let mut filename: String = String::new();
if self.track.unwrap() < 10 {
filename += "0";
}
filename += &self.track.unwrap().to_string();
if i_type == 0 {
filename += icarus_models::constants::MPTHREE_EXTENSION;
} else {
filename += icarus_models::constants::WAV_EXTENSION;
}
self.filename = Some(filename);
return 0;
}
pub fn _to_metadata_json(&self) -> Result<String, serde_json::Error> {
return serde_json::to_string_pretty(&self);
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct CoverArt {
pub id: Option<i32>,
pub title: Option<String>,
pub path: Option<String>,
pub data: Option<Vec<u8>>,
}
impl Default for CoverArt {
fn default() -> Self {
CoverArt {
id: None,
title: None,
path: None,
data: None,
}
}
}
impl CoverArt {
pub fn to_data(&self) -> Result<Vec<u8>, std::io::Error> {
let mut path: String = String::new();
match &self.path {
Some(val) => {
path = String::from(val);
}
None => {
();
}
}
let mut file = std::fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}
}
+6 -6
View File
@@ -21,8 +21,8 @@ impl Delete {
pub async fn delete_song(
&mut self,
token: &icarus_models::token::AccessToken,
song: &models::song::Song,
) -> Result<models::song::Song, std::io::Error> {
song: &icarus_models::song::Song,
) -> Result<icarus_models::song::Song, std::io::Error> {
self.api.endpoint = "song/data/delete".to_owned();
let url = self.retrieve_url(&song);
let client = reqwest::Client::builder().build().unwrap();
@@ -33,12 +33,12 @@ impl Delete {
.send()
.await
.unwrap();
let mut sng = models::song::Song::default();
let mut sng = icarus_models::song::Song::default();
match response.status() {
reqwest::StatusCode::OK => {
println!("Success!");
let s = response.json::<models::song::Song>().await;
let s = response.json::<icarus_models::song::Song>().await;
match s {
//
Ok(parsed) => {
@@ -57,7 +57,7 @@ impl Delete {
return Ok(sng);
}
fn retrieve_url(&self, song: &models::song::Song) -> String {
fn retrieve_url(&self, song: &icarus_models::song::Song) -> String {
let api = &self.api;
let mut url: String = String::from(&api.url);
url += &String::from("api/");
@@ -65,7 +65,7 @@ impl Delete {
url += &String::from("/");
url += &String::from(&api.endpoint);
url += &String::from("/");
url += &song.id.unwrap().to_string();
url += &song.id.to_string();
return url;
}
+20 -22
View File
@@ -24,7 +24,7 @@ impl Download {
pub async fn download_song(
&mut self,
token: &icarus_models::token::AccessToken,
song: &models::song::Song,
song: &icarus_models::song::Song,
) -> Result<String, MyError> {
self.api.endpoint = String::from("song/data/download");
let url = self.retrieve_url(&song);
@@ -44,27 +44,25 @@ impl Download {
.await;
match response {
Ok(rep) => {
match rep.status() {
reqwest::StatusCode::OK => {
let data = rep.text();
match data.await {
Ok(e) => {
return Ok(e);
}
Err(er) => {
println!("Error {:?}", er);
Ok(rep) => match rep.status() {
reqwest::StatusCode::OK => {
let data = rep.text();
match data.await {
Ok(e) => {
return Ok(e);
}
Err(er) => {
println!("Error {:?}", er);
}
}
}
}
reqwest::StatusCode::UNAUTHORIZED => {
println!("Need to grab a new token");
}
other => {
panic!("Uh oh! Something unexpected happened: {:?}", other);
}
}
}
reqwest::StatusCode::UNAUTHORIZED => {
println!("Need to grab a new token");
}
other => {
panic!("Uh oh! Something unexpected happened: {:?}", other);
}
},
Err(er) => {
return Err(MyError::Request(er));
}
@@ -73,7 +71,7 @@ impl Download {
return Err(MyError::Other(String::from("Error downloading")));
}
fn retrieve_url(&self, song: &models::song::Song) -> String {
fn retrieve_url(&self, song: &icarus_models::song::Song) -> String {
let api = &self.api;
let mut url: String = String::from(&api.url);
url += &String::from("api/");
@@ -81,7 +79,7 @@ impl Download {
url += &String::from("/");
url += &String::from(&api.endpoint);
url += &String::from("/");
url += &song.id.unwrap().to_string();
url += &song.id.to_string();
return url;
}
+3 -3
View File
@@ -19,9 +19,9 @@ impl RetrieveRecords {
pub async fn get_all_songs(
&mut self,
token: &icarus_models::token::AccessToken,
) -> Result<Vec<models::song::Song>, Error> {
) -> Result<Vec<icarus_models::song::Song>, Error> {
self.api.endpoint = String::from("song");
let mut songs: Vec<models::song::Song> = Vec::new();
let mut songs: Vec<icarus_models::song::Song> = Vec::new();
let url = self.retrieve_url();
let access_token = token.bearer_token();
@@ -46,7 +46,7 @@ impl RetrieveRecords {
match response.status() {
reqwest::StatusCode::OK => {
// on success, parse our JSON to an APIResponse
let s = response.json::<Vec<models::song::Song>>().await;
let s = response.json::<Vec<icarus_models::song::Song>>().await;
match s {
//
Ok(parsed) => {
+42 -31
View File
@@ -3,7 +3,6 @@ use std::default::Default;
use http::HeaderMap;
use http::HeaderValue;
use reqwest;
use reqwest::multipart::Form;
use serde::{Deserialize, Serialize};
use crate::models;
@@ -47,14 +46,13 @@ impl Upload {
pub async fn upload_song_with_metadata(
&mut self,
token: &icarus_models::token::AccessToken,
song: &models::song::Song,
cover: &models::song::CoverArt,
album: &models::song::Album,
) -> Result<reqwest::Response, std::io::Error> {
song: &icarus_models::song::Song,
cover: &icarus_models::coverart::CoverArt,
album: &icarus_models::album::collection::Album,
) -> Result<reqwest::Response, reqwest::Error> {
self.api.endpoint = String::from("song/data/upload/with/data");
let url = self.retrieve_url();
let mut new_song = self.initialize_song(&song, &album);
new_song.songpath = song.song_path();
let new_song = self.initialize_song(&song, &album);
let access_token = token.bearer_token();
if url.is_empty() {
@@ -63,6 +61,7 @@ impl Upload {
println!("Url: {}", url);
println!("Token: {}", access_token);
println!("Path: {:?}", new_song.songpath);
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
@@ -73,18 +72,20 @@ impl Upload {
let form = self.init_form(&new_song, &cover);
let client = reqwest::Client::builder().build().unwrap();
let response = client
match client
.post(url)
.headers(headers)
.multipart(form)
.send()
.await;
let response_text = response.unwrap();
println!("Something was sent");
println!("{:?}", response_text);
return Ok(response_text);
.await
{
Ok(r) => {
return Ok(r);
}
Err(err) => {
return Err(err);
}
}
}
fn _initialize_form(
@@ -92,7 +93,7 @@ impl Upload {
song_raw_data: Vec<u8>,
cover_raw_data: Vec<u8>,
song_detail: String,
) -> Form {
) -> reqwest::multipart::Form {
let mut headers = HeaderMap::new();
headers.insert(
http::header::CONTENT_TYPE,
@@ -109,9 +110,9 @@ impl Upload {
let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i);
let mut song_filename = String::from("audio");
song_filename += icarus_models::constants::WAV_EXTENSION;
song_filename += icarus_models::constants::WAVEXTENSION;
let mut cover_filename = String::from("cover");
cover_filename += icarus_models::constants::JPG_EXTENSION;
cover_filename += icarus_models::constants::JPGEXTENSION;
return reqwest::multipart::Form::new()
.part("cover", cover.file_name(cover_filename))
@@ -119,17 +120,22 @@ impl Upload {
.part("file", file.file_name(song_filename));
}
fn init_form(&self, song: &Song, cover: &models::song::CoverArt) -> reqwest::multipart::Form {
fn init_form(
&self,
song: &Song,
cover: &icarus_models::coverart::CoverArt,
) -> reqwest::multipart::Form {
let songpath = song.songpath.clone();
let coverpath = cover.path.clone().unwrap();
let coverpath = cover.path.clone();
println!("Cover path: {:?}", coverpath);
let song_detail = song.to_metadata_json().unwrap();
println!("\n{}\n", song_detail);
let mut song_filename = String::from("audio");
song_filename += icarus_models::constants::WAV_EXTENSION;
song_filename += icarus_models::constants::DEFAULTMUSICEXTENSION;
let mut cover_filename = String::from("cover");
cover_filename += icarus_models::constants::JPG_EXTENSION;
cover_filename += icarus_models::constants::JPGEXTENSION;
let form = reqwest::multipart::Form::new()
.part(
@@ -172,23 +178,28 @@ impl Upload {
return url;
}
fn initialize_song(&self, song: &models::song::Song, album: &models::song::Album) -> Song {
let dur = song.duration.clone().unwrap();
fn initialize_song(
&self,
song: &icarus_models::song::Song,
album: &icarus_models::album::collection::Album,
) -> Song {
let dur = song.duration.clone();
println!("Duration: {}", dur);
return Song {
title: String::from(&song.title.clone().unwrap()),
title: String::from(&song.title.clone()),
album: album.title.clone(),
artist: String::from(&song.artist.clone().unwrap().clone()),
album_artist: album.album_artist.clone(),
artist: String::from(&song.artist.clone().clone()),
album_artist: album.artist.clone(),
year: album.year.clone(),
genre: album.genre.clone(),
duration: f64::round(dur) as i32,
track: (song.track.clone().unwrap()),
// duration: f64::round(dur) as i32,
duration: dur,
track: (song.track.clone()),
track_count: album.track_count.clone(),
disc: song.disc.clone().unwrap(),
disc: song.disc.clone(),
disc_count: album.disc_count.clone(),
songpath: String::new(),
songpath: song.directory.clone() + "/" + &song.filename.clone(),
};
}
}
+1
View File
@@ -1 +1,2 @@
pub mod checks;
pub mod string;
+10
View File
@@ -0,0 +1,10 @@
pub fn o_to_string(val: &std::ffi::OsString) -> Result<std::string::String, std::io::Error> {
match val.clone().into_string() {
Ok(value) => Ok(value),
Err(_) => Err(std::io::Error::new(
std::io::ErrorKind::Other,
String::from("Error"),
)),
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"album": "Sample Tracks 2",
"album_artist": "KD",
"genre": "Country",
"year": 2025,
"track_count": 3,
"disc_count": 1,
"tracks": [
{
"title": "Uh huh",
"artist": "KD",
"disc": 1,
"track": 1,
"duration": 32
},
{
"title": "Bold and brash",
"artist": "KD",
"disc": 1,
"track": 2,
"duration": 37
},
{
"title": "How does this work?",
"artist": "KD",
"disc": 1,
"track": 3,
"duration": 46
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.