From 715c741f36e1dae41a3c95e9e6da2090932bdf7c Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 20:03:21 -0400 Subject: [PATCH 01/47] Blank slate --- .gitmodules | 3 - CMakeLists.txt | 108 ------ IcarusDownloadManager.rc | 99 ------ IcarusDownloadManager.sln | 31 -- IcarusDownloadManager.vcxproj | 165 ---------- IcarusDownloadManager.vcxproj.filters | 120 ------- IcarusDownloadManager.vcxproj.user | 11 - include/Managers/ActionManager.h | 93 ------ include/Managers/CommitManager.h | 220 ------------- include/Managers/FileManager.h | 31 -- include/Managers/TokenManager.h | 25 -- include/Managers/UserManager.h | 28 -- include/Models/API.h | 19 -- include/Models/Flags.h | 18 - include/Models/IcarusAction.h | 53 --- include/Models/Song.h | 90 ----- include/Models/Token.h | 18 - include/Models/UploadForm.h | 18 - include/Models/User.h | 17 - include/Parsers/APIParser.h | 25 -- include/Syncers/Delete.h | 25 -- include/Syncers/Download.h | 33 -- include/Syncers/RetrieveRecords.h | 28 -- include/Syncers/SyncerBase.h | 29 -- include/Syncers/Upload.h | 55 ---- include/UI/AboutWindow.h | 36 -- include/UI/CommonWindow.h | 33 -- include/UI/MainWindow.h | 84 ----- include/Utilities/Checks.h | 67 ---- include/Utilities/Conversions.h | 32 -- resource.h | 14 - src/Main.cpp | 79 ----- src/Managers/ActionManager.cpp | 118 ------- src/Managers/CommitManager.cpp | 457 -------------------------- src/Managers/FileManager.cpp | 73 ---- src/Managers/TokenManager.cpp | 62 ---- src/Managers/UserManager.cpp | 55 ---- src/Models/Song.cpp | 22 -- src/Parsers/APIParser.cpp | 53 --- src/Syncers/Delete.cpp | 64 ---- src/Syncers/Download.cpp | 93 ------ src/Syncers/RetrieveRecords.cpp | 67 ---- src/Syncers/Upload.cpp | 243 -------------- src/UI/AboutWindow.cpp | 52 --- src/UI/MainWindow.cpp | 180 ---------- src/Utilities/Conversions.cpp | 26 -- vcpkg | 1 - vcpkg.json | 9 - 48 files changed, 3282 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 IcarusDownloadManager.rc delete mode 100644 IcarusDownloadManager.sln delete mode 100644 IcarusDownloadManager.vcxproj delete mode 100644 IcarusDownloadManager.vcxproj.filters delete mode 100644 IcarusDownloadManager.vcxproj.user delete mode 100644 include/Managers/ActionManager.h delete mode 100644 include/Managers/CommitManager.h delete mode 100644 include/Managers/FileManager.h delete mode 100644 include/Managers/TokenManager.h delete mode 100644 include/Managers/UserManager.h delete mode 100644 include/Models/API.h delete mode 100644 include/Models/Flags.h delete mode 100644 include/Models/IcarusAction.h delete mode 100644 include/Models/Song.h delete mode 100644 include/Models/Token.h delete mode 100644 include/Models/UploadForm.h delete mode 100644 include/Models/User.h delete mode 100644 include/Parsers/APIParser.h delete mode 100644 include/Syncers/Delete.h delete mode 100644 include/Syncers/Download.h delete mode 100644 include/Syncers/RetrieveRecords.h delete mode 100644 include/Syncers/SyncerBase.h delete mode 100644 include/Syncers/Upload.h delete mode 100644 include/UI/AboutWindow.h delete mode 100644 include/UI/CommonWindow.h delete mode 100644 include/UI/MainWindow.h delete mode 100644 include/Utilities/Checks.h delete mode 100644 include/Utilities/Conversions.h delete mode 100644 resource.h delete mode 100644 src/Main.cpp delete mode 100644 src/Managers/ActionManager.cpp delete mode 100644 src/Managers/CommitManager.cpp delete mode 100644 src/Managers/FileManager.cpp delete mode 100644 src/Managers/TokenManager.cpp delete mode 100644 src/Managers/UserManager.cpp delete mode 100644 src/Models/Song.cpp delete mode 100644 src/Parsers/APIParser.cpp delete mode 100644 src/Syncers/Delete.cpp delete mode 100644 src/Syncers/Download.cpp delete mode 100644 src/Syncers/RetrieveRecords.cpp delete mode 100644 src/Syncers/Upload.cpp delete mode 100644 src/UI/AboutWindow.cpp delete mode 100644 src/UI/MainWindow.cpp delete mode 100644 src/Utilities/Conversions.cpp delete mode 160000 vcpkg delete mode 100644 vcpkg.json diff --git a/.gitmodules b/.gitmodules index 72d488d..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "3rdparty/vcpkg"] - path = vcpkg - url = https://github.com/microsoft/vcpkg diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 5294329..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -cmake_minimum_required(VERSION 3.20.6) - -if(NOT DEFINED VCPKG_ROOT_PATH) - set(VCPKG_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vcpkg) -endif() - -message("The vcpkg root path ${VCPKG_ROOT_PATH}") - -if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) - set(TOOLCHAIN_PATH ${VCPKG_ROOT_PATH}/scripts/buildsystems/vcpkg.cmake) - - set(CMAKE_TOOLCHAIN_FILE - "${TOOLCHAIN_PATH}" - CACHE STRING "Vcpkg toolchain file") - - message("Using default toolchain file") -endif() - - -set(SOFTWARE_DESCRIPTION - "A tool to interact with the Icarus Music streaming API") -set(SOFTWARE_VERSION - "0.3.2") - - -project(IcarusDownloadManager VERSION ${SOFTWARE_VERSION} DESCRIPTION ${SOFTWARE_DESCRIPTION} LANGUAGES CXX) - - -message(STATUS "Checking compiler flags for C++20 support.") - -# Set C++20 support flags for various compilers -include(CheckCXXCompilerFlag) - -if(WIN32) - message("Windows environment") - - if (MSVC_VERSION GREATER_EQUAL "1900") - message("Visual Studio version is at least ${vs_ver}") - - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("/std:c++20" _cpp_latest_flag_supported) - if (_cpp_latest_flag_supported) - add_compile_options("/std:c++20") - endif() - - set(CMAKE_CXX_STANDARD 20) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - endif() -else() - check_cxx_compiler_flag("-std=c++20" COMPILER_SUPPORTS_CXX20) - check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) - - if(COMPILER_SUPPORTS_CXX20) - message(STATUS "C++20 is supported.") - - set(CMAKE_CXX_STANDARD 20) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -stdlib=libc++") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") - endif() - elseif(COMPILER_SUPPORTS_CXX0X) - message(STATUS "C++0x is supported.") - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - endif() - else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++20 support. Please use a different C++ compiler.") - endif() -endif() - - -set(SOURCES - src/Main.cpp - src/Managers/ActionManager.cpp - src/Managers/CommitManager.cpp - src/Managers/FileManager.cpp - src/Managers/TokenManager.cpp - src/Managers/UserManager.cpp - src/Models/Song.cpp - src/Parsers/APIParser.cpp - src/Syncers/Delete.cpp - src/Syncers/Download.cpp - src/Syncers/RetrieveRecords.cpp - src/Syncers/Upload.cpp - src/Utilities/Conversions.cpp -) - -set(IDM_INCLUDE_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/include") - -include_directories(${IDM_INCLUDE_DIR}) - -set(USE_SYSTEM_CURL OFF) -set(BUILD_CPR_TESTS OFF) - -find_package(nlohmann_json CONFIG REQUIRED) -find_package(OpenSSL REQUIRED) -find_package(CURL REQUIRED) -find_package(cpr CONFIG REQUIRED) - - -add_executable(icd ${SOURCES}) -target_link_libraries(icd PRIVATE nlohmann_json::nlohmann_json OpenSSL::SSL OpenSSL::Crypto CURL::libcurl cpr::cpr) diff --git a/IcarusDownloadManager.rc b/IcarusDownloadManager.rc deleted file mode 100644 index 78870b7..0000000 --- a/IcarusDownloadManager.rc +++ /dev/null @@ -1,99 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,2,0 - PRODUCTVERSION 0,3,2,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "Tool to interact with Icarus API" - VALUE "FileVersion", "0.3.2.0" - VALUE "InternalName", "IcarusDo.exe" - VALUE "LegalCopyright", "Copyright (C) 2022" - VALUE "OriginalFilename", "IcarusDo.exe" - VALUE "ProductName", "IcarusDownloadManager" - VALUE "ProductVersion", "0.3.2.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/IcarusDownloadManager.sln b/IcarusDownloadManager.sln deleted file mode 100644 index df5cd41..0000000 --- a/IcarusDownloadManager.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcarusDownloadManager", "IcarusDownloadManager.vcxproj", "{12955990-643F-4A99-95E5-4752AFA179B0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {12955990-643F-4A99-95E5-4752AFA179B0}.Debug|x64.ActiveCfg = Debug|x64 - {12955990-643F-4A99-95E5-4752AFA179B0}.Debug|x64.Build.0 = Debug|x64 - {12955990-643F-4A99-95E5-4752AFA179B0}.Debug|x86.ActiveCfg = Debug|Win32 - {12955990-643F-4A99-95E5-4752AFA179B0}.Debug|x86.Build.0 = Debug|Win32 - {12955990-643F-4A99-95E5-4752AFA179B0}.Release|x64.ActiveCfg = Release|x64 - {12955990-643F-4A99-95E5-4752AFA179B0}.Release|x64.Build.0 = Release|x64 - {12955990-643F-4A99-95E5-4752AFA179B0}.Release|x86.ActiveCfg = Release|Win32 - {12955990-643F-4A99-95E5-4752AFA179B0}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EA22B463-3EA6-4452-9AF1-D300C3BDE72D} - EndGlobalSection -EndGlobal diff --git a/IcarusDownloadManager.vcxproj b/IcarusDownloadManager.vcxproj deleted file mode 100644 index e16e870..0000000 --- a/IcarusDownloadManager.vcxproj +++ /dev/null @@ -1,165 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 17.0 - {12955990-643F-4A99-95E5-4752AFA179B0} - Win32Proj - 10.0 - - - - Application - true - v143 - - - Application - false - v143 - - - Application - true - v143 - NotSet - - - Application - false - v143 - NotSet - - - - - - - - - - - - - - - - - - - - - true - - - true - - - $(ProjectDir)include;$(IncludePath) - - - $(ProjectDir)include;$(IncludePath) - - - - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - stdcpp20 - - - MachineX86 - true - Windows - - - - - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - stdcpp20 - - - MachineX86 - true - Windows - true - true - - - - - stdcpp20 - - - - - stdcpp20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/IcarusDownloadManager.vcxproj.filters b/IcarusDownloadManager.vcxproj.filters deleted file mode 100644 index e61501d..0000000 --- a/IcarusDownloadManager.vcxproj.filters +++ /dev/null @@ -1,120 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/IcarusDownloadManager.vcxproj.user b/IcarusDownloadManager.vcxproj.user deleted file mode 100644 index 43952bb..0000000 --- a/IcarusDownloadManager.vcxproj.user +++ /dev/null @@ -1,11 +0,0 @@ - - - - upload-meta -u kverse -p demolaugh -h http://localhost:5002 -smca "D:\OneDrive\media\music\mp3\bb_king\paying_the_cost_to_be_the_boss" - WindowsLocalDebugger - - - upload-meta -u kverse -p demolaugh -h http://localhost:5002 -smca "D:\OneDrive\media\music\mp3\bb_king\paying_the_cost_to_be_the_boss" - WindowsLocalDebugger - - \ No newline at end of file diff --git a/include/Managers/ActionManager.h b/include/Managers/ActionManager.h deleted file mode 100644 index 66bc3e1..0000000 --- a/include/Managers/ActionManager.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef ACTIONMANAGER_H_ -#define ACTIONMANAGER_H_ - -#include -#include -#include -#include -#include - -#include"Models/Flags.h" -#include"Models/IcarusAction.h" - -namespace Managers -{ - - - -class ActionManager -{ -public: - ActionManager(char**, int); - - Models::IcarusAction retrieveIcarusAction() const; -private: - constexpr std::array supportedFlags() noexcept - { - constexpr std::array allFlags{"-u", "-p", "-t", "-h", "-s", - "-sd", "-sr", "-d", "-D", "-b", "-rt", "-nc", - "-m", "-ca", "-smca", "-t"}; - - return allFlags; - } - constexpr std::array supportedActions() noexcept; - - void initialize(); - void validateFlags(); - // Checks to see if the flag is valid - template - bool isValidFlag(const Str flag) - { - const auto flags = supportedFlags(); - const auto i = std::find_if(flags.begin(), flags.end(), [&](const Str &f) - { - return f.compare(flag) == 0 ? true : false; - }); - - auto result = i != flags.end() ? true : false; - - return result; - } - - template - bool doesFlagHaveValue(const Str flag) - { - const auto flags = parsedFlags(); - auto i = std::find_if(flags.begin(), flags.end(), [&](const Str &f) - { - return f.compare(flag) == 0 ? true : false; - }); - - if (i != flags.end()) - { - if (++i != flags.end() && !isValidFlag(*i)) - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - - void printAction() noexcept; - void printFlags() noexcept; - - std::vector parsedFlags(); - - std::string action; - - std::vector flags; - - char **params; - int paramCount; -}; - -} - -#endif diff --git a/include/Managers/CommitManager.h b/include/Managers/CommitManager.h deleted file mode 100644 index d3827f2..0000000 --- a/include/Managers/CommitManager.h +++ /dev/null @@ -1,220 +0,0 @@ -#ifndef COMMITMANAGER_H_ -#define COMMITMANAGER_H_ - -#include -#include -#include -#include -#include - -#include"Models/API.h" -#include"Models/IcarusAction.h" -#include"Models/Song.h" -#include"Models/Token.h" -#include"Utilities/Checks.h" - -namespace Managers -{ - -class CommitManager -{ -public: - CommitManager(Models::IcarusAction&); - - void commitAction(); - - - enum class RetrieveTypes - { - songs - }; - - // Used for parsing songs from the metadata file - class Album - { - public: - Album() = default; - - void printInfo(); - - - std::string album; - std::string albumArtist; - std::string genre; - int year; - int trackCount; - int discCount; - std::vector songs; - }; - -private: - enum class ActionValues; - - std::map mapActions() noexcept; - - void deleteSong(); - void downloadSong(); - void retrieveObjects(); - void uploadSong(); - - Models::Token parseToken(Models::API); - - // Uploads a single song. The song is constructed from a metadata file that contains - // information about the album the song is from. Also, the cover art of the song must - // be present. - // - // Expects - // * Song - mp3 file path - // * TrackID - track number to chose from when retrieving metadata. "1" and "1:1" are similar - // * Metadata - Source file containing metadata of the song - // * Cover art - path to image cover art - void uploadSongWithMetadata(); - - // Expects the song path, trackID, metadata file path, and cover path - void singTargetUpload(const std::string &songPath, const std::string &trackID, - const std::string &metaPath, const std::string &coverPath); - // Expects the source directory that contains songs, a metadata file, and cover image - // Disc and Track is retrieved from the filename if the filename conforms to a standard. - // If not, then the disc and track will default to 1 - // - // Standards - // * track01.mp3 - Disc 1, Track 1 - // * track05d02.mp3 - Disc 2, Track 5 - void multiTargetUpload(const std::string &sourcePath); - - // Standards - // * track01.mp3 - Disc 1, Track 1 - // * track05d02.mp3 - Disc 2, Track 5 - template - void initializeDiscAndTrack(Song &song) - { - auto disc = 1; - auto track = 1; - // If 1 go with first standard, if 2 go with the second, if 0 then will default to 1 for disc and track - auto mode = 0; - const Str &songPath = song.songPath; - auto file = std::filesystem::path(songPath); - auto filename = file.filename().string();; - - auto trd = song.songPath.find("trackd"); - auto tr = song.songPath.find("track"); - - if (tr != Str::npos) - { - mode = 1; - } - - if (trd != Str::npos) - { - mode = 2; - } - - auto dl = [](char c, char t){ return c == t; }; - auto d = Utilities::Checks::itemIterInContainer(filename, 'd', dl); - auto k = Utilities::Checks::itemIterInContainer(filename, 'k', dl); - auto dot = Utilities::Checks::itemIterInContainer(filename, '.', dl); - - switch(mode) - { - case 1: - { - // if (k != songPath.end() && dot != songPath.end()) - if (k != filename.end() && dot != filename.end()) - { - auto tStr = std::string(++k, dot); - std::cout << "TStr: " << tStr<<"\n"; - - if (Utilities::Checks::isNumber(tStr)) - { - track = std::atoi(tStr.c_str()); - } - } - break; - } - case 2: - { - // if (k != songPath.end() && dot != songPath.end() && d != songPath.end()) - if (k != filename.end() && dot != filename.end() && d != filename.end()) - { - auto tStr = std::string(++k, d); - auto dStr = std::string(++d, dot); - std::cout<<"DStr: "< - void parseDiscAndTrack(Song &song, const Str &trackID) - { - auto sep = [](char c, char t) { return c == t; }; - auto separator = Utilities::Checks::itemIterInContainer(trackID, ':', sep); - - if (separator != trackID.end()) - { - auto dStr = Str(trackID.begin(), separator); - auto tStr = Str(++separator, trackID.end()); - - song.disc = std::atoi(dStr.c_str()); - song.track = std::atoi(tStr.c_str()); - } - else - { - auto isNumber = Utilities::Checks::isNumber(trackID); - if (isNumber) - { - song.track = std::atoi(trackID.c_str()); - } - } - } - - - // Checks for the no confirm flag. Used when uploading songs from a directory - bool checkForNoConfirm() - { - for (const auto &arg: this->icaAction.flags) - { - if (arg.flag.compare("-nc") == 0) - { - return true; - } - } - - return false; - } - - - Album retrieveMetadata(const std::string_view path); - std::string retrieveFileContent(const std::string_view path); - - enum class ActionValues - { - deleteAct, - downloadAct, - retrieveAct, - uploadAct, - UPLOAD_SONG_WITH_METADATA // Uploads the song with metadata, including cover art - }; - - - Models::IcarusAction icaAction; - -}; - -} - -#endif diff --git a/include/Managers/FileManager.h b/include/Managers/FileManager.h deleted file mode 100644 index 675950c..0000000 --- a/include/Managers/FileManager.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef FILEMANAGER_H_ -#define FILEMANAGER_H_ - -#include - -namespace Managers -{ - -class FileManager -{ -public: - FileManager(); - FileManager(std::string); - - void saveFile(std::string); - void modifyFilePath(std::string); - - char* retrieveFileBuffer() const; - int retrieveFileBufferLength() const; -private: - void readFile(); - - std::string filePath; - char* fileBuffer; - bool fileRead; - int fileBufferLength; -}; - -} - -#endif diff --git a/include/Managers/TokenManager.h b/include/Managers/TokenManager.h deleted file mode 100644 index 4e42632..0000000 --- a/include/Managers/TokenManager.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef TOKENMANAGER_H_ -#define TOKENMANAGER_H_ - -#include"Models/API.h" -#include"Models/Token.h" -#include"Models/User.h" - -namespace Managers -{ - -class TokenManager -{ -public: - TokenManager(const Models::User&); - TokenManager(const Models::User&, Models::API&); - - Models::Token requestToken(); -private: - Models::API api; - Models::User user; -}; - -} - -#endif diff --git a/include/Managers/UserManager.h b/include/Managers/UserManager.h deleted file mode 100644 index 423e938..0000000 --- a/include/Managers/UserManager.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef USERMANAGER_H_ -#define USERMANAGER_H_ - -#include - -#include"Models/IcarusAction.h" -#include"Models/User.h" - -namespace Managers -{ - -class UserManager -{ -public: - UserManager(Models::User); - UserManager(const Models::IcarusAction); - - Models::User retrieveUser() const; -private: - void parseUserFromActions(); - - Models::User user; - Models::IcarusAction icaAction; -}; - -} - -#endif diff --git a/include/Models/API.h b/include/Models/API.h deleted file mode 100644 index 7c72fc2..0000000 --- a/include/Models/API.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef API_H_ -#define API_H_ - -#include - -namespace Models -{ - -class API -{ -public: - std::string url; - std::string endpoint; - std::string version; -}; - -} - -#endif diff --git a/include/Models/Flags.h b/include/Models/Flags.h deleted file mode 100644 index 96206f5..0000000 --- a/include/Models/Flags.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FLAGS_H_ -#define FLAGS_H_ - -#include - -namespace Models -{ - -class Flags -{ -public: - std::string flag; - std::string value; -}; - -} - -#endif diff --git a/include/Models/IcarusAction.h b/include/Models/IcarusAction.h deleted file mode 100644 index 031886d..0000000 --- a/include/Models/IcarusAction.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef ICARUSACTION_H_ -#define ICARUSACTION_H_ - -#include -#include -#include -#include -#include - -#include"Flags.h" - -namespace Models -{ - -class IcarusAction -{ -public: - std::string retrieveFlagValue(const std::string_view flag) - { - std::string value; - - const auto fg = std::find_if(flags.begin(), flags.end(), [&](Flags f) - { - return f.flag.compare(flag) == 0 ? true : false; - }); - - if (fg != flags.end()) - { - value.assign(fg->value); - } - - return value; - } - void print_action_and_flags() noexcept - { - std::cout<<"Action: "<action<<"\n"; - std::cout<<"Flag count: "<flags.size()<<"\n"; - - for (const auto &flag : this->flags) - { - std::cout<<"flag "< flags; -}; - -} - -#endif diff --git a/include/Models/Song.h b/include/Models/Song.h deleted file mode 100644 index a66c787..0000000 --- a/include/Models/Song.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef SONG_H_ -#define SONG_H_ - -#include -#include -#include - - -namespace Models -{ - -class Song -{ -public: - Song() = default; - - void printInfo() - { - std::cout<<"Title: "<title<<"\n"; - std::cout<<"\n"; - } - - std::string song_path() noexcept - { - std::stringstream buffer; - - buffer << this->directory; - - const auto count = this->directory.size(); - - if (this->directory.at(count - 1) != '/' || this->directory.at(count - 1) != '\\') - { - buffer << "/"; - } - - buffer << this->filename; - - return buffer.str(); - } - - int generate_filename_from_track() - { - auto result = 0; - std::stringstream buffer; - buffer << "track"; - - // NOTE: Multiple discs in one directory is not being addressed - if (this->track < 10) - { - buffer << "0"; - } - - buffer << this->track << ".mp3"; - - - this->filename.assign(buffer.str()); - - return result; - } - - std::string toMetadataJson(); - - - int id; - std::string title; - std::string artist; - std::string album; - std::string genre; - int year; - int duration; - int track; - int disc; - std::string data; - [[deprecated("Use song_path() function instead")]] - std::string songPath; - std::string filename; - std::string directory; -}; - -class CoverArt -{ -public: - int id; - std::string title; - std::string path; -}; - -} - -#endif diff --git a/include/Models/Token.h b/include/Models/Token.h deleted file mode 100644 index eeb0338..0000000 --- a/include/Models/Token.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TOKEN_H_ -#define TOKEN_H_ - -#include - -namespace Models -{ - -struct Token -{ - std::string accessToken; - std::string tokenType; - int expiration; -}; - -} - -#endif diff --git a/include/Models/UploadForm.h b/include/Models/UploadForm.h deleted file mode 100644 index b65b957..0000000 --- a/include/Models/UploadForm.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef UPLOADFORM_H_ -#define UPLOADFORM_H_ - -#include - - -namespace Models -{ - -struct UploadForm -{ - std::string url; - std::string filePath; -}; - -} - -#endif diff --git a/include/Models/User.h b/include/Models/User.h deleted file mode 100644 index aed560d..0000000 --- a/include/Models/User.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef USER_H_ -#define USER_H_ - -#include - -namespace Models -{ - -struct User -{ - std::string username; - std::string password; -}; - -} - -#endif diff --git a/include/Parsers/APIParser.h b/include/Parsers/APIParser.h deleted file mode 100644 index 51aa22b..0000000 --- a/include/Parsers/APIParser.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef APIPARSER_H_ -#define APIPARSER_H_ - -#include"Models/API.h" -#include"Models/IcarusAction.h" - -namespace Parsers -{ - -class APIParser -{ -public: - APIParser(Models::IcarusAction); - - Models::API retrieveAPI() const; -private: - void parseAPI(); - - Models::API api; - Models::IcarusAction icaAct; -}; - -} - -#endif diff --git a/include/Syncers/Delete.h b/include/Syncers/Delete.h deleted file mode 100644 index b927f64..0000000 --- a/include/Syncers/Delete.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef DELETE_H_ -#define DELETE_H_ - -#include"Models/API.h" -#include"Models/Song.h" -#include"Models/Token.h" - -#include"SyncerBase.h" - -namespace Syncers -{ - -class Delete : SyncerBase -{ -public: - Delete(Models::API); - - void deleteSong(const Models::Token, Models::Song); -private: - std::string retrieveUrl(Models::Song); -}; - -} - -#endif diff --git a/include/Syncers/Download.h b/include/Syncers/Download.h deleted file mode 100644 index 7c0fcb6..0000000 --- a/include/Syncers/Download.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DOWNLOAD_H_ -#define DOWNLOAD_H_ - -#include -#include - -#include"Models/API.h" -#include"Models/Song.h" -#include"Models/Token.h" - -#include"SyncerBase.h" - -namespace Syncers -{ - -class Download : SyncerBase -{ -public: - Download(); - Download(Models::API); - Download(std::string); - - void downloadSong(const Models::Token token, Models::Song); -private: - std::string retrieveUrl(Models::Song); - - std::string downloadFilePath; - void saveSong(Models::Song&); -}; - -} - -#endif diff --git a/include/Syncers/RetrieveRecords.h b/include/Syncers/RetrieveRecords.h deleted file mode 100644 index 72fa807..0000000 --- a/include/Syncers/RetrieveRecords.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RETRIEVERECORDS_H_ -#define RETRIEVERECORDS_H_ - -#include "Managers/CommitManager.h" -#include "Models/API.h" -#include "Models/Token.h" -#include "Syncers/SyncerBase.h" - -namespace Syncers -{ - -class RetrieveRecords: public SyncerBase -{ -public: - RetrieveRecords(); - RetrieveRecords(Models::API, Models::Token); - - void retrieve(Managers::CommitManager::RetrieveTypes); -private: - void fetchSongs(); - - Models::API api; - Models::Token token; -}; - -} - -#endif diff --git a/include/Syncers/SyncerBase.h b/include/Syncers/SyncerBase.h deleted file mode 100644 index 6948a42..0000000 --- a/include/Syncers/SyncerBase.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SYNCERBASE_H_ -#define SYNCERBASE_H_ - -#include - -#include"Models/API.h" - -namespace Syncers -{ - -class SyncerBase -{ -protected: - Models::API api; - const int OK = 200; - const int UNAUTHORIZED = 401; - const int NOTFOUND = 404; - - enum class Result - { - OK = 200, - UNAUTHORIZED = 401, - NOTFOUND = 404 - }; -}; - -} - -#endif diff --git a/include/Syncers/Upload.h b/include/Syncers/Upload.h deleted file mode 100644 index 49b7ce1..0000000 --- a/include/Syncers/Upload.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef UPLOAD_H_ -#define UPLOAD_H_ - -#include -#include -#include - -#include - -#include "Managers/CommitManager.h" -#include "Managers/FileManager.h" -#include "Models/API.h" -#include "Models/Song.h" -#include "Models/Token.h" -#include "Models/UploadForm.h" - -namespace fs = std::filesystem; - - -namespace Syncers -{ - -class Upload -{ -public: - Upload() = default; - Upload(Models::API api, Models::Token token) : m_token(token), api(api) - { - this->api.endpoint = "song/data"; - } - - Models::Song uploadSong(Models::Song&); - void uploadSongsFromDirectory(const std::string&, const bool, bool); - void uploadSongWithMetadata(Managers::CommitManager::Album&, Models::Song&, Models::CoverArt&); -private: - Managers::FileManager fMgr; - Models::API api; - Models::Song song; - Models::Token m_token; - - std::vector retrieveAllSongsFromDirectory(const std::string&, - bool); - - std::string retrieveUrl(); - - Models::Song retrieveSongPath(fs::directory_entry&); - - void printSongDetails(); - void printSongDetails(std::vector&); - void printJsonData(const nlohmann::json&); -}; - -} - -#endif diff --git a/include/UI/AboutWindow.h b/include/UI/AboutWindow.h deleted file mode 100644 index 15e5593..0000000 --- a/include/UI/AboutWindow.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ABOUTWINDOW_H_ -#define ABOUTWINDOW_H_ - -#include - -#include -#include -#include -#include -#include - -#include"UI/CommonWindow.h" - -namespace UI -{ - -class AboutWindow: public QDialog, public CommonWindow -{ - Q_OBJECT -public: - AboutWindow(QWidget* parent=0); - ~AboutWindow() = default; - -private: - void connections(); - void setupWindow(); - - std::unique_ptr appName; - -private slots: - void closeWindow(); -}; - -} - -#endif diff --git a/include/UI/CommonWindow.h b/include/UI/CommonWindow.h deleted file mode 100644 index f3a5413..0000000 --- a/include/UI/CommonWindow.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef COMMONWINDOW_H_ -#define COMMONWINDOW_H_ - -#include - -#include -#include -#include -#include -#include - - -namespace UI -{ - -class CommonWindow -{ -public: - CommonWindow() = default; - ~CommonWindow() = default; -protected: - virtual void connections()=0; - std::unique_ptr selectionBoxQt; - std::unique_ptr actionButtonQt; - std::unique_ptr mainLayoutQt; - std::unique_ptr subLayoutOneQt; - std::unique_ptr subLayoutTwoQt; - int windowHeight, windowWidth; -}; - -} - -#endif diff --git a/include/UI/MainWindow.h b/include/UI/MainWindow.h deleted file mode 100644 index 0460b1e..0000000 --- a/include/UI/MainWindow.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef MAINWINDOW_H_ -#define MAINWINDOW_H_ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include"UI/CommonWindow.h" -#include"UI/AboutWindow.h" - -namespace UI -{ - -class MainWindow: public QMainWindow, public CommonWindow -{ - Q_OBJECT -public: - MainWindow(); - ~MainWindow() = default; -private: - void configureDownloadSection(); - void configureUploadSection(); - void configureWindowDimensions(); - void configureWindowProperties(); - void connections(); - void createMenus(); - void setupMainWidget(); - void setupMainWindow(); - void setupWindowLists(); - - - std::unique_ptr widgetStack; - - std::unique_ptr stackLayout; - - std::unique_ptr urlPortion; - std::unique_ptr songPathPortion; - - std::unique_ptr mainWidgetQt; - std::unique_ptr uploadSongWidgetQt; - - std::unique_ptr MainDockWidgetQt; - - std::unique_ptr windowComboBox; - - std::unique_ptr uploadSongQt; - - std::unique_ptr urlQt; - std::unique_ptr sourceFilePathQt; - - std::unique_ptr urlLabel; - std::unique_ptr songPath; - - std::unique_ptr fileMenuQt; - std::unique_ptr editMenuQt; - std::unique_ptr helpMenuQt; - - std::unique_ptr closeApplicationQt; - std::unique_ptr aboutApplicationQt; - - std::unique_ptr aboutWindow; -signals: -private slots: - void uploadSong(); - void exitApplication(); - void displaySoftwareInformation(); - void setCurrentIndex(int); -}; - -} - -#endif diff --git a/include/Utilities/Checks.h b/include/Utilities/Checks.h deleted file mode 100644 index 8743e53..0000000 --- a/include/Utilities/Checks.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef CHECKS_H_ -#define CHECKS_H_ - -#include -#include -#include -#include - -namespace Utilities -{ - class Checks - { - public: - Checks() = delete; - - static auto isNumber(const std::string &val) - { - return !val.empty() && std::find_if(val.begin(), - val.end(), [](char c) - { - return !std::isdigit(c); - }) == val.end(); - } - - // Note: Not implemented - template - static auto itemInContainer(const Container container, const Item item, Func func) - { - auto result = false; - auto i = std::find_if(container.begin(), container.end(), [&](Item i) - { - return func(item, i); - }); - - if (i != container.end()) - { - result = true; - } - - return result; - } - - template - static auto itemIterInContainer(const Container &container, const Item &item, Func func) - { - auto result = false; - - auto ii = std::find_if(container.begin(), container.end(), [&](Item i) - { - return func(i, item); - }); - - if (ii == container.end()) - { - ii = container.end(); - } - - return ii; - } - private: - }; -} - -#endif - - - diff --git a/include/Utilities/Conversions.h b/include/Utilities/Conversions.h deleted file mode 100644 index 3bfa5a4..0000000 --- a/include/Utilities/Conversions.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CONVERSIONS_H_ -#define CONVERSIONS_H_ - -#include -#include - -namespace Utilities -{ - -class Conversions -{ -public: - Conversions(); - - static void toLowerChar(char &c) - { - if (std::isalpha(c)) - { - c = std::tolower(c); - } - } - - void initializeValues(); - - template - void printValue(T val); -private: -}; - -} - -#endif diff --git a/resource.h b/resource.h deleted file mode 100644 index 3b3ded8..0000000 --- a/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by IcarusDownloadManager.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/Main.cpp b/src/Main.cpp deleted file mode 100644 index b9072ac..0000000 --- a/src/Main.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include - -#include"Managers/ActionManager.h" -#include"Managers/CommitManager.h" - -using std::cin; -using std::cout; -using std::endl; -using std::string; - -using Managers::ActionManager; -using Managers::CommitManager; - -constexpr static auto IcarusDownloadManager_version() -{ - return "v0.3.2"; -} - -void printHelp() -{ - cout<<"icd [Action] [flag]\n\n"; - - cout<<"Actions\n"; - cout<<"download\n"; - cout<<"upload\n"; - cout<<"upload-meta\n"; - cout<<"retrieve\n"; - cout<<"delete\n\n"; - - cout<<"Flags\n"; - cout<<"Required for all actions\n"; - cout<<"-u username\n"; - cout<<"-p password\n"; - cout<<"-h host\n\n"; - - cout<<"Required for upload\n"; - cout<<"-s path of song\n"; - cout<<"-sd directory where to search for songs to upload (Optional)\n"; - cout<<"-sr directory where to recursively search for songs to upload (Optional)\n"; - cout<<"-nc will not prompt the user when uploading from a directory\n\n"; - - cout<<"Required for upload with metadata\n"; - cout<<"-s path of song\n"; - cout<<"-t track number\n"; - cout<<"-m metadata filepath\n"; - cout<<"-ca coverart filepath\n"; - cout<<"-scma directory where songs, metadata, and cover art exists and will be uploaded (Optional)\n\n"; - - cout<<"Required for download\n"; - cout<<"-b song id\n"; - cout<<"-d path to download song (Optional)\n\n"; - - cout<<"Required for retrieving records\n"; - cout<<"-rt retrieve type (songs is only accepted)\n\n"; - - cout<<"Required for deleting a song\n"; - cout<<"-D song id\n\n"; -} - - -int main(int argc, char** argv) -{ - if (argc < 2) - { - printHelp(); - return -1; - } - - ActionManager actMgr(argv, argc); - auto chosenAction = actMgr.retrieveIcarusAction(); - - chosenAction.print_action_and_flags(); - - CommitManager commitMgr(chosenAction); - commitMgr.commitAction(); - - return 0; -} diff --git a/src/Managers/ActionManager.cpp b/src/Managers/ActionManager.cpp deleted file mode 100644 index 27a6bfc..0000000 --- a/src/Managers/ActionManager.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include"Managers/ActionManager.h" - -#include -#include -#include -#include - -using std::cout; -using std::endl; -using std::string; -using std::string_view; -using std::vector; - -using Models::Flags; -using Models::IcarusAction; - -namespace Managers -{ - -#pragma region Constructors -ActionManager::ActionManager(char **param, int paramCount) : - params(std::move(param)), paramCount(paramCount) -{ - initialize(); -} -#pragma endregion - - -#pragma region Functions -IcarusAction ActionManager::retrieveIcarusAction() const -{ - IcarusAction icarusAction; - icarusAction.flags = flags; - icarusAction.action = action; - - return icarusAction; -} - - - -void ActionManager::initialize() -{ - validateFlags(); - - action = std::move(string{params[1]}); - transform(action.begin(), action.end(), - action.begin(), ::tolower); -} -void ActionManager::validateFlags() -{ - cout<<"Validating flags\n"; - - const auto flagVals = parsedFlags(); - - for (auto flag = flagVals.begin(); flag != flagVals.end(); ++flag) - { - Flags flg; - cout<<"Value: "<<*flag<<"\n"; - - if (isValidFlag(*flag) && doesFlagHaveValue(*flag)) - { - cout<<"Flag has value\n"; - flg.flag = *flag; - flg.value = *(++flag); - } - else if (isValidFlag(*flag)) - { - cout<<"Flag does not have a value\n"; - flg.flag = *flag; - } - else - { - cout<<"Flag "<<*flag<<" is not valid"< ActionManager::parsedFlags() -{ - auto parsed = vector(); - - for (auto i = 2; i < paramCount; ++i) - { - const std::string flag(std::move(*(params + i))); - parsed.push_back(std::move(flag)); - } - - return parsed; -} - -#pragma region Testing -void ActionManager::printAction() noexcept -{ - if (action.empty()) - { - printf("Action is empty\n"); - } - else - { - cout<<"Action is "< -#include -#include -#include - -#include "nlohmann/json.hpp" - -#include "Models/API.h" -#include "Models/Song.h" -#include "Models/Token.h" -#include "Parsers/APIParser.h" -#include "Syncers/Delete.h" -#include "Syncers/Download.h" -#include "Syncers/RetrieveRecords.h" -#include "Syncers/Upload.h" - -#include "Managers/TokenManager.h" -#include "Managers/UserManager.h" - -using std::cout; -using std::endl; -using std::map; -using std::string; - -using Managers::TokenManager; -using Managers::UserManager; -using Models::API; -using Models::Song; -using Models::Token; -using Parsers::APIParser; -using Models::IcarusAction; -using Syncers::Delete; -using Syncers::Download; -using Syncers::RetrieveRecords; -using Syncers::Upload; - -namespace filesystem = std::filesystem; - -namespace Managers -{ - -#pragma region Constructors -CommitManager::CommitManager(IcarusAction& icaAct) : icaAction(std::move(icaAct)) -{ } -#pragma endregion - - -#pragma region Functions -void CommitManager::commitAction() -{ - auto action = icaAction.action; - cout<<"Commiting "< - CommitManager::mapActions() noexcept -{ - const std::map actions{ - {"delete", ActionValues::deleteAct}, - {"download", ActionValues::downloadAct}, - {"retrieve", ActionValues::retrieveAct}, - {"upload", ActionValues::uploadAct}, - {"upload-meta", ActionValues::UPLOAD_SONG_WITH_METADATA} - }; - - return actions; -} - - - - -Token CommitManager::parseToken(API api) -{ - cout<<"fetching token\n"; - UserManager usrMgr{icaAction}; - auto user = usrMgr.retrieveUser(); - - TokenManager tk{user, api}; - - return tk.requestToken(); -} - -void CommitManager::deleteSong() -{ - APIParser apiPrs{icaAction}; - auto api = apiPrs.retrieveAPI(); - - auto token = parseToken(api); - - Song song{}; - - for (auto arg : icaAction.flags) - { - auto flag = arg.flag; - auto value = arg.value; - - if (flag.compare("-D") == 0) - { - song.id = atoi(value.c_str()); - } - } - - Delete del{api}; - cout<<"Deleting song..."<icaAction.retrieveFlagValue("-s"); - const auto metadataPath = this->icaAction.retrieveFlagValue("-m"); - const auto coverPath = this->icaAction.retrieveFlagValue("-ca"); - const auto trackID = this->icaAction.retrieveFlagValue("-t"); - const auto singleTarget = !songPath.empty() && !metadataPath.empty() && - !coverPath.empty() && !trackID.empty() ? true : false; - - const auto uni = this->icaAction.retrieveFlagValue("-smca"); - const auto multiTarget = !uni.empty() ? true : false; - - if (singleTarget && multiTarget) - { - cout<<"Cannot upload from source and directory\n"; - return; - } - - cout<<"Song path: "<(song, trackID); - - auto c = [](const Song &songA, const Song &songB) { return songA.track == songB.track && songA.disc == songB.disc; }; - auto sng = Utilities::Checks::itemIterInContainer>(album.songs, song, c); - - if (sng == album.songs.end()) - { - cout<<"Not found with disc "< songs; - Models::CoverArt cover; - string metadataPath; - - for (auto &p: fs::directory_iterator(sourcePath)) - { - const auto &pp = p.path(); - const auto stem = pp.stem(); - const auto file = pp.filename(); - const auto extension = pp.extension(); - - cout<<"Stem "< extensions; - extensions.reserve(3); - extensions.push_back(".jpg"); - extensions.push_back(".jpeg"); - extensions.push_back("."); - - return ext.compare(extensions[0]) == 0 || ext.compare(extensions[1]) == 0 || ext.compare(extensions[2]) == 0; - }; - - if (extension.compare(".mp3") == 0) - { - Song song; - song.songPath = pp.string(); - - initializeDiscAndTrack(song); - - songs.emplace_back(std::move(song)); - } - // else if (extension.compare(".jpg") == 0 || extension.compare(".png") == 0) - else if (validImg(extension.string())) - { - cover.path.assign(pp.string()); - } - else if (extension.compare(".json") == 0) - { - metadataPath.assign(pp.string()); - } - } - - auto album = retrieveMetadata(metadataPath); - songs.clear(); - songs.assign(album.songs.begin(), album.songs.end()); - - Upload up(api, token); - - for (auto &song : songs) - { - up.uploadSongWithMetadata(album, song, cover); - } -} - -#pragma region private -CommitManager::Album CommitManager::retrieveMetadata(const std::string_view path) -{ - CommitManager::Album album; - const auto fileContent = retrieveFileContent(path); - cout<<"Parsing...\n"; - auto serialized = nlohmann::json::parse(fileContent); - cout<<"Parsed\n"; - - album.album = serialized["album"].get(); - album.albumArtist = serialized["album_artist"].get(); - album.genre = serialized["genre"].get(); - album.year = serialized["year"].get(); - album.trackCount = serialized["track_count"].get(); - album.discCount = serialized["disc_count"].get(); - album.songs.reserve(album.trackCount); - - for (auto &j : serialized["tracks"]) - { - Song song; - song.title = j["title"].get(); - song.track = j["track"].get(); - song.disc = j["disc"].get(); - song.artist = j["artist"].get(); - song.album = album.album; - song.year = album.year; - song.genre = album.genre; - song.generate_filename_from_track(); - const auto p = fs::path(path); - song.directory = p.parent_path().string(); - - album.songs.push_back(song); - } - - return album; -} - -string CommitManager::retrieveFileContent(const std::string_view path) -{ - string path_str(path); - string value; - - std::stringstream buffer; - std::fstream file(path_str, std::ios::in); - buffer<album<<"\n"; - std::cout<<"Album Artist: "<albumArtist<<"\n"; - std::cout<<"Genre: "<genre<<"\n"; - std::cout<<"Year: "<year<<"\n"; - std::cout<<"Track count: "<trackCount<<"\n"; - std::cout<<"Disc count: "<discCount<<"\n"; - std::cout<<"\n"; -} - -#pragma region Functions - -} diff --git a/src/Managers/FileManager.cpp b/src/Managers/FileManager.cpp deleted file mode 100644 index a2c5618..0000000 --- a/src/Managers/FileManager.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include - -#include"Managers/FileManager.h" - -using std::cout; -using std::endl; -using std::ifstream; -using std::ofstream; -using std::string; - -namespace Managers -{ - -#pragma region Constructors -FileManager::FileManager() {} -FileManager::FileManager(string filePath) -{ - this->filePath = filePath; - readFile(); -} -#pragma endregion - - -#pragma region Functions -void FileManager::saveFile(string newFilePath) -{ - if (!fileRead) - readFile(); - - ofstream of{newFilePath, ofstream::binary}; - of.write(fileBuffer, fileBufferLength); - of.close(); -} - -void FileManager::readFile() -{ - ifstream is{filePath, ifstream::binary}; - if (is) - { - is.seekg (0, is.end); - fileBufferLength = is.tellg(); - is.seekg (0, is.beg); - - fileBuffer = new char [fileBufferLength]; - - cout<< "Reading "<filePath = filePath; -} - -char* FileManager::retrieveFileBuffer() const -{ - return fileBuffer; -} - -int FileManager::retrieveFileBufferLength() const { return fileBufferLength; } - -#pragma endregion - -} diff --git a/src/Managers/TokenManager.cpp b/src/Managers/TokenManager.cpp deleted file mode 100644 index 44f1725..0000000 --- a/src/Managers/TokenManager.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include"Managers/TokenManager.h" - -#include - -#include -#include - -using std::cout; -using std::endl; - -using json = nlohmann::json; - -using Managers::TokenManager; -using Models::API; -using Models::Token; -using Models::User; - -namespace Managers -{ - -#pragma region Constructors -TokenManager::TokenManager(const User& user) -{ - this->user = user; -} -TokenManager::TokenManager(const User& user, API& api) -{ - this->user = user; - this->api = api; - this->api.endpoint = "api/" + api.version - + "/login"; -} -#pragma endregion - - -#pragma region Functions -Token TokenManager::requestToken() -{ - Token token{}; - json usrObj; - - usrObj["username"] = user.username; - usrObj["password"] = user.password; - - cout<<"Sending request for token"< -#include -#include - -using std::string; -using std::vector; - -using Models::IcarusAction; -using Models::User; - -namespace Managers -{ - -#pragma region Constructors -UserManager::UserManager(User user) -{ - this->user = user; -} -UserManager::UserManager(const IcarusAction icaAct) -{ - this->icaAction = icaAct; - this->user = User{}; - parseUserFromActions(); -} -#pragma endregion - - -#pragma region Functions -User UserManager::retrieveUser() const -{ - return user; -} - -void UserManager::parseUserFromActions() -{ - auto args = icaAction.flags; - - for (auto arg : args) - { - auto flag = arg.flag; - if (flag.compare("-u") == 0) - { - user.username = arg.value; - } - if (flag.compare("-p") == 0) - { - user.password = arg.value; - } - } -} -#pragma endregion - -} diff --git a/src/Models/Song.cpp b/src/Models/Song.cpp deleted file mode 100644 index 49338a7..0000000 --- a/src/Models/Song.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Models/Song.h" - -#include "nlohmann/json.hpp" - -using std::string; - -namespace Models -{ - string Song::toMetadataJson() - { - nlohmann::json s; - s["title"] = this->title; - s["artist"] = this->artist; - s["album"] = this->album; - s["genre"] = this->genre; - s["year"] = this->year; - s["track"] = this->track; - s["disc"] = this->disc; - - return s.dump(); - } -} \ No newline at end of file diff --git a/src/Parsers/APIParser.cpp b/src/Parsers/APIParser.cpp deleted file mode 100644 index 379877f..0000000 --- a/src/Parsers/APIParser.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "Parsers/APIParser.h" - -#include - -using std::cout; -using std::endl; - -using Models::API; -using Models::IcarusAction; - -namespace Parsers -{ - -#pragma region Constructors -APIParser::APIParser(IcarusAction icaAct) : icaAct(icaAct) -{ - api = API{}; - parseAPI(); -} -#pragma endregion - - -#pragma region Functions -API APIParser::retrieveAPI() const -{ - return api; -} - -void APIParser::parseAPI() -{ - auto flags = icaAct.flags; - cout << "Parsing api" << endl; - - for (auto i =0; i < flags.size(); ++i) - { - auto arg = flags[i].flag; - auto value = flags[i].value; - - if (arg.compare("-h") == 0) - { - api.url = (value[value.size()-1] == '/') ? value : value + "/"; - break; - } - } - - // NOTE: For now I will hard code - // the api version since I am only - // on version 1 - api.version = "v1"; -} -#pragma endregion - -} diff --git a/src/Syncers/Delete.cpp b/src/Syncers/Delete.cpp deleted file mode 100644 index 0bc9ed3..0000000 --- a/src/Syncers/Delete.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "Syncers/Delete.h" - -#include -#include - -#include - -using std::cout; -using std::endl; -using std::exception; -using std::string; - -using Models::API; -using Models::Song; -using Models::Token; - -namespace Syncers -{ - -#pragma region Constructors -Delete::Delete(API api) -{ - this->api = api; - this->api.endpoint = "song/data"; -} -#pragma endregion - - -#pragma region Functions -void Delete::deleteSong(const Token token, Song song) -{ - try - { - auto url = retrieveUrl(song); - string auth{token.tokenType}; - auth.append(" " + token.accessToken); - auto r = cpr::Delete(cpr::Url(url), - cpr::Header{{"authorization", auth}}); - - auto statusCode = r.status_code; - - cout<<"Status code "< -#include -#include - -#include - -using std::cout; -using std::endl; -using std::exception; -using std::ofstream; -using std::string; - -using Models::API; -using Models::Song; -using Models::Token; - -namespace Syncers -{ - -#pragma region Constructors -Download::Download() { } -Download::Download(API api) -{ - this->api = api; - this->api.endpoint = "song/data"; -} -Download::Download(string filePath) -{ - downloadFilePath = filePath; -} -#pragma endregion - - -#pragma region Functions -void Download::downloadSong(const Token token, Song song) -{ - try - { - string url = retrieveUrl(song); - song.songPath.append("track.mp3"); - cout<<"song path "< -#include - -#include -#include - -#include "Utilities/Conversions.h" - -using std::cout; -using std::endl; -using std::ofstream; - -using Managers::CommitManager; -using Models::API; -using Models::Token; -using Utilities::Conversions; - -namespace Syncers -{ - -#pragma region Constructors -RetrieveRecords::RetrieveRecords() { } -RetrieveRecords::RetrieveRecords(API api, Token token) - : token(token), api(api) { } -#pragma endregion - -#pragma region Functions -void RetrieveRecords::retrieve(CommitManager::RetrieveTypes type) -{ - switch (type) - { - case CommitManager::RetrieveTypes::songs: - fetchSongs(); - break; - default: - break; - } -} -void RetrieveRecords::fetchSongs() -{ - cout<<"fetching songs"< -#include -#include - -#include "cpr/cpr.h" - -#include "Syncers/Upload.h" -#include "Utilities/Conversions.h" - -using std::cout; -using std::cin; -using std::endl; -using std::exception; -using std::string; - -using json = nlohmann::json; - -using Managers::FileManager; -using Models::API; -using Models::Song; -using Models::UploadForm; - -using namespace cpr; - -namespace Syncers -{ - -#pragma region Constructors -#pragma endregion - - -#pragma region Functions -Song Upload::uploadSong(Song& song) -{ - try - { - auto url = retrieveUrl(); - - cout<<"url "<m_token.tokenType}; - auth.append(" " + this->m_token.accessToken); - auto r = cpr::Post(cpr::Url{url}, - cpr::Multipart{{"key", "small value"}, - {"file", cpr::File{song.songPath}}}, - cpr::Header{{"authorization", auth}} - ); - - cout << "status code: " << r.status_code<< std::endl; - cout << r.text << endl; - auto result = nlohmann::json::parse(r.text); - cout<<"Finished"<(); - song.title = result["title"].get(); - song.artist = result["artist"].get(); - song.album = result["album"].get(); - song.genre = result["genre"].get(); - song.year = result["year"].get(); - song.duration = result["duration"].get(); - song.track = result["track"].get(); - - return song; - } - catch (exception& e) - { - auto msg = e.what(); - cout<> answer; - Utilities::Conversions::toLowerChar(answer); - - if (answer == 'y' || answer == 'Y') - { - confirmUpload = true; - break; - } - } - - cout << "uploading songs\n"; - for (auto& song: songs) - { - song = uploadSong(song); - } - } - catch (exception& e) - { - cout<api.endpoint.assign("song/data/upload/with/data"); - - try - { - auto url = retrieveUrl(); - - cout << "url " << url << "\n"; - string auth(this->m_token.tokenType); - auth.append(" " + this->m_token.accessToken); - - nlohmann::json s; - s["title"] = song.title; - s["album"] = album.album; - s["album_artist"] = album.albumArtist; - s["artist"] = song.artist; - s["year"] = album.year; - s["genre"] = album.genre; - s["disc"] = song.disc; - s["track"] = song.track; - s["disc_count"] = album.discCount; - s["track_count"] = album.trackCount; - - const auto meta = s.dump(); - - cout<<"\n\nMeta:\n"< Upload::retrieveAllSongsFromDirectory(const std::string& directory, - bool recursive) -{ - std::vector allSongs; - - if (recursive) - { - for (auto p: fs::recursive_directory_iterator(directory)) - { - auto song = retrieveSongPath(p); - if (!song.songPath.empty()) - allSongs.push_back(song); - } - } - else - { - for (auto p: fs::directory_iterator(directory)) - { - auto song = retrieveSongPath(p); - if (!song.songPath.empty()) - allSongs.push_back(song); - } - } - - return allSongs; -} - - -string Upload::retrieveUrl() -{ - const string url{api.url + "api/" + api.version + "/" + - api.endpoint}; - - return url; -} - - -Song Upload::retrieveSongPath(fs::directory_entry& dirEntry) -{ - constexpr auto mp3Ext = ".mp3"; - Song song; - if (fs::is_regular_file(dirEntry.path())) - { - const auto ext = dirEntry.path().extension().string(); - if (ext.compare(mp3Ext) == 0) - { - cout << "found mp3 file" << endl; - song.songPath = dirEntry.path().string(); - } - } - - return song; -} - - -#pragma region Testing - -void Upload::printSongDetails(std::vector& songs) -{ - for (auto& song: songs) - { - cout<<"Song details: "<{new QVBoxLayout}; - - appName = unique_ptr{new QLabel(tr("IcarusDownloadManager"))}; - actionButtonQt = unique_ptr{new QPushButton(tr("Close"))}; - - mainLayoutQt->addWidget(appName.get()); - mainLayoutQt->addWidget(actionButtonQt.get()); - - - setFixedWidth(windowWidth); - setFixedHeight(windowHeight); - - setLayout(mainLayoutQt.get()); - - setWindowTitle("About"); - - connections(); -} -void AboutWindow::connections() -{ - QObject::connect(actionButtonQt.get(), SIGNAL(clicked()), this, - SLOT(closeWindow())); -} - - -void AboutWindow::closeWindow() -{ - this->hide(); -} -#pragma endregion - -} diff --git a/src/UI/MainWindow.cpp b/src/UI/MainWindow.cpp deleted file mode 100644 index b44d6d3..0000000 --- a/src/UI/MainWindow.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include "UI/MainWindow.h" - -#include -#include - -#include "Models/UploadForm.h" -#include "Syncers/Upload.h" -#include "Utilities/Conversions.h" - -using std::cout; -using std::endl; -using std::string; -using std::unique_ptr; - -using Models::UploadForm; -using Syncers::Upload; - -namespace UI -{ - -#pragma region Constructors -MainWindow::MainWindow() -{ - setupMainWindow(); - aboutWindow = unique_ptr{new AboutWindow}; -} -#pragma endregion - - -#pragma region Functions -void MainWindow::configureDownloadSection() -{ -} -void MainWindow::configureUploadSection() -{ - uploadSongQt = unique_ptr{new QPushButton(tr("Upload"))}; - urlQt = unique_ptr{new QTextEdit()}; - sourceFilePathQt = unique_ptr{new QTextEdit()}; - - urlLabel = unique_ptr{new QLabel(tr("URL"))}; - songPath = unique_ptr{new QLabel(tr("Song Path"))}; - - urlPortion = unique_ptr{new QHBoxLayout}; - songPathPortion = unique_ptr{new QHBoxLayout}; - - urlPortion.get()->addWidget(urlLabel.get()); - urlPortion.get()->addWidget(urlQt.get()); - - songPathPortion->addWidget(songPath.get()); - songPathPortion->addWidget(sourceFilePathQt.get()); - - subLayoutOneQt = unique_ptr{new QVBoxLayout}; - subLayoutOneQt.get()->addLayout(urlPortion.get()); - subLayoutOneQt->addLayout(songPathPortion.get()); - mainLayoutQt.get()->addLayout(subLayoutOneQt.get()); -} -void MainWindow::configureWindowDimensions() -{ - windowWidth = 450; - windowHeight = 450; -} -void MainWindow::configureWindowProperties() -{ - setWindowTitle("IcarusDownloadManager"); - setFixedHeight(windowHeight); - setFixedWidth(windowWidth); -} -void MainWindow::connections() -{ - QObject::connect(uploadSongQt.get(), SIGNAL(clicked()), this, SLOT(uploadSong())); - QObject::connect(closeApplicationQt.get(), SIGNAL(triggered()), this, - SLOT(exitApplication())); - QObject::connect(aboutApplicationQt.get(), SIGNAL(triggered()), this, - SLOT(displaySoftwareInformation())); - QObject::connect(windowComboBox.get(), SIGNAL(activated(int)), - this, SLOT(setCurrentIndex(int))); -} -void MainWindow::createMenus() -{ - fileMenuQt = unique_ptr{menuBar()->addMenu(tr("File"))}; - editMenuQt = unique_ptr{menuBar()->addMenu(tr("Edit"))}; - helpMenuQt = unique_ptr{menuBar()->addMenu(tr("Help"))}; - - closeApplicationQt = unique_ptr{new QAction(new QObject(nullptr))}; - closeApplicationQt->setText("Exit Application"); - - aboutApplicationQt = unique_ptr{new QAction(new QObject(nullptr))}; - aboutApplicationQt->setText("About"); - - fileMenuQt->addAction(closeApplicationQt.get()); - helpMenuQt->addAction(aboutApplicationQt.get()); - -} -void MainWindow::setupMainWidget() -{ - mainWidgetQt = unique_ptr{new QWidget}; - - windowComboBox = unique_ptr{new QComboBox}; - setupWindowLists(); - - - stackLayout = unique_ptr{new QVBoxLayout}; - stackLayout->addWidget(windowComboBox.get()); - - uploadSongWidgetQt = unique_ptr{new QWidget}; - uploadSongWidgetQt->setLayout(mainLayoutQt.get()); - - stackLayout->addWidget(uploadSongWidgetQt.get()); - - mainWidgetQt->setLayout(stackLayout.get()); -} -void MainWindow::setupMainWindow() -{ - configureWindowDimensions(); - - mainLayoutQt = unique_ptr{new QVBoxLayout}; - widgetStack = unique_ptr{new QStackedWidget}; - - configureUploadSection(); - - setupMainWidget(); - - widgetStack->addWidget(mainWidgetQt.get()); - - MainDockWidgetQt = unique_ptr{new QDockWidget}; - MainDockWidgetQt.get()->setWindowTitle(tr("Music Manager")); - MainDockWidgetQt->setWidget(widgetStack.get()); - MainDockWidgetQt.get()->setFeatures(QDockWidget::NoDockWidgetFeatures); - - setCentralWidget(MainDockWidgetQt.get()); - - createMenus(); - - configureWindowProperties(); - - connections(); -} -void MainWindow::setupWindowLists() -{ - windowComboBox->addItem(tr("Upload song")); - windowComboBox->addItem(tr("Download song")); - windowComboBox->addItem(tr("Display all songs")); - windowComboBox->addItem(tr("Display songs")); -} - - -void MainWindow::exitApplication() -{ - exit(0); -} -void MainWindow::displaySoftwareInformation() -{ - aboutWindow->show(); -} -void MainWindow::setCurrentIndex(int index) -{ - cout<<"index "<itemText(index); - auto cnvert = Utilities::Conversions(qText); - auto convertedStr = cnvert.convertQStringToString(); - cout<<"item text"<setEnabled(false); - - string url = urlQt->toPlainText().toUtf8().constData(); - string filePath = sourceFilePathQt->toPlainText().toUtf8().constData(); - cout<<"URL endpoint: "<setEnabled(true); -} -#pragma endregion - -} diff --git a/src/Utilities/Conversions.cpp b/src/Utilities/Conversions.cpp deleted file mode 100644 index 92aa7bb..0000000 --- a/src/Utilities/Conversions.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "Utilities/Conversions.h" - -#include - -using std::string; -using std::unique_ptr; - -namespace Utilities -{ - -Conversions::Conversions() -{ - initializeValues(); -} - -void Conversions::initializeValues() -{ -} -template -void Conversions::printValue(T val) -{ - std::cout<<"going to print value\n"; - std::cout< Date: Sun, 7 Apr 2024 21:42:38 -0400 Subject: [PATCH 02/47] Added gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 59f00ad..1951b62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ /.vs/* /build /x64 + + +# Added by cargo + +/target -- 2.47.3 From d521802f4b0b1ac0196c83741fbfac6b3a2b53d8 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 21:43:32 -0400 Subject: [PATCH 03/47] Updated gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 1951b62..450eff1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ # Added by cargo /target +.vscode/ +Cargo.lock -- 2.47.3 From 0b4785681e05b1b7d12a9f2ea4dfdcfc73bdc521 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 21:43:48 -0400 Subject: [PATCH 04/47] Added rust code --- Cargo.toml | 12 +++++ src/main.rs | 82 +++++++++++++++++++++++++++++ src/managers/action_managers.rs | 52 +++++++++++++++++++ src/managers/commit_manager.rs | 92 +++++++++++++++++++++++++++++++++ src/managers/mod.rs | 0 src/managers/user_manager.rs | 21 ++++++++ src/models/api.rs | 8 +++ src/models/flags.rs | 7 +++ src/models/icarus_action.rs | 18 +++++++ src/models/mod.rs | 0 src/models/song.rs | 48 +++++++++++++++++ src/models/token.rs | 8 +++ src/models/upload_form.rs | 7 +++ src/models/user.rs | 7 +++ src/parsers/api_parser.rs | 0 src/parsers/mod.rs | 0 src/syncers/delete.rs | 0 src/syncers/download.rs | 0 src/syncers/mod.rs | 0 src/syncers/retrieve_records.rs | 0 src/syncers/syncer_base.rs | 0 src/syncers/upload.rs | 0 src/utilities/checks.rs | 24 +++++++++ src/utilities/conversions.rs | 19 +++++++ src/utilities/mod.rs | 0 25 files changed, 405 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/managers/action_managers.rs create mode 100644 src/managers/commit_manager.rs create mode 100644 src/managers/mod.rs create mode 100644 src/managers/user_manager.rs create mode 100644 src/models/api.rs create mode 100644 src/models/flags.rs create mode 100644 src/models/icarus_action.rs create mode 100644 src/models/mod.rs create mode 100644 src/models/song.rs create mode 100644 src/models/token.rs create mode 100644 src/models/upload_form.rs create mode 100644 src/models/user.rs create mode 100644 src/parsers/api_parser.rs create mode 100644 src/parsers/mod.rs create mode 100644 src/syncers/delete.rs create mode 100644 src/syncers/download.rs create mode 100644 src/syncers/mod.rs create mode 100644 src/syncers/retrieve_records.rs create mode 100644 src/syncers/syncer_base.rs create mode 100644 src/syncers/upload.rs create mode 100644 src/utilities/checks.rs create mode 100644 src/utilities/conversions.rs create mode 100644 src/utilities/mod.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..13088dc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "IcarusDownloadManager" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" +# rodio = "0.17.3" +# metadata = "0.1.8" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d23bb23 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,82 @@ +mod managers; +mod models; + +use std::env; +use std::process; + +// use managers::ActionManager; +// use models::{user, upload_form}; + +// use models:: + + +fn exit_program(code: i32) { + process::exit(code); +} + +fn print_help() { + let msg: String = String::from(r#"icd [Action] [flag] + + Actions + download + upload + upload-meta + retrieve + delete + + Flags + Required for all actions + -u username + -p password + -h host + + Required for upload + -s path of song + -sd directory where to search for songs to upload (Optional) + -sr directory where to recursively search for songs to upload (Optional) + -nc will not prompt the user when uploading from a directory + + Required for upload with metadata + -s path of song + -t track number + -m metadata filepath + -ca coverart filepath + -scma directory where songs, metadata, and cover art exists and will be uploaded (Optional) + + Required for download + -b song id + -d path to download song (Optional) + + Required for retrieving records + -rt retrieve type (songs is only accepted) + + Required for deleting a song + -D song id"#); + + println!("{}", msg); +} + +fn main() { + let args: Vec = env::args().collect(); + + if args.len() == 0 { + print_help(); + exit_program(-1); + } + + let act_mgr = managers::ActionManager { + action: String::from(""), + flags: Vec::new(), + params: args, + param_count: args.len(), + }; + + let chosen_act = act_mgr.retrieve_icarus_action(); + + chosen_act.print_action_and_flags(); + + let cmt_mgr = managers::CommitManager { + }; + + cmt_mgr.commit_action(); +} diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs new file mode 100644 index 0000000..34db17e --- /dev/null +++ b/src/managers/action_managers.rs @@ -0,0 +1,52 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct ActionManager { + action: String, + flags: Vec, + params: Vec, + param_count: i32, +} + +impl ActionManager { + // TODO: Implement + pub fn retrieve_icarus_action(&self) -> models::IcarusAction { + return models::IcarusAction { + action: String::from(""), + flags: Vec::new(), + }; + } + + // TODO: Implement + fn supported_flags(&self) -> Vec { + return Vec::new(); + } + + // TODO: Implement + fn supported_actions(&self) { + } + // TODO: Implement + fn initialize(&self) { + } + // TODO: Implement + fn validate_flags(&self) { + } + // TODO: Implement + fn is_valid_flag(&self, flag: &String) -> bool{ + return false; + } + // TODO: Implement + fn does_flag_have_value(&self, flag: &String) -> bool { + return false; + } + // TODO: Implement + fn print_action(&self) { + } + // TODO: Implement + fn print_flags(&self) { + } + // TODO: Implement + fn parsed_flags(&self) -> Vec { + return Vec::new(); + } +} diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs new file mode 100644 index 0000000..68c9490 --- /dev/null +++ b/src/managers/commit_manager.rs @@ -0,0 +1,92 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct CommitManager { + action: String, + flags: Vec, + params: Vec, + param_count: i32, + ica_action: models::IcarusAction, +} + +struct Album { + pub title: String, + pub album_artist: String, + pub genre: String, + pub year: i32, + pub track_count: i32, + pub disc_count: i32, + pub songs: Vec, + +} + +enum ActionValues { + DeleteAct, + DownloadAct, + RetrieveAct, + UploadAct, + UploadSongWithMetadata, +} + +enum RetrieveTypes { + Songs +} + +impl Album { + // TODO: Implement + pub fn print_info(&self) { + } +} + +impl CommitManager { + // TODO: Implement + pub fn commit_action(&self) { + } + + // TODO: Implement + fn map_actions(&self) -> HashMap { + return HashMap::new(); + } + + // TODO: Implement + fn parse_token(&self, api: &models::API) { + } + // TODO: Implement + fn upload_song_with_metadata(&self) { + } + // TODO: Implement + fn sing_target_upload(&self, songpath: &String, track_id: &String, + meta_path: &String, cover_path: &String) { + } + // TODO: Implement + fn multi_target_upload(&self, sourcepath: &String) { + } + // TODO: Implement + fn initialize_disc_and_track(&self, song: &Song) { + } + // TODO: Implement + fn parse_disc_and_track(&self, song: &Song, track_id: &String) { + } + // TODO: Implement + fn check_for_no_confirm(&self) -> bool { + return false; + } + // TODO: Implement + fn retrieve_metadata(&self, path: &String) -> models::Album { + return Album { + title: String::from(""), + album_artist: String::from(""), + genre: String::from(""), + year: 0, + track_count: 0, + disc_count: 0, + songs: Vec::new(), + }; + } + // TODO: Implement + fn retrieve_file_content(&self, path: &String) -> String { + return String::from(""); + } +} diff --git a/src/managers/mod.rs b/src/managers/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs new file mode 100644 index 0000000..217c374 --- /dev/null +++ b/src/managers/user_manager.rs @@ -0,0 +1,21 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct UserManager { + user: models::User, + ica_action: models::IcarusAction, +} + +impl UserManager { + // TODO: Implement + pub fn retrieve_user(&self) -> models::User { + return models::User { + username: String::from(""), + password: String::from(""), + }; + } + + // TODO: Implement + fn parse_user_from_actions(&self) { + } +} diff --git a/src/models/api.rs b/src/models/api.rs new file mode 100644 index 0000000..4df4aa5 --- /dev/null +++ b/src/models/api.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct API { + pub url: String, + pub endpoint: String, + pub version: String, +} diff --git a/src/models/flags.rs b/src/models/flags.rs new file mode 100644 index 0000000..8748262 --- /dev/null +++ b/src/models/flags.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct Flags { + pub flag: String, + pub value: String, +} diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs new file mode 100644 index 0000000..4ea0847 --- /dev/null +++ b/src/models/icarus_action.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct IcarusAction { + pub action: String, + pub flags: Vec, +} + +impl IcarusAction { + // TODO: Implement + pub fn retrieve_flag_value(&self, flag: &String) -> String { + return String::from(""); + } + + // TODO: Implement + pub fn print_action_and_flags(&self) { + } +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/models/song.rs b/src/models/song.rs new file mode 100644 index 0000000..a0fd312 --- /dev/null +++ b/src/models/song.rs @@ -0,0 +1,48 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct Song { + pub id: i32, + pub title: String, + pub artist: String, + pub album: String, + pub genre: String, + pub year: int, + pub duration: f64, + pub track: i32, + pub disc: i32, + pub data: String, + // use filepath instead + // pub song_path: String, + pub filepath: String, + pub directory: String, +} + +impl Song { + // TODO: Implement + pub fn print_info(&self) { + } + + // TODO: Implement + pub fn song_path(&self) -> String { + return String::from(""); + } + + // TODO: Implement + pub fn generate_filename_from_track() -> i32 { + return 0; + } + + // TODO: Implement + pub fn to_metadata_json() -> String { + return String::from(""); + } +} + + +#[derive(Debug, Deserialize, Serialize)] +struct CoverArt { + pub id: i32, + pub title: String, + pub path: String, +} \ No newline at end of file diff --git a/src/models/token.rs b/src/models/token.rs new file mode 100644 index 0000000..9710ecd --- /dev/null +++ b/src/models/token.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct Token { + pub access_token: String, + pub token_type: String, + pub expiration: i32, +} diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs new file mode 100644 index 0000000..1f78b56 --- /dev/null +++ b/src/models/upload_form.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct UploadForm { + pub url: String, + pub filepath: String, +} \ No newline at end of file diff --git a/src/models/user.rs b/src/models/user.rs new file mode 100644 index 0000000..c352bad --- /dev/null +++ b/src/models/user.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct User { + pub username: String, + pub password: String, +} \ No newline at end of file diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/parsers/mod.rs b/src/parsers/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/download.rs b/src/syncers/download.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/mod.rs b/src/syncers/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs new file mode 100644 index 0000000..e7bca40 --- /dev/null +++ b/src/utilities/checks.rs @@ -0,0 +1,24 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct Checks { +} + +impl Checks { + // TODO: Implement + pub fn is_number(val: &String) -> bool { + return false; + } + + // TODO: Implement + pub fn item_in_container(container: &Vec, item: &String, + func: fn(a: &String, b: &String) -> String) -> String { + return String::from(""); + } + + // TODO: Implement + pub fn item_iter_in_container(container: &Vec, item: &String, + func: fn(a: &String, b: &String) -> String) -> String { + return String::from(""); + } +} diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs new file mode 100644 index 0000000..d55ccae --- /dev/null +++ b/src/utilities/conversions.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct Conversions { +} + +impl Conversions { + // TODO: Implement + pub fn to_lower_char(val: &mut String) { + } + + // TODO: Implement + pub fn initialize_values(&self) { + } + + // TODO: Implement + pub fn print_value(&self, val: i32) { + } +} diff --git a/src/utilities/mod.rs b/src/utilities/mod.rs new file mode 100644 index 0000000..e69de29 -- 2.47.3 From 0e76c6d4c7cf03a0ea90529d3cdabb83320971f6 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 21:59:59 -0400 Subject: [PATCH 05/47] Added modules --- src/main.rs | 8 +++++--- src/managers/action_managers.rs | 5 ++++- src/managers/commit_manager.rs | 7 +++++-- src/managers/user_manager.rs | 5 ++++- src/models/api.rs | 5 ++++- src/models/flags.rs | 4 +++- src/models/icarus_action.rs | 5 ++++- src/models/song.rs | 7 +++++-- src/models/token.rs | 5 ++++- src/models/upload_form.rs | 5 ++++- src/models/user.rs | 5 ++++- src/utilities/checks.rs | 5 ++++- src/utilities/conversions.rs | 6 +++++- 13 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index d23bb23..459620a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,8 @@ mod models; use std::env; use std::process; -// use managers::ActionManager; +// use managers::{ActionManager}; +use crate::src::managers::{ActionManager, CommitManager}; // use models::{user, upload_form}; // use models:: @@ -64,7 +65,8 @@ fn main() { exit_program(-1); } - let act_mgr = managers::ActionManager { + let act_mgr = ActionManager { + // let act_mgr = crate::src::managers::ActionManager { action: String::from(""), flags: Vec::new(), params: args, @@ -75,7 +77,7 @@ fn main() { chosen_act.print_action_and_flags(); - let cmt_mgr = managers::CommitManager { + let cmt_mgr = CommitManager { }; cmt_mgr.commit_action(); diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 34db17e..6651d9b 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod managers { + #[derive(Debug, Deserialize, Serialize)] -struct ActionManager { +pub struct ActionManager { action: String, flags: Vec, params: Vec, @@ -50,3 +52,4 @@ impl ActionManager { return Vec::new(); } } +} diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 68c9490..45ce9e7 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -2,8 +2,10 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; +mod managers { + #[derive(Debug, Deserialize, Serialize)] -struct CommitManager { +pub struct CommitManager { action: String, flags: Vec, params: Vec, @@ -11,7 +13,7 @@ struct CommitManager { ica_action: models::IcarusAction, } -struct Album { +pub struct Album { pub title: String, pub album_artist: String, pub genre: String, @@ -90,3 +92,4 @@ impl CommitManager { return String::from(""); } } +} diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index 217c374..71fb827 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod managers { + #[derive(Debug, Deserialize, Serialize)] -struct UserManager { +pub struct UserManager { user: models::User, ica_action: models::IcarusAction, } @@ -19,3 +21,4 @@ impl UserManager { fn parse_user_from_actions(&self) { } } +} diff --git a/src/models/api.rs b/src/models/api.rs index 4df4aa5..c770b20 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -1,8 +1,11 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct API { +pub struct API { pub url: String, pub endpoint: String, pub version: String, } +} diff --git a/src/models/flags.rs b/src/models/flags.rs index 8748262..5090ed6 100644 --- a/src/models/flags.rs +++ b/src/models/flags.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod models { #[derive(Debug, Deserialize, Serialize)] -struct Flags { +pub struct Flags { pub flag: String, pub value: String, } +} diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index 4ea0847..73896b8 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct IcarusAction { +pub struct IcarusAction { pub action: String, pub flags: Vec, } @@ -16,3 +18,4 @@ impl IcarusAction { pub fn print_action_and_flags(&self) { } } +} diff --git a/src/models/song.rs b/src/models/song.rs index a0fd312..95b268f 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct Song { +pub struct Song { pub id: i32, pub title: String, pub artist: String, @@ -41,8 +43,9 @@ impl Song { #[derive(Debug, Deserialize, Serialize)] -struct CoverArt { +pub struct CoverArt { pub id: i32, pub title: String, pub path: String, +} } \ No newline at end of file diff --git a/src/models/token.rs b/src/models/token.rs index 9710ecd..53bca7f 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -1,8 +1,11 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct Token { +pub struct Token { pub access_token: String, pub token_type: String, pub expiration: i32, } +} diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs index 1f78b56..935b835 100644 --- a/src/models/upload_form.rs +++ b/src/models/upload_form.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct UploadForm { +pub struct UploadForm { pub url: String, pub filepath: String, +} } \ No newline at end of file diff --git a/src/models/user.rs b/src/models/user.rs index c352bad..39a9f98 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; +mod models { + #[derive(Debug, Deserialize, Serialize)] -struct User { +pub struct User { pub username: String, pub password: String, +} } \ No newline at end of file diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index e7bca40..1816d94 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod utilities { + #[derive(Debug, Deserialize, Serialize)] -struct Checks { +pub struct Checks { } impl Checks { @@ -22,3 +24,4 @@ impl Checks { return String::from(""); } } +} diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index d55ccae..0d18b3f 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; +mod utilities { + #[derive(Debug, Deserialize, Serialize)] -struct Conversions { +pub struct Conversions { } impl Conversions { @@ -17,3 +19,5 @@ impl Conversions { pub fn print_value(&self, val: i32) { } } + +} \ No newline at end of file -- 2.47.3 From 23771784927214cb82615f6bd745d294cea6a6f0 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 22:41:46 -0400 Subject: [PATCH 06/47] Fixed build issues --- Cargo.toml | 3 +++ src/main.rs | 17 ++++++++--------- src/managers/action_managers.rs | 18 ++++++++++-------- src/managers/commit_manager.rs | 26 ++++++++++++++------------ src/managers/mod.rs | 3 +++ src/managers/user_manager.rs | 14 ++++++++------ src/models/api.rs | 4 ++-- src/models/flags.rs | 4 ++-- src/models/icarus_action.rs | 8 +++++--- src/models/mod.rs | 7 +++++++ src/models/song.rs | 6 +++--- src/models/token.rs | 4 ++-- src/models/upload_form.rs | 4 ++-- src/models/user.rs | 17 ++++++++--------- src/parsers/mod.rs | 1 + src/syncers/mod.rs | 5 +++++ src/utilities/checks.rs | 4 ++-- src/utilities/conversions.rs | 4 ++-- src/utilities/mod.rs | 2 ++ 19 files changed, 89 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 13088dc..ef2d8a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ name = "IcarusDownloadManager" version = "0.1.0" edition = "2021" + + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/src/main.rs b/src/main.rs index 459620a..46efc53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,11 +4,6 @@ mod models; use std::env; use std::process; -// use managers::{ActionManager}; -use crate::src::managers::{ActionManager, CommitManager}; -// use models::{user, upload_form}; - -// use models:: fn exit_program(code: i32) { @@ -65,19 +60,23 @@ fn main() { exit_program(-1); } - let act_mgr = ActionManager { - // let act_mgr = crate::src::managers::ActionManager { + let act_mgr = managers::action_managers::ActionManager { action: String::from(""), flags: Vec::new(), params: args, - param_count: args.len(), + param_count: 2, }; let chosen_act = act_mgr.retrieve_icarus_action(); chosen_act.print_action_and_flags(); - let cmt_mgr = CommitManager { + let cmt_mgr = managers::commit_manager::CommitManager { + action: String::from(""), + flags: Vec::new(), + params: Vec::new(), + param_count: 1, + ica_action: chosen_act, }; cmt_mgr.commit_action(); diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 6651d9b..b4029a8 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -1,19 +1,21 @@ use serde::{Deserialize, Serialize}; -mod managers { +use crate::models; + +// mod managers { #[derive(Debug, Deserialize, Serialize)] pub struct ActionManager { - action: String, - flags: Vec, - params: Vec, - param_count: i32, + pub action: String, + pub flags: Vec, + pub params: Vec, + pub param_count: i32, } impl ActionManager { // TODO: Implement - pub fn retrieve_icarus_action(&self) -> models::IcarusAction { - return models::IcarusAction { + pub fn retrieve_icarus_action(&self) -> models::icarus_action::IcarusAction { + return models::icarus_action::IcarusAction { action: String::from(""), flags: Vec::new(), }; @@ -52,4 +54,4 @@ impl ActionManager { return Vec::new(); } } -} +// } diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 45ce9e7..12dfa8a 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -2,15 +2,17 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; -mod managers { +use crate::models; + +// mod managers { #[derive(Debug, Deserialize, Serialize)] pub struct CommitManager { - action: String, - flags: Vec, - params: Vec, - param_count: i32, - ica_action: models::IcarusAction, + pub action: String, + pub flags: Vec, + pub params: Vec, + pub param_count: i32, + pub ica_action: models::icarus_action::IcarusAction, } pub struct Album { @@ -20,7 +22,7 @@ pub struct Album { pub year: i32, pub track_count: i32, pub disc_count: i32, - pub songs: Vec, + pub songs: Vec, } @@ -53,7 +55,7 @@ impl CommitManager { } // TODO: Implement - fn parse_token(&self, api: &models::API) { + fn parse_token(&self, api: &models::api::API) { } // TODO: Implement fn upload_song_with_metadata(&self) { @@ -66,17 +68,17 @@ impl CommitManager { fn multi_target_upload(&self, sourcepath: &String) { } // TODO: Implement - fn initialize_disc_and_track(&self, song: &Song) { + fn initialize_disc_and_track(&self, song: &models::song::Song) { } // TODO: Implement - fn parse_disc_and_track(&self, song: &Song, track_id: &String) { + fn parse_disc_and_track(&self, song: &models::song::Song, track_id: &String) { } // TODO: Implement fn check_for_no_confirm(&self) -> bool { return false; } // TODO: Implement - fn retrieve_metadata(&self, path: &String) -> models::Album { + fn retrieve_metadata(&self, path: &String) -> Album { return Album { title: String::from(""), album_artist: String::from(""), @@ -92,4 +94,4 @@ impl CommitManager { return String::from(""); } } -} +// } diff --git a/src/managers/mod.rs b/src/managers/mod.rs index e69de29..33e3254 100644 --- a/src/managers/mod.rs +++ b/src/managers/mod.rs @@ -0,0 +1,3 @@ +pub mod action_managers; +pub mod commit_manager; +pub mod user_manager; \ No newline at end of file diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index 71fb827..bd81d31 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -1,17 +1,19 @@ use serde::{Deserialize, Serialize}; -mod managers { +use crate::models; + +// mod managers { #[derive(Debug, Deserialize, Serialize)] pub struct UserManager { - user: models::User, - ica_action: models::IcarusAction, + user: models::user::User, + ica_action: models::icarus_action::IcarusAction, } impl UserManager { // TODO: Implement - pub fn retrieve_user(&self) -> models::User { - return models::User { + pub fn retrieve_user(&self) -> models::user::User { + return models::user::User { username: String::from(""), password: String::from(""), }; @@ -21,4 +23,4 @@ impl UserManager { fn parse_user_from_actions(&self) { } } -} +// } diff --git a/src/models/api.rs b/src/models/api.rs index c770b20..49fe1eb 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -mod models { +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct API { @@ -8,4 +8,4 @@ pub struct API { pub endpoint: String, pub version: String, } -} +// } diff --git a/src/models/flags.rs b/src/models/flags.rs index 5090ed6..ee07178 100644 --- a/src/models/flags.rs +++ b/src/models/flags.rs @@ -1,9 +1,9 @@ use serde::{Deserialize, Serialize}; -mod models { +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Flags { pub flag: String, pub value: String, } -} +// } diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index 73896b8..d246f43 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -1,11 +1,13 @@ use serde::{Deserialize, Serialize}; -mod models { +use crate::models; + +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct IcarusAction { pub action: String, - pub flags: Vec, + pub flags: Vec, } impl IcarusAction { @@ -18,4 +20,4 @@ impl IcarusAction { pub fn print_action_and_flags(&self) { } } -} +// } diff --git a/src/models/mod.rs b/src/models/mod.rs index e69de29..5da7165 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -0,0 +1,7 @@ +pub mod api; +pub mod flags; +pub mod icarus_action; +pub mod song; +pub mod token; +pub mod upload_form; +pub mod user; \ No newline at end of file diff --git a/src/models/song.rs b/src/models/song.rs index 95b268f..08b49d0 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -mod models { +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Song { @@ -9,7 +9,7 @@ pub struct Song { pub artist: String, pub album: String, pub genre: String, - pub year: int, + pub year: i32, pub duration: f64, pub track: i32, pub disc: i32, @@ -48,4 +48,4 @@ pub struct CoverArt { pub title: String, pub path: String, } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/src/models/token.rs b/src/models/token.rs index 53bca7f..07fbe6b 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -mod models { +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Token { @@ -8,4 +8,4 @@ pub struct Token { pub token_type: String, pub expiration: i32, } -} +// } diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs index 935b835..e7f4edc 100644 --- a/src/models/upload_form.rs +++ b/src/models/upload_form.rs @@ -1,10 +1,10 @@ use serde::{Deserialize, Serialize}; -mod models { +// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct UploadForm { pub url: String, pub filepath: String, } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/src/models/user.rs b/src/models/user.rs index 39a9f98..2790a96 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,10 +1,9 @@ -use serde::{Deserialize, Serialize}; +// mod models { + use serde::{Deserialize, Serialize}; -mod models { - -#[derive(Debug, Deserialize, Serialize)] -pub struct User { - pub username: String, - pub password: String, -} -} \ No newline at end of file + #[derive(Debug, Deserialize, Serialize)] + pub struct User { + pub username: String, + pub password: String, + } +// } \ No newline at end of file diff --git a/src/parsers/mod.rs b/src/parsers/mod.rs index e69de29..c5b5ef6 100644 --- a/src/parsers/mod.rs +++ b/src/parsers/mod.rs @@ -0,0 +1 @@ +pub mod api_parser; \ No newline at end of file diff --git a/src/syncers/mod.rs b/src/syncers/mod.rs index e69de29..5eddbb6 100644 --- a/src/syncers/mod.rs +++ b/src/syncers/mod.rs @@ -0,0 +1,5 @@ +pub mod delete; +pub mod download; +pub mod retrieve_records; +pub mod syncer_base; +pub mod upload; \ No newline at end of file diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 1816d94..ace1ca7 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -mod utilities { +// mod utilities { #[derive(Debug, Deserialize, Serialize)] pub struct Checks { @@ -24,4 +24,4 @@ impl Checks { return String::from(""); } } -} +// } diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index 0d18b3f..822ac12 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -mod utilities { +// mod utilities { #[derive(Debug, Deserialize, Serialize)] pub struct Conversions { @@ -20,4 +20,4 @@ impl Conversions { } } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/src/utilities/mod.rs b/src/utilities/mod.rs index e69de29..e7eb3d8 100644 --- a/src/utilities/mod.rs +++ b/src/utilities/mod.rs @@ -0,0 +1,2 @@ +pub mod checks; +pub mod conversions; \ No newline at end of file -- 2.47.3 From 4cbe4ca41d6367b154014504adc2a19dbe38c17e Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 7 Apr 2024 22:42:55 -0400 Subject: [PATCH 07/47] rustfmt --- src/main.rs | 8 +++---- src/managers/action_managers.rs | 17 ++++++--------- src/managers/commit_manager.rs | 37 +++++++++++++++------------------ src/managers/mod.rs | 2 +- src/managers/user_manager.rs | 3 +-- src/models/icarus_action.rs | 3 +-- src/models/mod.rs | 2 +- src/models/song.rs | 6 ++---- src/models/upload_form.rs | 2 +- src/models/user.rs | 14 ++++++------- 10 files changed, 41 insertions(+), 53 deletions(-) diff --git a/src/main.rs b/src/main.rs index 46efc53..f1313c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,14 +4,13 @@ mod models; use std::env; use std::process; - - fn exit_program(code: i32) { process::exit(code); } fn print_help() { - let msg: String = String::from(r#"icd [Action] [flag] + let msg: String = String::from( + r#"icd [Action] [flag] Actions download @@ -47,7 +46,8 @@ fn print_help() { -rt retrieve type (songs is only accepted) Required for deleting a song - -D song id"#); + -D song id"#, + ); println!("{}", msg); } diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index b4029a8..487e4f7 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -27,16 +27,13 @@ impl ActionManager { } // TODO: Implement - fn supported_actions(&self) { - } + fn supported_actions(&self) {} // TODO: Implement - fn initialize(&self) { - } + fn initialize(&self) {} // TODO: Implement - fn validate_flags(&self) { - } + fn validate_flags(&self) {} // TODO: Implement - fn is_valid_flag(&self, flag: &String) -> bool{ + fn is_valid_flag(&self, flag: &String) -> bool { return false; } // TODO: Implement @@ -44,11 +41,9 @@ impl ActionManager { return false; } // TODO: Implement - fn print_action(&self) { - } + fn print_action(&self) {} // TODO: Implement - fn print_flags(&self) { - } + fn print_flags(&self) {} // TODO: Implement fn parsed_flags(&self) -> Vec { return Vec::new(); diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 12dfa8a..dc0ec22 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -23,7 +23,6 @@ pub struct Album { pub track_count: i32, pub disc_count: i32, pub songs: Vec, - } enum ActionValues { @@ -35,19 +34,17 @@ enum ActionValues { } enum RetrieveTypes { - Songs + Songs, } impl Album { // TODO: Implement - pub fn print_info(&self) { - } + pub fn print_info(&self) {} } impl CommitManager { // TODO: Implement - pub fn commit_action(&self) { - } + pub fn commit_action(&self) {} // TODO: Implement fn map_actions(&self) -> HashMap { @@ -55,24 +52,24 @@ impl CommitManager { } // TODO: Implement - fn parse_token(&self, api: &models::api::API) { + fn parse_token(&self, api: &models::api::API) {} + // TODO: Implement + fn upload_song_with_metadata(&self) {} + // TODO: Implement + fn sing_target_upload( + &self, + songpath: &String, + track_id: &String, + meta_path: &String, + cover_path: &String, + ) { } // TODO: Implement - fn upload_song_with_metadata(&self) { - } + fn multi_target_upload(&self, sourcepath: &String) {} // TODO: Implement - fn sing_target_upload(&self, songpath: &String, track_id: &String, - meta_path: &String, cover_path: &String) { - } + fn initialize_disc_and_track(&self, song: &models::song::Song) {} // TODO: Implement - fn multi_target_upload(&self, sourcepath: &String) { - } - // TODO: Implement - fn initialize_disc_and_track(&self, song: &models::song::Song) { - } - // TODO: Implement - fn parse_disc_and_track(&self, song: &models::song::Song, track_id: &String) { - } + fn parse_disc_and_track(&self, song: &models::song::Song, track_id: &String) {} // TODO: Implement fn check_for_no_confirm(&self) -> bool { return false; diff --git a/src/managers/mod.rs b/src/managers/mod.rs index 33e3254..3699871 100644 --- a/src/managers/mod.rs +++ b/src/managers/mod.rs @@ -1,3 +1,3 @@ pub mod action_managers; pub mod commit_manager; -pub mod user_manager; \ No newline at end of file +pub mod user_manager; diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index bd81d31..bafc7da 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -20,7 +20,6 @@ impl UserManager { } // TODO: Implement - fn parse_user_from_actions(&self) { - } + fn parse_user_from_actions(&self) {} } // } diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index d246f43..47916ce 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -17,7 +17,6 @@ impl IcarusAction { } // TODO: Implement - pub fn print_action_and_flags(&self) { - } + pub fn print_action_and_flags(&self) {} } // } diff --git a/src/models/mod.rs b/src/models/mod.rs index 5da7165..986c861 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -4,4 +4,4 @@ pub mod icarus_action; pub mod song; pub mod token; pub mod upload_form; -pub mod user; \ No newline at end of file +pub mod user; diff --git a/src/models/song.rs b/src/models/song.rs index 08b49d0..d7ce412 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -22,8 +22,7 @@ pub struct Song { impl Song { // TODO: Implement - pub fn print_info(&self) { - } + pub fn print_info(&self) {} // TODO: Implement pub fn song_path(&self) -> String { @@ -41,11 +40,10 @@ impl Song { } } - #[derive(Debug, Deserialize, Serialize)] pub struct CoverArt { pub id: i32, pub title: String, pub path: String, } -// } \ No newline at end of file +// } diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs index e7f4edc..4ca2548 100644 --- a/src/models/upload_form.rs +++ b/src/models/upload_form.rs @@ -7,4 +7,4 @@ pub struct UploadForm { pub url: String, pub filepath: String, } -// } \ No newline at end of file +// } diff --git a/src/models/user.rs b/src/models/user.rs index 2790a96..3f6d277 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,9 +1,9 @@ // mod models { - use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; - #[derive(Debug, Deserialize, Serialize)] - pub struct User { - pub username: String, - pub password: String, - } -// } \ No newline at end of file +#[derive(Debug, Deserialize, Serialize)] +pub struct User { + pub username: String, + pub password: String, +} +// } -- 2.47.3 From 3fafea1f9f3633f49ae002acf6b3d411bf4fe866 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 12:35:52 -0400 Subject: [PATCH 08/47] Updated models --- src/models/api.rs | 14 +++++++-- src/models/flags.rs | 13 ++++++-- src/models/icarus_action.rs | 13 ++++++-- src/models/song.rs | 63 +++++++++++++++++++++++++++---------- src/models/token.rs | 20 +++++++++--- src/models/upload_form.rs | 17 +++++++--- src/models/user.rs | 13 ++++++-- 7 files changed, 119 insertions(+), 34 deletions(-) diff --git a/src/models/api.rs b/src/models/api.rs index 49fe1eb..2ed7415 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -1,6 +1,7 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct API { @@ -8,4 +9,13 @@ pub struct API { pub endpoint: String, pub version: String, } -// } + +impl Default for API { + fn default() -> Self { + API { + url: String::from(""), + endpoint: String::from(""), + version: String::from(""), + } + } +} \ No newline at end of file diff --git a/src/models/flags.rs b/src/models/flags.rs index ee07178..9be619b 100644 --- a/src/models/flags.rs +++ b/src/models/flags.rs @@ -1,9 +1,18 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Flags { pub flag: String, pub value: String, } -// } + +impl Default for Flags { + fn default() -> Self { + Flags { + flag: String::new(), + value: String::new(), + } + } +} diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index 47916ce..bc8f687 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -1,8 +1,9 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; use crate::models; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct IcarusAction { @@ -10,6 +11,15 @@ pub struct IcarusAction { pub flags: Vec, } +impl Default for IcarusAction { + fn default() -> Self { + IcarusAction { + action: String::new(), + flags: Vec::new(), + } + } +} + impl IcarusAction { // TODO: Implement pub fn retrieve_flag_value(&self, flag: &String) -> String { @@ -19,4 +29,3 @@ impl IcarusAction { // TODO: Implement pub fn print_action_and_flags(&self) {} } -// } diff --git a/src/models/song.rs b/src/models/song.rs index d7ce412..ad4e98d 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -1,23 +1,43 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Song { - pub id: i32, - pub title: String, - pub artist: String, - pub album: String, - pub genre: String, - pub year: i32, - pub duration: f64, - pub track: i32, - pub disc: i32, - pub data: String, + pub id: Option, + pub title: Option, + pub artist: Option, + pub album: Option, + pub genre: Option, + pub year: Option, + pub duration: Option, + pub track: Option, + pub disc: Option, + pub data: Option, // use filepath instead // pub song_path: String, - pub filepath: String, - pub directory: String, + pub filepath: Option, + pub directory: Option, +} + +impl Default for Song { + fn default() -> Self { + Song { + id: None, + title: None, + artist: None, + album: None, + genre: None, + year: None, + duration: None, + track: None, + disc: None, + data: None, + filepath: None, + directory: None, + } + } } impl Song { @@ -42,8 +62,17 @@ impl Song { #[derive(Debug, Deserialize, Serialize)] pub struct CoverArt { - pub id: i32, - pub title: String, - pub path: String, + pub id: Option, + pub title: Option, + pub path: Option, +} + +impl Default for CoverArt { + fn default() -> Self { + CoverArt { + id: None, + title: None, + path: None, + } + } } -// } diff --git a/src/models/token.rs b/src/models/token.rs index 07fbe6b..73a3bb2 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -1,11 +1,21 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct Token { - pub access_token: String, - pub token_type: String, - pub expiration: i32, + pub access_token: Option, + pub token_type: Option, + pub expiration: Option, +} + +impl Default for Token { + fn default() -> Self { + Token { + access_token: None, + token_type: None, + expiration: None, + } + } } -// } diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs index 4ca2548..903d5b4 100644 --- a/src/models/upload_form.rs +++ b/src/models/upload_form.rs @@ -1,10 +1,19 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -// mod models { #[derive(Debug, Deserialize, Serialize)] pub struct UploadForm { - pub url: String, - pub filepath: String, + pub url: Option, + pub filepath: Option, } -// } + +impl Default for UploadForm { + fn default() -> Self { + UploadForm { + url: None, + filepath: None, + } + } +} \ No newline at end of file diff --git a/src/models/user.rs b/src/models/user.rs index 3f6d277..54c20cf 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,4 +1,5 @@ -// mod models { +use std::default::Default; + use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize)] @@ -6,4 +7,12 @@ pub struct User { pub username: String, pub password: String, } -// } + +impl Default for User { + fn default() -> Self { + User { + username: String::new(), + password: String::new(), + } + } +} -- 2.47.3 From 269899af0797ea81887f9c2d4fcd581a098a0e69 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 12:36:20 -0400 Subject: [PATCH 09/47] Added parsers module --- src/parsers/api_parser.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs index e69de29..4ea10da 100644 --- a/src/parsers/api_parser.rs +++ b/src/parsers/api_parser.rs @@ -0,0 +1,20 @@ + +use crate::models; + +pub struct APIParser { + pub api: models::api::API, + pub ica_act: models::icarus_action::IcarusAction, +} + +impl APIParser { + // pub fn init() -> APIParser { + // } + + pub fn retrieve_api(&self) -> models::api::API { + return models::api::API::default(); + } + + // TODO: Implement + fn parse_api(&self) { + } +} \ No newline at end of file -- 2.47.3 From 0307c0254b44621616b93034432d32e508325806 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 12:36:40 -0400 Subject: [PATCH 10/47] Updated utilities module --- src/utilities/checks.rs | 6 +----- src/utilities/conversions.rs | 15 +++++++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index ace1ca7..464ca6d 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -1,15 +1,12 @@ use serde::{Deserialize, Serialize}; -// mod utilities { - #[derive(Debug, Deserialize, Serialize)] pub struct Checks { } impl Checks { - // TODO: Implement pub fn is_number(val: &String) -> bool { - return false; + return val.is_numeric(); } // TODO: Implement @@ -24,4 +21,3 @@ impl Checks { return String::from(""); } } -// } diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index 822ac12..ed90b8d 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -1,23 +1,22 @@ use serde::{Deserialize, Serialize}; -// mod utilities { #[derive(Debug, Deserialize, Serialize)] pub struct Conversions { } impl Conversions { - // TODO: Implement - pub fn to_lower_char(val: &mut String) { + pub fn to_lower_char(val: &mut char) { + if val.is_alphabetic() { + val = val.to_lowercase(); + } } - // TODO: Implement pub fn initialize_values(&self) { } - // TODO: Implement - pub fn print_value(&self, val: i32) { + pub fn print_value(&self, val: T) { + println!("Going to print value"); + println!("{}", val); } } - -// } \ No newline at end of file -- 2.47.3 From 66fb53185ebbb055c71ca8f72d02b2283c42ad86 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 12:37:19 -0400 Subject: [PATCH 11/47] Updated main.rs --- src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index f1313c6..5a6a66f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,11 +60,13 @@ fn main() { exit_program(-1); } + let args_len = args.len() as i32; + let act_mgr = managers::action_managers::ActionManager { action: String::from(""), flags: Vec::new(), params: args, - param_count: 2, + param_count: args_len, }; let chosen_act = act_mgr.retrieve_icarus_action(); -- 2.47.3 From a071fc93ba56a701919906504daa920bad3d642c Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 13:27:45 -0400 Subject: [PATCH 12/47] Updated api_parser and song model --- src/models/song.rs | 51 ++++++++++++++++++++++++++++++--------- src/parsers/api_parser.rs | 26 +++++++++++++++----- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/models/song.rs b/src/models/song.rs index ad4e98d..bce2972 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -3,7 +3,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { pub id: Option, pub title: Option, @@ -41,22 +41,51 @@ impl Default for Song { } impl Song { - // TODO: Implement - pub fn print_info(&self) {} - - // TODO: Implement - pub fn song_path(&self) -> String { - return String::from(""); + pub fn print_info(&self) { + println!("Title: {:?}", self.title); } - // TODO: Implement - pub fn generate_filename_from_track() -> i32 { + pub fn song_path(&self) -> String { + // let directory = &self.directory.unwrap(); + let directory = & 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 = & as Clone>::clone(&self.filepath).unwrap(); + buffer += filename; + + return 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 += ".mp3"; + } else { + filename += ".wav"; + } + + // &mut self.filepath = Some(filename); + self.filepath = Some(filename); + return 0; } // TODO: Implement - pub fn to_metadata_json() -> String { - return String::from(""); + pub fn to_metadata_json(&self) -> Result { + return serde_json::to_string_pretty(&self); } } diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs index 4ea10da..7bfdb96 100644 --- a/src/parsers/api_parser.rs +++ b/src/parsers/api_parser.rs @@ -7,14 +7,28 @@ pub struct APIParser { } impl APIParser { - // pub fn init() -> APIParser { - // } - pub fn retrieve_api(&self) -> models::api::API { - return models::api::API::default(); + return self.api; } - // TODO: Implement - fn parse_api(&self) { + pub fn parse_api(&self) { + let flags = self.ica_act.flags; + println!("Parsing api"); + + for (i, elem) in flags { + let arg = elem.flag; + let value = elem.value; + + if arg == "-h" { + if value.chars().nth((value.len() - 1)) == '/' { + self.api.url = value; + } else { + self.api.url = value + "/"; + } + break; + } + } + + self.api.version = "v1"; } } \ No newline at end of file -- 2.47.3 From 3bd2d6175b1e6e4d717584191be59adac975729d Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 14:42:49 -0400 Subject: [PATCH 13/47] Updated icarus_action model --- src/models/icarus_action.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index bc8f687..b5528ff 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -21,11 +21,25 @@ impl Default for IcarusAction { } impl IcarusAction { - // TODO: Implement pub fn retrieve_flag_value(&self, flag: &String) -> String { - return String::from(""); + let mut val: String = String::new(); + + for f in self.flags.iter() { + if f.flag == *flag { + val = flag.clone(); + break; + } + } + + return val; } - // TODO: Implement - pub fn print_action_and_flags(&self) {} + pub fn print_action_and_flags(&self) { + println!("Action: {}", self.action); + println!("Flag count: {}", self.flags.len()); + + for flag in self.flags.iter() { + println!("flag {} value {}", flag.flag, flag.value); + } + } } -- 2.47.3 From 82ab9142e672f303be125d4d6b933908df5d39bf Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 16:17:55 -0400 Subject: [PATCH 14/47] Updated structs in managers module --- src/managers/action_managers.rs | 132 ++++++++++++++++++++++++++------ src/models/flags.rs | 2 +- 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 487e4f7..f875e60 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -2,8 +2,6 @@ use serde::{Deserialize, Serialize}; use crate::models; -// mod managers { - #[derive(Debug, Deserialize, Serialize)] pub struct ActionManager { pub action: String, @@ -13,40 +11,130 @@ pub struct ActionManager { } impl ActionManager { - // TODO: Implement pub fn retrieve_icarus_action(&self) -> models::icarus_action::IcarusAction { return models::icarus_action::IcarusAction { - action: String::from(""), - flags: Vec::new(), + flags: self.flags.clone(), + action: String::from(&self.action), }; } - // TODO: Implement fn supported_flags(&self) -> Vec { - return Vec::new(); + return vec![String::from("-u"), + String::from("-p"), + String::from("-t"), + String::from("-h"), + String::from("-s"), + String::from("-sd"), + String::from("-sr"), + String::from("-d"), + String::from("-D"), + String::from("-b"), + String::from("-rt"), + String::from("-nc"), + String::from("-m"), + String::from("-ca"), + String::from("-smca"), + String::from("-t"), + ]; } // TODO: Implement fn supported_actions(&self) {} - // TODO: Implement - fn initialize(&self) {} - // TODO: Implement - fn validate_flags(&self) {} - // TODO: Implement + + pub fn initialize(&mut self) { + self.validate_flags(); + self.action = self.action.to_lowercase(); + } + + fn validate_flags(&mut self) { + println!("Validating flags"); + + let flag_vals = self.parsed_flags(); + + for i in 0..flag_vals.len() { + let flag = &flag_vals[i]; + println!("Value: {}", flag); + + let mut flg = models::flags::Flags::default(); + + if self.is_valid_flag(flag) && self.does_flag_have_value(flag) { + println!("Flag has value"); + flg.flag = String::from(flag); + flg.value = String::from(&flag_vals[i+1]); + } else if self.is_valid_flag(flag) { + println!("Flag does not have a value"); + flg.flag = String::from(flag); + } else { + println!("Flag {} is not valid", flag); + std::process::exit(-1); + } + + self.flags.push(flg); + } + } + fn is_valid_flag(&self, flag: &String) -> bool { - return false; + let flags = self.supported_flags(); + let mut found: bool = false; + + for flg in &flags { + if flg == flag { + found = true; + break; + } + } + + return found; } - // TODO: Implement + fn does_flag_have_value(&self, flag: &String) -> bool { - return false; + let flags_tmp = self.parsed_flags(); + + let mut i_found: i32 = -1; + + for i in 0..flags_tmp.len() { + let flg = &flags_tmp[i]; + if flg == flag { + i_found = i as i32; + break; + } + } + + if i_found >= 0 { + if (i_found + 1) < flags_tmp.len().try_into().unwrap() { + return true; + } else { + return false; + } + } else { + return false; + } } - // TODO: Implement - fn print_action(&self) {} - // TODO: Implement - fn print_flags(&self) {} - // TODO: Implement + + fn print_action(&self) { + if self.action.len() == 0 { + println!("Action is empty"); + } else { + println!("Action is {}", self.action); + } + } + + fn print_flags(&self) { + println!("Printing flags..."); + for flag in &self.flags { + println!("Flag {}", flag.flag); + println!("Value {}", flag.value); + } + } + fn parsed_flags(&self) -> Vec { - return Vec::new(); + let mut parsed: Vec = Vec::new(); + + for i in 2..self.params.len() { + let flag = String::from(&self.params[i]); + parsed.push(flag); + } + + return parsed; } } -// } diff --git a/src/models/flags.rs b/src/models/flags.rs index 9be619b..d51f2b3 100644 --- a/src/models/flags.rs +++ b/src/models/flags.rs @@ -2,7 +2,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct Flags { pub flag: String, pub value: String, -- 2.47.3 From 8551f4a6c4c8e689b482411f6a23c6fdfc859396 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 16:18:05 -0400 Subject: [PATCH 15/47] Updated main.rs --- src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5a6a66f..9fb8eb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,12 +62,13 @@ fn main() { let args_len = args.len() as i32; - let act_mgr = managers::action_managers::ActionManager { + let mut act_mgr = managers::action_managers::ActionManager { action: String::from(""), flags: Vec::new(), params: args, param_count: args_len, }; + act_mgr.initialize(); let chosen_act = act_mgr.retrieve_icarus_action(); @@ -81,5 +82,5 @@ fn main() { ica_action: chosen_act, }; - cmt_mgr.commit_action(); + // cmt_mgr.commit_action(); } -- 2.47.3 From ce0ec470ec8faa0c0d30450f0102a28ea8bd7f02 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 16:46:53 -0400 Subject: [PATCH 16/47] More changes --- src/main.rs | 13 ++++++++----- src/managers/commit_manager.rs | 12 +++++------- src/models/api.rs | 2 +- src/models/icarus_action.rs | 2 +- src/models/song.rs | 3 --- src/parsers/api_parser.rs | 17 +++++++++++------ src/utilities/checks.rs | 4 ++-- src/utilities/conversions.rs | 6 +++--- 8 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9fb8eb2..2260a2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ mod managers; mod models; +mod utilities; +mod parsers; +mod syncers; use std::env; use std::process; @@ -75,12 +78,12 @@ fn main() { chosen_act.print_action_and_flags(); let cmt_mgr = managers::commit_manager::CommitManager { - action: String::from(""), - flags: Vec::new(), - params: Vec::new(), - param_count: 1, +// action: String::from(""), +// flags: Vec::new(), +// params: Vec::new(), +// param_count: 1, ica_action: chosen_act, }; - // cmt_mgr.commit_action(); + cmt_mgr.commit_action(); } diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index dc0ec22..c13c40c 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -3,15 +3,14 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; use crate::models; - -// mod managers { +use crate::utilities; #[derive(Debug, Deserialize, Serialize)] pub struct CommitManager { - pub action: String, - pub flags: Vec, - pub params: Vec, - pub param_count: i32, + // pub action: String, + // pub flags: Vec, + // pub params: Vec, + // pub param_count: i32, pub ica_action: models::icarus_action::IcarusAction, } @@ -91,4 +90,3 @@ impl CommitManager { return String::from(""); } } -// } diff --git a/src/models/api.rs b/src/models/api.rs index 2ed7415..774ffcd 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -3,7 +3,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct API { pub url: String, pub endpoint: String, diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index b5528ff..1d2d3d6 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::models; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct IcarusAction { pub action: String, pub flags: Vec, diff --git a/src/models/song.rs b/src/models/song.rs index bce2972..2f7b0d3 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -46,7 +46,6 @@ impl Song { } pub fn song_path(&self) -> String { - // let directory = &self.directory.unwrap(); let directory = & as Clone>::clone(&self.directory).unwrap(); let mut buffer: String = directory.to_string(); @@ -77,13 +76,11 @@ impl Song { filename += ".wav"; } - // &mut self.filepath = Some(filename); self.filepath = Some(filename); return 0; } - // TODO: Implement pub fn to_metadata_json(&self) -> Result { return serde_json::to_string_pretty(&self); } diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs index 7bfdb96..8c8a684 100644 --- a/src/parsers/api_parser.rs +++ b/src/parsers/api_parser.rs @@ -1,6 +1,7 @@ use crate::models; +#[derive(Clone, Debug)] pub struct APIParser { pub api: models::api::API, pub ica_act: models::icarus_action::IcarusAction, @@ -8,27 +9,31 @@ pub struct APIParser { impl APIParser { pub fn retrieve_api(&self) -> models::api::API { - return self.api; + return self.api.clone(); } - pub fn parse_api(&self) { - let flags = self.ica_act.flags; + pub fn parse_api(&mut self) { + let flags = self.ica_act.flags.clone(); println!("Parsing api"); - for (i, elem) in flags { + let mut i = 0; + // for (i, elem) in flags { + for elem in flags { let arg = elem.flag; let value = elem.value; if arg == "-h" { - if value.chars().nth((value.len() - 1)) == '/' { + if value.chars().nth((value.len() - 1)) == Some('/') { self.api.url = value; } else { self.api.url = value + "/"; } break; } + + i += 1; } - self.api.version = "v1"; + self.api.version = "v1".to_string(); } } \ No newline at end of file diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 464ca6d..9287291 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -5,8 +5,8 @@ pub struct Checks { } impl Checks { - pub fn is_number(val: &String) -> bool { - return val.is_numeric(); + pub fn is_numeric(text: &String) -> bool { + text.parse::().is_ok() } // TODO: Implement diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index ed90b8d..c0bf7fd 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -8,15 +8,15 @@ pub struct Conversions { impl Conversions { pub fn to_lower_char(val: &mut char) { if val.is_alphabetic() { - val = val.to_lowercase(); + *val = val.to_lowercase().next().unwrap(); } } pub fn initialize_values(&self) { } - pub fn print_value(&self, val: T) { + pub fn print_value(&self, val: T) { println!("Going to print value"); - println!("{}", val); + println!("{:?}", val); } } -- 2.47.3 From 1cd66ce1de0b139ac6a7907b1b754ec7c90c73c5 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 8 Apr 2024 18:26:47 -0400 Subject: [PATCH 17/47] Saving changes --- src/managers/commit_manager.rs | 107 +++++++++++++++++++++++++++++++-- src/utilities/checks.rs | 16 +++++ 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index c13c40c..ef26043 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,3 +1,4 @@ +use std::default::Default; use std::collections::HashMap; use serde::{Deserialize, Serialize}; @@ -14,6 +15,7 @@ pub struct CommitManager { pub ica_action: models::icarus_action::IcarusAction, } + pub struct Album { pub title: String, pub album_artist: String, @@ -24,6 +26,20 @@ pub struct Album { pub songs: Vec, } +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(), + } + } +} + enum ActionValues { DeleteAct, DownloadAct, @@ -37,19 +53,55 @@ enum RetrieveTypes { } impl Album { - // TODO: Implement - pub fn print_info(&self) {} + 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: {}", self.disc_count); + } } impl CommitManager { - // TODO: Implement - pub fn commit_action(&self) {} + + pub fn commit_action(&self) { + let action = &self.ica_action.action; + println!("Committing {} action", action); + + match self.map_actions()[action] { + ActionValues::DeleteAct => self.delete_song(), + ActionValues::DownloadAct => self.download_song(), + ActionValues::RetrieveAct => self.retrieve_object(), + ActionValues::UploadAct => self.upload_song(), + ActionValues::UploadSongWithMetadata => self.upload_song_with_metadata(), + _ => { + println!("Nothing good here"); + } + } + } // TODO: Implement fn map_actions(&self) -> HashMap { return HashMap::new(); } + // TODO: Implement + fn delete_song(&self) { + } + + // TODO: Implement + fn download_song(&self) { + } + + // TODO: Implement + fn retrieve_object(&self) { + } + + // TODO: Implement + fn upload_song(&self) { + } + // TODO: Implement fn parse_token(&self, api: &models::api::API) {} // TODO: Implement @@ -66,7 +118,52 @@ impl CommitManager { // TODO: Implement fn multi_target_upload(&self, sourcepath: &String) {} // TODO: Implement - fn initialize_disc_and_track(&self, song: &models::song::Song) {} + // 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) { + let disc = 1; + let track = 1; + let mut mode = 0; + let songpath = song.song_path(); + let filename = & as Clone>::clone(&song.filepath).unwrap(); + + // let directory = & as Clone>::clone(&self.directory).unwrap(); + let trd = filename.contains("trackd"); + let tr = filename.contains("track"); + + if tr { + mode = 1; + } + + if trd { + mode = 2; + } + + let dl = |a: &char, b: &char| -> bool { + return a == b; + }; + let d = utilities::checks::Checks::index_of_item_in_container(&filename, &'d', dl); + let k = utilities::checks::Checks::index_of_item_in_container(&filename, &'k', dl); + let dot = utilities::checks::Checks::index_of_item_in_container(&filename, &'.', dl); + let end = filename.len() as i32; + + match mode { + 1 => { + if k != end && dot != end { + let st = k + 1; + let ed = dot - 1; + let t = &filename[&st..&ed]; + } + }, + 2 => { + }, + _ => println!(""), + } + + song.disc = Some(disc); + song.track = Some(track); + } // TODO: Implement fn parse_disc_and_track(&self, song: &models::song::Song, track_id: &String) {} // TODO: Implement diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 9287291..adcbc0c 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -20,4 +20,20 @@ impl Checks { func: fn(a: &String, b: &String) -> String) -> String { return String::from(""); } + + // TODO: Implement + pub fn index_of_item_in_container(container: &String, item: &char, + func: fn(a: &char, b: &char) -> bool) -> i32 { + let mut index = -1; + + for c in container.chars() { + if func(&c, item) { + break; + } + + index += 1; + } + + return index; + } } -- 2.47.3 From c7141533be67f9b043d075f1085863bffc0bea4b Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 14 Apr 2024 20:00:27 -0400 Subject: [PATCH 18/47] Added new struct and methods --- src/managers/token_manager.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/managers/token_manager.rs diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs new file mode 100644 index 0000000..20313da --- /dev/null +++ b/src/managers/token_manager.rs @@ -0,0 +1,32 @@ +use std::default::Default; + +use crate::models; + +pub struct TokenManager { + pub user: models::user::User, + pub api: models::api::API, +} + + +impl TokenManager { + pub fn request_token(&self) -> models::token::Token { + let usr_json = self.user.to_json(); + println!("Sending request for a token"); + + let endpoint = self.construct_endpoint(); + let mut url: String = String::from(&self.api.url); + url += &endpoint; + + println!("URL: {}", url); + + return models::token::Token::default(); + } + + fn construct_endpoint(&self) -> String { + let mut endpoint: String = String::from("api/"); + endpoint += &self.api.version; + endpoint += "/login"; + + return endpoint; + } +} \ No newline at end of file -- 2.47.3 From cae266340d8a9a8fc2b10e35cb72850e2af398cc Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 14 Apr 2024 20:01:16 -0400 Subject: [PATCH 19/47] More changes. Not functional yet --- src/managers/action_managers.rs | 2 ++ src/managers/commit_manager.rs | 57 ++++++++++++++++++++++++++++++--- src/managers/mod.rs | 1 + src/managers/user_manager.rs | 29 ++++++++++------- src/models/user.rs | 8 ++++- 5 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index f875e60..780eeb6 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -39,7 +39,9 @@ impl ActionManager { } // TODO: Implement + /** fn supported_actions(&self) {} + */ pub fn initialize(&mut self) { self.validate_flags(); diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index ef26043..d3f890f 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; +use crate::managers; use crate::models; +use crate::parsers; use crate::utilities; #[derive(Debug, Deserialize, Serialize)] @@ -81,13 +83,30 @@ impl CommitManager { } } - // TODO: Implement fn map_actions(&self) -> HashMap { - return HashMap::new(); + let mut actions: HashMap = 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); + + return actions; } // TODO: Implement fn delete_song(&self) { + let mut prsr = parsers::api_parser::APIParser { + ica_act: self.ica_action.clone(), + api: models::api::API::default(), + }; + + let api = prsr.retrieve_api(); + + let song = models::song::Song::default(); + + for arg in &self.ica_action.flags { + } } // TODO: Implement @@ -102,8 +121,25 @@ impl CommitManager { fn upload_song(&self) { } - // TODO: Implement - fn parse_token(&self, api: &models::api::API) {} + fn parse_token(&self, api: &models::api::API) -> models::token::Token { + println!("Fetching token"); + + let mut usr_mgr: managers::user_manager::UserManager = managers::user_manager::UserManager { + user: models::user::User { + username: String::new(), + password: String::new(), + }, + ica_action: self.ica_action.clone(), + }; + + let usr = usr_mgr.retrieve_user(); + let tok_mgr = managers::token_manager::TokenManager { + user: usr, + api: api.clone(), + }; + + return tok_mgr.request_token(); + } // TODO: Implement fn upload_song_with_metadata(&self) {} // TODO: Implement @@ -153,7 +189,18 @@ impl CommitManager { if k != end && dot != end { let st = k + 1; let ed = dot - 1; - let t = &filename[&st..&ed]; + let mut t: String = String::new(); + let mut index = 0; + for a in filename.chars() { + if index <= ed { + t.push(a); + } else if index >= st { + t.push(a); + } + + index += 1; + } + // let t = &filename[1..5]; } }, 2 => { diff --git a/src/managers/mod.rs b/src/managers/mod.rs index 3699871..ba06c8e 100644 --- a/src/managers/mod.rs +++ b/src/managers/mod.rs @@ -1,3 +1,4 @@ pub mod action_managers; pub mod commit_manager; pub mod user_manager; +pub mod token_manager; diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index bafc7da..6e2b24e 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -2,24 +2,31 @@ use serde::{Deserialize, Serialize}; use crate::models; -// mod managers { #[derive(Debug, Deserialize, Serialize)] pub struct UserManager { - user: models::user::User, - ica_action: models::icarus_action::IcarusAction, + pub user: models::user::User, + pub ica_action: models::icarus_action::IcarusAction, } impl UserManager { - // TODO: Implement pub fn retrieve_user(&self) -> models::user::User { - return models::user::User { - username: String::from(""), - password: String::from(""), - }; + return self.user.clone(); } - // TODO: Implement - fn parse_user_from_actions(&self) {} + pub fn parse_user_from_actions(&mut self) { + let args = &self.ica_action.flags; + + for arg in args { + let flag = &arg.flag; + + if flag == "-u" { + self.user.username = String::from(&arg.value); + } + + if flag == "-p" { + self.user.password = String::from(&arg.value); + } + } + } } -// } diff --git a/src/models/user.rs b/src/models/user.rs index 54c20cf..d788787 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -2,7 +2,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct User { pub username: String, pub password: String, @@ -16,3 +16,9 @@ impl Default for User { } } } + +impl User { + pub fn to_json(&self) -> Result { + return serde_json::to_string_pretty(&self); + } +} -- 2.47.3 From b5a877e4582045fb746da8fe7995e2a857d70895 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 14 Apr 2024 20:08:49 -0400 Subject: [PATCH 20/47] Changed name of the project --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef2d8a4..e7d96e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "IcarusDownloadManager" +name = "icarus-dm" version = "0.1.0" edition = "2021" @@ -12,4 +12,4 @@ edition = "2021" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" # rodio = "0.17.3" -# metadata = "0.1.8" \ No newline at end of file +# metadata = "0.1.8" -- 2.47.3 From ea48cdc4bc19d81db5fc0a54691c1d4542835764 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 14 Apr 2024 20:10:35 -0400 Subject: [PATCH 21/47] Removed cmake workflow --- .github/workflows/cmake.yml | 50 ------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml deleted file mode 100644 index a2fcccc..0000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: hosted-ninja_multi-vcpkg_submod-triplet-cacheoff -on: [push, workflow_dispatch] - -jobs: - job: - name: ${{ matrix.os }}-${{ github.workflow }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - include: - - os: windows-latest - triplet: x64-windows - - os: ubuntu-latest - triplet: x64-linux - - os: macos-latest - triplet: x64-osx - - env: - VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }} - - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - - uses: lukka/get-cmake@latest - - name: dir - run: find $RUNNER_WORKSPACE - shell: bash - - - name: Setup vcpkg - uses: lukka/run-vcpkg@main - id: runvcpkg - with: - vcpkgJsonGlob: '**/cmakepresets/vcpkg.json' - - - name: List $RUNNER_WORKSPACE before build - run: find $RUNNER_WORKSPACE - shell: bash - - name: Prints output of run-vcpkg's action. - run: echo "root='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_ROOT_OUT }}', triplet='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_DEFAULT_TRIPLET_OUT }}' " - # - name: Build - # Build your program with the given configuration - # run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: List $RUNNER_WORKSPACE after build - run: find $RUNNER_WORKSPACE - shell: bash -- 2.47.3 From 0f6c4460f0eb3829d369f949a8f271adb5a22b04 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 14 Apr 2024 20:11:16 -0400 Subject: [PATCH 22/47] Adding rust workflow --- .github/workflows/rust.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..2bef732 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,23 @@ +name: Rust + +on: + push: + branches: [ "rust-lg" ] + pull_request: + branches: [ "rust-lg" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose + -- 2.47.3 From 33abb7b9482dc6aab2b0d2b1d998abddca099562 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 16 Apr 2024 20:34:00 -0400 Subject: [PATCH 23/47] Adding code to the syncers module --- src/syncers/delete.rs | 10 ++++++++++ src/syncers/syncer_base.rs | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index e69de29..ee576e5 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -0,0 +1,10 @@ +use crate::models; + +#[derive(Clone, Debug)] +pub struct Delete { +} + +impl Delete { + pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { + } +} \ No newline at end of file diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs index e69de29..c76f9ae 100644 --- a/src/syncers/syncer_base.rs +++ b/src/syncers/syncer_base.rs @@ -0,0 +1,19 @@ + +use crate::models; + +struct Syncer { +} + +impl Syncer { + pub fn retrieve_url(api: &models::api::API, song: &models::song::Song) -> String { + let mut url: String = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + url += &String::from("/"); + url += &song.id.unwrap().to_string(); + + return url; + } +} \ No newline at end of file -- 2.47.3 From 72e6070946ccfddd6216677fbee0f9265eb7ffa5 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 5 May 2024 15:59:55 -0400 Subject: [PATCH 24/47] Cargo formatting --- src/main.rs | 16 ++++--- src/managers/action_managers.rs | 25 +++++++++-- src/managers/commit_manager.rs | 75 +++++++++++++++++++++------------ src/managers/mod.rs | 2 +- src/managers/token_manager.rs | 3 +- src/managers/user_manager.rs | 1 - src/models/api.rs | 3 +- src/models/icarus_action.rs | 1 - src/models/song.rs | 9 ++-- src/models/token.rs | 1 - src/models/upload_form.rs | 3 +- src/parsers/api_parser.rs | 3 +- src/parsers/mod.rs | 2 +- src/syncers/delete.rs | 8 ++-- src/syncers/download.rs | 1 + src/syncers/mod.rs | 2 +- src/syncers/retrieve_records.rs | 1 + src/syncers/syncer_base.rs | 6 +-- src/syncers/upload.rs | 1 + src/utilities/checks.rs | 24 +++++++---- src/utilities/conversions.rs | 7 +-- src/utilities/mod.rs | 2 +- 22 files changed, 116 insertions(+), 80 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2260a2c..9506921 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ mod managers; mod models; -mod utilities; mod parsers; mod syncers; +mod utilities; use std::env; use std::process; @@ -17,7 +17,7 @@ fn print_help() { Actions download - upload + upload (Search NOTE) upload-meta retrieve delete @@ -58,13 +58,15 @@ fn print_help() { fn main() { let args: Vec = env::args().collect(); - if args.len() == 0 { + if args.len() == 1 { print_help(); exit_program(-1); } let args_len = args.len() as i32; + println!("Argument count: {}", args_len); + let mut act_mgr = managers::action_managers::ActionManager { action: String::from(""), flags: Vec::new(), @@ -78,10 +80,10 @@ fn main() { chosen_act.print_action_and_flags(); let cmt_mgr = managers::commit_manager::CommitManager { -// action: String::from(""), -// flags: Vec::new(), -// params: Vec::new(), -// param_count: 1, + // action: String::from(""), + // flags: Vec::new(), + // params: Vec::new(), + // param_count: 1, ica_action: chosen_act, }; diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 780eeb6..3dd8cd9 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -19,7 +19,8 @@ impl ActionManager { } fn supported_flags(&self) -> Vec { - return vec![String::from("-u"), + return vec![ + String::from("-u"), String::from("-p"), String::from("-t"), String::from("-h"), @@ -45,6 +46,7 @@ impl ActionManager { pub fn initialize(&mut self) { self.validate_flags(); + self.validate_action(); self.action = self.action.to_lowercase(); } @@ -53,16 +55,22 @@ impl ActionManager { let flag_vals = self.parsed_flags(); - for i in 0..flag_vals.len() { + let mut i = 0; + println!("Flag count: {}", flag_vals.len()); + // for mut i in 0..flag_vals.len() { + while i < flag_vals.len() { let flag = &flag_vals[i]; - println!("Value: {}", flag); + println!("Index: {} | Value: {}", i, flag); let mut flg = models::flags::Flags::default(); if self.is_valid_flag(flag) && self.does_flag_have_value(flag) { println!("Flag has value"); flg.flag = String::from(flag); - flg.value = String::from(&flag_vals[i+1]); + flg.value = String::from(&flag_vals[i + 1]); + // println!("Before change {}", i); + i = i + 1; + // println!("After change {}", i); } else if self.is_valid_flag(flag) { println!("Flag does not have a value"); flg.flag = String::from(flag); @@ -72,6 +80,15 @@ impl ActionManager { } self.flags.push(flg); + println!(""); + i += 1; + } + } + + fn validate_action(&self) { + if self.params.len() >= 2 { + let act = &self.params[1]; + println!("The action {}", act); } } diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index d3f890f..6ba3170 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,5 +1,5 @@ -use std::default::Default; use std::collections::HashMap; +use std::default::Default; use serde::{Deserialize, Serialize}; @@ -17,7 +17,6 @@ pub struct CommitManager { pub ica_action: models::icarus_action::IcarusAction, } - pub struct Album { pub title: String, pub album_artist: String, @@ -35,19 +34,21 @@ impl Default for Album { album_artist: String::new(), genre: String::new(), year: 0, - track_count: 0, + track_count: 0, disc_count: 0, songs: Vec::new(), } } } +#[derive(Clone, Debug)] enum ActionValues { DeleteAct, DownloadAct, RetrieveAct, UploadAct, UploadSongWithMetadata, + None, } enum RetrieveTypes { @@ -66,28 +67,38 @@ impl Album { } impl CommitManager { - pub fn commit_action(&self) { let action = &self.ica_action.action; println!("Committing {} action", action); - match self.map_actions()[action] { - ActionValues::DeleteAct => self.delete_song(), - ActionValues::DownloadAct => self.download_song(), - ActionValues::RetrieveAct => self.retrieve_object(), - ActionValues::UploadAct => self.upload_song(), - ActionValues::UploadSongWithMetadata => self.upload_song_with_metadata(), - _ => { - println!("Nothing good here"); + let mapped_actions = self.map_actions(); + let mapped_action = self.find_mapped_action(&mapped_actions, action); + + println!("{:?}", mapped_action); + } + + fn find_mapped_action( + &self, + actions: &HashMap, + action: &String, + ) -> ActionValues { + for (key, act) in actions { + if key == action { + return act.clone(); } } + + return ActionValues::None; } fn map_actions(&self) -> HashMap { let mut actions: HashMap = 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("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); @@ -101,36 +112,42 @@ impl CommitManager { api: models::api::API::default(), }; + println!("Deleting song"); + let api = prsr.retrieve_api(); let song = models::song::Song::default(); - for arg in &self.ica_action.flags { - } + for arg in &self.ica_action.flags {} } // TODO: Implement fn download_song(&self) { + println!("Deleting song"); } // TODO: Implement fn retrieve_object(&self) { + println!("Deleting song"); } // TODO: Implement + // NOTE: Might not need to implement. I will see how this goes fn upload_song(&self) { + println!("Deleting song"); } fn parse_token(&self, api: &models::api::API) -> models::token::Token { println!("Fetching token"); - let mut usr_mgr: managers::user_manager::UserManager = managers::user_manager::UserManager { - user: models::user::User { - username: String::new(), - password: String::new(), - }, - ica_action: self.ica_action.clone(), - }; + let mut usr_mgr: managers::user_manager::UserManager = + managers::user_manager::UserManager { + user: models::user::User { + username: String::new(), + password: String::new(), + }, + ica_action: self.ica_action.clone(), + }; let usr = usr_mgr.retrieve_user(); let tok_mgr = managers::token_manager::TokenManager { @@ -141,7 +158,9 @@ impl CommitManager { return tok_mgr.request_token(); } // TODO: Implement - fn upload_song_with_metadata(&self) {} + fn upload_song_with_metadata(&self) { + println!("Deleting song"); + } // TODO: Implement fn sing_target_upload( &self, @@ -162,7 +181,8 @@ impl CommitManager { let track = 1; let mut mode = 0; let songpath = song.song_path(); - let filename = & as Clone>::clone(&song.filepath).unwrap(); + let filename = + & as Clone>::clone(&song.filepath).unwrap(); // let directory = & as Clone>::clone(&self.directory).unwrap(); let trd = filename.contains("trackd"); @@ -202,9 +222,8 @@ impl CommitManager { } // let t = &filename[1..5]; } - }, - 2 => { - }, + } + 2 => {} _ => println!(""), } diff --git a/src/managers/mod.rs b/src/managers/mod.rs index ba06c8e..dbe307c 100644 --- a/src/managers/mod.rs +++ b/src/managers/mod.rs @@ -1,4 +1,4 @@ pub mod action_managers; pub mod commit_manager; -pub mod user_manager; pub mod token_manager; +pub mod user_manager; diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index 20313da..fec2a73 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -7,7 +7,6 @@ pub struct TokenManager { pub api: models::api::API, } - impl TokenManager { pub fn request_token(&self) -> models::token::Token { let usr_json = self.user.to_json(); @@ -29,4 +28,4 @@ impl TokenManager { return endpoint; } -} \ No newline at end of file +} diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index 6e2b24e..1479916 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -2,7 +2,6 @@ use serde::{Deserialize, Serialize}; use crate::models; - #[derive(Debug, Deserialize, Serialize)] pub struct UserManager { pub user: models::user::User, diff --git a/src/models/api.rs b/src/models/api.rs index 774ffcd..d8665f1 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -2,7 +2,6 @@ use std::default::Default; use serde::{Deserialize, Serialize}; - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct API { pub url: String, @@ -18,4 +17,4 @@ impl Default for API { version: String::from(""), } } -} \ No newline at end of file +} diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index 1d2d3d6..e0e39cf 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize}; use crate::models; - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IcarusAction { pub action: String, diff --git a/src/models/song.rs b/src/models/song.rs index 2f7b0d3..7060a27 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -2,7 +2,6 @@ use std::default::Default; use serde::{Deserialize, Serialize}; - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { pub id: Option, @@ -46,16 +45,18 @@ impl Song { } pub fn song_path(&self) -> String { - let directory = & as Clone>::clone(&self.directory).unwrap(); + let directory = + & as Clone>::clone(&self.directory).unwrap(); let mut buffer: String = directory.to_string(); let count = buffer.len(); - if buffer.chars().nth(count-1) != Some('/') { + if buffer.chars().nth(count - 1) != Some('/') { buffer += "/"; } - let filename = & as Clone>::clone(&self.filepath).unwrap(); + let filename = + & as Clone>::clone(&self.filepath).unwrap(); buffer += filename; return buffer; diff --git a/src/models/token.rs b/src/models/token.rs index 73a3bb2..cd57a8d 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -2,7 +2,6 @@ use std::default::Default; use serde::{Deserialize, Serialize}; - #[derive(Debug, Deserialize, Serialize)] pub struct Token { pub access_token: Option, diff --git a/src/models/upload_form.rs b/src/models/upload_form.rs index 903d5b4..ef90173 100644 --- a/src/models/upload_form.rs +++ b/src/models/upload_form.rs @@ -2,7 +2,6 @@ use std::default::Default; use serde::{Deserialize, Serialize}; - #[derive(Debug, Deserialize, Serialize)] pub struct UploadForm { pub url: Option, @@ -16,4 +15,4 @@ impl Default for UploadForm { filepath: None, } } -} \ No newline at end of file +} diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs index 8c8a684..790c3b7 100644 --- a/src/parsers/api_parser.rs +++ b/src/parsers/api_parser.rs @@ -1,4 +1,3 @@ - use crate::models; #[derive(Clone, Debug)] @@ -36,4 +35,4 @@ impl APIParser { self.api.version = "v1".to_string(); } -} \ No newline at end of file +} diff --git a/src/parsers/mod.rs b/src/parsers/mod.rs index c5b5ef6..35820cf 100644 --- a/src/parsers/mod.rs +++ b/src/parsers/mod.rs @@ -1 +1 @@ -pub mod api_parser; \ No newline at end of file +pub mod api_parser; diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index ee576e5..58b8c5a 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -1,10 +1,8 @@ use crate::models; #[derive(Clone, Debug)] -pub struct Delete { -} +pub struct Delete {} impl Delete { - pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { - } -} \ No newline at end of file + pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) {} +} diff --git a/src/syncers/download.rs b/src/syncers/download.rs index e69de29..8b13789 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -0,0 +1 @@ + diff --git a/src/syncers/mod.rs b/src/syncers/mod.rs index 5eddbb6..29f57f6 100644 --- a/src/syncers/mod.rs +++ b/src/syncers/mod.rs @@ -2,4 +2,4 @@ pub mod delete; pub mod download; pub mod retrieve_records; pub mod syncer_base; -pub mod upload; \ No newline at end of file +pub mod upload; diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index e69de29..8b13789 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -0,0 +1 @@ + diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs index c76f9ae..dd9fff9 100644 --- a/src/syncers/syncer_base.rs +++ b/src/syncers/syncer_base.rs @@ -1,8 +1,6 @@ - use crate::models; -struct Syncer { -} +struct Syncer {} impl Syncer { pub fn retrieve_url(api: &models::api::API, song: &models::song::Song) -> String { @@ -16,4 +14,4 @@ impl Syncer { return url; } -} \ No newline at end of file +} diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index e69de29..8b13789 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -0,0 +1 @@ + diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index adcbc0c..6778365 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -1,8 +1,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize)] -pub struct Checks { -} +pub struct Checks {} impl Checks { pub fn is_numeric(text: &String) -> bool { @@ -10,20 +9,29 @@ impl Checks { } // TODO: Implement - pub fn item_in_container(container: &Vec, item: &String, - func: fn(a: &String, b: &String) -> String) -> String { + pub fn item_in_container( + container: &Vec, + item: &String, + func: fn(a: &String, b: &String) -> String, + ) -> String { return String::from(""); } // TODO: Implement - pub fn item_iter_in_container(container: &Vec, item: &String, - func: fn(a: &String, b: &String) -> String) -> String { + pub fn item_iter_in_container( + container: &Vec, + item: &String, + func: fn(a: &String, b: &String) -> String, + ) -> String { return String::from(""); } // TODO: Implement - pub fn index_of_item_in_container(container: &String, item: &char, - func: fn(a: &char, b: &char) -> bool) -> i32 { + pub fn index_of_item_in_container( + container: &String, + item: &char, + func: fn(a: &char, b: &char) -> bool, + ) -> i32 { let mut index = -1; for c in container.chars() { diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index c0bf7fd..53493d1 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -1,9 +1,7 @@ use serde::{Deserialize, Serialize}; - #[derive(Debug, Deserialize, Serialize)] -pub struct Conversions { -} +pub struct Conversions {} impl Conversions { pub fn to_lower_char(val: &mut char) { @@ -12,8 +10,7 @@ impl Conversions { } } - pub fn initialize_values(&self) { - } + pub fn initialize_values(&self) {} pub fn print_value(&self, val: T) { println!("Going to print value"); diff --git a/src/utilities/mod.rs b/src/utilities/mod.rs index e7eb3d8..f2a82e4 100644 --- a/src/utilities/mod.rs +++ b/src/utilities/mod.rs @@ -1,2 +1,2 @@ pub mod checks; -pub mod conversions; \ No newline at end of file +pub mod conversions; -- 2.47.3 From fdd25d9c8f782764067fa2649f6c61f68c5ebd26 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 5 May 2024 18:47:47 -0400 Subject: [PATCH 25/47] Continuing work --- src/main.rs | 4 - src/managers/action_managers.rs | 13 +-- src/managers/commit_manager.rs | 192 ++++++++++++++++++++++++++++---- src/syncers/delete.rs | 4 +- src/utilities/checks.rs | 8 +- 5 files changed, 180 insertions(+), 41 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9506921..080b2f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,10 +80,6 @@ fn main() { chosen_act.print_action_and_flags(); let cmt_mgr = managers::commit_manager::CommitManager { - // action: String::from(""), - // flags: Vec::new(), - // params: Vec::new(), - // param_count: 1, ica_action: chosen_act, }; diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 3dd8cd9..e1d666b 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -39,10 +39,6 @@ impl ActionManager { ]; } - // TODO: Implement - /** - fn supported_actions(&self) {} - */ pub fn initialize(&mut self) { self.validate_flags(); @@ -57,7 +53,7 @@ impl ActionManager { let mut i = 0; println!("Flag count: {}", flag_vals.len()); - // for mut i in 0..flag_vals.len() { + while i < flag_vals.len() { let flag = &flag_vals[i]; println!("Index: {} | Value: {}", i, flag); @@ -68,9 +64,8 @@ impl ActionManager { println!("Flag has value"); flg.flag = String::from(flag); flg.value = String::from(&flag_vals[i + 1]); - // println!("Before change {}", i); + i = i + 1; - // println!("After change {}", i); } else if self.is_valid_flag(flag) { println!("Flag does not have a value"); flg.flag = String::from(flag); @@ -85,10 +80,10 @@ impl ActionManager { } } - fn validate_action(&self) { + fn validate_action(&mut self) { if self.params.len() >= 2 { let act = &self.params[1]; - println!("The action {}", act); + self.action = String::from(act); } } diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 6ba3170..5c7023d 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,22 +1,22 @@ use std::collections::HashMap; use std::default::Default; +use std::fs::File; +use std::io::{Read, Error}; use serde::{Deserialize, Serialize}; -use crate::managers; +use crate::{exit_program, managers}; use crate::models; use crate::parsers; +use crate::syncers; use crate::utilities; #[derive(Debug, Deserialize, Serialize)] pub struct CommitManager { - // pub action: String, - // pub flags: Vec, - // pub params: Vec, - // pub param_count: i32, pub ica_action: models::icarus_action::IcarusAction, } +#[derive(Debug, Deserialize, Serialize)] pub struct Album { pub title: String, pub album_artist: String, @@ -62,7 +62,7 @@ impl Album { println!("Genre: {}", self.genre); println!("Year: {}", self.year); println!("Track Count: {}", self.track_count); - println!("Disc Count: {}", self.disc_count); + println!("Disc Count: {}\n", self.disc_count); } } @@ -75,6 +75,17 @@ impl CommitManager { let mapped_action = self.find_mapped_action(&mapped_actions, action); println!("{:?}", mapped_action); + + match mapped_action { + ActionValues::DeleteAct => self.delete_song(), + ActionValues::DownloadAct => self.download_song(), + ActionValues::RetrieveAct => self.retrieve_object(), + ActionValues::UploadAct => self.upload_song(), + ActionValues::UploadSongWithMetadata => self.upload_song_with_metadata(), + _ => { + println!("Nothing good here"); + }, + } } fn find_mapped_action( @@ -94,7 +105,7 @@ impl CommitManager { fn map_actions(&self) -> HashMap { let mut actions: HashMap = HashMap::new(); actions.insert("download".to_string(), ActionValues::DownloadAct); - // actions.insert("upload".to_string(), ActionValues::UploadAct); + actions.insert("upload".to_string(), ActionValues::UploadAct); actions.insert( "upload-meta".to_string(), ActionValues::UploadSongWithMetadata, @@ -111,14 +122,31 @@ impl CommitManager { ica_act: self.ica_action.clone(), api: models::api::API::default(), }; + prsr.parse_api(); + let api = prsr.retrieve_api(); + + let token = self.parse_token(&api); println!("Deleting song"); - let api = prsr.retrieve_api(); + let mut song = models::song::Song::default(); - let song = models::song::Song::default(); + for arg in &self.ica_action.flags { + let flag = &arg.flag; + let value = &arg.value; - for arg in &self.ica_action.flags {} + if flag == "-D" { + song.id = Some(value.parse::().unwrap()); + } + } + + let del = syncers::delete::Delete { + api: api, + }; + + println!("Deleting song.."); + + del.delete_song(&token, &song); } // TODO: Implement @@ -148,6 +176,7 @@ impl CommitManager { }, ica_action: self.ica_action.clone(), }; + usr_mgr.parse_user_from_actions(); let usr = usr_mgr.retrieve_user(); let tok_mgr = managers::token_manager::TokenManager { @@ -171,14 +200,31 @@ impl CommitManager { ) { } // TODO: Implement - fn multi_target_upload(&self, sourcepath: &String) {} - // TODO: Implement + fn multi_target_upload(&self, sourcepath: &String) { + let mut prsr = parsers::api_parser::APIParser { + api: models::api::API::default(), + ica_act: self.ica_action.clone(), + }; + prsr.parse_api(); + let api = prsr.retrieve_api(); + let token = self.parse_token(&api); + + let directory_path = std::path::Path::new(&sourcepath); + + if !directory_path.exists() { + println!("Directory does not exist"); + std::process::exit(-1); + } + + // let mut cover_art = models:: + } + // 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) { - let disc = 1; - let track = 1; + let mut disc = 1; + let mut track = 1; let mut mode = 0; let songpath = song.song_path(); let filename = @@ -220,25 +266,102 @@ impl CommitManager { index += 1; } - // let t = &filename[1..5]; + + if utilities::checks::Checks::is_numeric(&t) { + track = t.parse::().unwrap(); + } + disc = 1 + } + } + 2 => { + if k != end && dot != end && d != end { + let st = k + 1; + let ed = dot - 1; + let mut t: String = String::new(); + let mut index = 0; + for a in filename.chars() { + if index <= ed { + t.push(a); + } else if index >= st { + t.push(a); + } + + index += 1; + } + + if utilities::checks::Checks::is_numeric(&t) { + track = t.parse::().unwrap(); + } + + let sst = d + 1; + let eed = dot; + let mut d_s = String::new(); + index = 0; + for a in filename.chars() { + if index <= eed { + d_s.push(a); + } else if index >= sst { + d_s.push(a); + } + + index += 1; + } + + if utilities::checks::Checks::is_numeric(&d_s) { + track = d_s.parse::().unwrap(); + } } } - 2 => {} _ => println!(""), } song.disc = Some(disc); song.track = Some(track); } - // TODO: Implement - fn parse_disc_and_track(&self, song: &models::song::Song, track_id: &String) {} - // TODO: Implement + + fn parse_disc_and_track(&self, song: &mut models::song::Song, track_id: &String) { + let sep = |a: &char, b: &char| -> bool { + return false; + }; + + let index = utilities::checks::Checks::index_of_item_in_container(track_id, &':', sep); + + if index == -1 { + let mut d_str: String = String::new(); + let mut t_str = String::new(); + + for c in track_id.chars().skip(0).take(index as usize) { + d_str.push(c); + } + + let start = index + 1; + let end = track_id.len() - 1; + + for c in track_id.chars().skip(start as usize).take(end as usize) { + d_str.push(c); + } + + song.disc = Some(d_str.parse::().unwrap()); + song.track = Some(t_str.parse::().unwrap()); + } else { + if utilities::checks::Checks::is_numeric(track_id) { + song.track = Some(track_id.parse::().unwrap()); + } + } + } + fn check_for_no_confirm(&self) -> bool { + for flag in self.ica_action.flags.iter() { + if flag.flag == "-nc" { + return true; + } + } return false; } - // TODO: Implement + fn retrieve_metadata(&self, path: &String) -> Album { - return Album { + /* + let mut alb = Album { title: String::from(""), album_artist: String::from(""), genre: String::from(""), @@ -247,9 +370,30 @@ impl CommitManager { disc_count: 0, songs: Vec::new(), }; + */ + + let content = self.retrieve_file_content(&path); + // let alb = serde_json::from_str(&content.unwrap()); + + /* + let mut file: std::fs::File = std::fs::File::open(filepath).unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + + return serde_json::from_str(&data).unwrap(); + */ + + // return alb.unwrap(); + return serde_json::from_str(&content.unwrap()).unwrap(); } - // TODO: Implement - fn retrieve_file_content(&self, path: &String) -> String { - return String::from(""); + + fn retrieve_file_content(&self, path: &String) -> Result { + /* + let mut file = File::open(path)?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; + */ + + return std::fs::read_to_string(path); } } diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index 58b8c5a..21617ff 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -1,7 +1,9 @@ use crate::models; #[derive(Clone, Debug)] -pub struct Delete {} +pub struct Delete { + pub api: models::api::API, +} impl Delete { pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) {} diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 6778365..1badc23 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -27,11 +27,13 @@ impl Checks { } // TODO: Implement - pub fn index_of_item_in_container( + pub fn index_of_item_in_container( container: &String, item: &char, - func: fn(a: &char, b: &char) -> bool, - ) -> i32 { + func: F, + ) -> i32 + where F: Fn(&char, &char) -> bool, + { let mut index = -1; for c in container.chars() { -- 2.47.3 From 115e8b15271330db7114add4b428c714abb792e2 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 6 May 2024 20:43:04 -0400 Subject: [PATCH 26/47] Adding code to the syncers module --- src/syncers/delete.rs | 18 ++++++++++++++++-- src/syncers/download.rs | 14 ++++++++++++++ src/syncers/retrieve_records.rs | 16 ++++++++++++++++ src/syncers/syncer_base.rs | 26 +++++++++++++++++++++++++- src/syncers/upload.rs | 14 ++++++++++++++ 5 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index 21617ff..c97204b 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -1,10 +1,24 @@ +use std::default::Default; + use crate::models; +use super::syncer_base; + #[derive(Clone, Debug)] pub struct Delete { pub api: models::api::API, } -impl Delete { - pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) {} +impl Default for Delete { + fn default() -> Self { + Delete { + api: models::api::API::default(), + } + } +} + +impl Delete { + pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { + let url = syncer_base::Syncer::retrieve_url(&self.api, &song); + } } diff --git a/src/syncers/download.rs b/src/syncers/download.rs index 8b13789..2607afa 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -1 +1,15 @@ +use std::default::Default; +use crate::models; + +pub struct Download{ + pub api: models::api::API, +} + +impl Default for Download { + fn default() -> Self { + Download { + api: models::api::API::default(), + } + } +} \ No newline at end of file diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index 8b13789..b6039b1 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -1 +1,17 @@ +use std::default::Default; +use crate::models; + + +pub struct RetrieveRecords { + pub api: models::api::API, +} + + +impl Default for RetrieveRecords { + fn default() -> Self { + RetrieveRecords { + api: models::api::API::default(), + } + } +} \ No newline at end of file diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs index dd9fff9..7cbc353 100644 --- a/src/syncers/syncer_base.rs +++ b/src/syncers/syncer_base.rs @@ -1,6 +1,10 @@ use crate::models; -struct Syncer {} +pub struct Syncer { + ok: i32, + unauthorized: i32, + not_found: i32, +} impl Syncer { pub fn retrieve_url(api: &models::api::API, song: &models::song::Song) -> String { @@ -14,4 +18,24 @@ impl Syncer { return url; } + + pub fn ok() -> i32 { + return 200; + } + + pub fn unauthorized() -> i32 { + return 401; + } + + pub fn not_found() -> i32 { + return 404; + } } + +pub enum Result { + OK, + UNAUTHORIZED, + NOTFOUND, +} + + diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 8b13789..809cc81 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1 +1,15 @@ +use std::default::Default; +use crate::models; + +pub struct Upload { + pub api: models::api::API, +} + +impl Default for Upload { + fn default() -> Self { + Upload { + api: models::api::API::default(), + } + } +} \ No newline at end of file -- 2.47.3 From bf2d760aa489b324725d711f1bfa8804d8953e9a Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 12 May 2024 16:05:45 -0400 Subject: [PATCH 27/47] Added dependencies --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e7d96e9..75ab991 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +futures = { version = "0.3.30" } +reqwest = { version = "0.12.4", features = ["json", "blocking"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" +tokio = { version = "1.37", features = ["full"] } # rodio = "0.17.3" # metadata = "0.1.8" -- 2.47.3 From aab17f6f3ccb32334fc990be899cc26a0b7ee40e Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 12 May 2024 16:06:10 -0400 Subject: [PATCH 28/47] Adding more code to the syncers module --- src/models/token.rs | 16 +++++++++++ src/syncers/delete.rs | 40 +++++++++++++++++++++++++-- src/syncers/download.rs | 11 ++++++++ src/syncers/retrieve_records.rs | 49 +++++++++++++++++++++++++++++++++ src/syncers/syncer_base.rs | 15 ++-------- src/syncers/upload.rs | 32 +++++++++++++++++++++ 6 files changed, 148 insertions(+), 15 deletions(-) diff --git a/src/models/token.rs b/src/models/token.rs index cd57a8d..25bf3d2 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -18,3 +18,19 @@ impl Default for Token { } } } + +impl Token { + pub fn bearer_token(&self) -> String { + let mut token: String = String::from("Bearer "); + + match &self.access_token { + Some(tok) => { + token += tok; + } + None => { + } + } + + return token; + } +} diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index c97204b..f07a910 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -1,4 +1,11 @@ use std::default::Default; +use std::io::Error; + +use reqwest; +use reqwest::Response; +use serde; +// use serde::Deserialize; +// use serde::Serialize; use crate::models; @@ -18,7 +25,36 @@ impl Default for Delete { } impl Delete { - pub fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { - let url = syncer_base::Syncer::retrieve_url(&self.api, &song); + pub async fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { + let url = self.retrieve_url(&song); + let client = reqwest::Client::new(); + let access_token = token.bearer_token(); + let response = client.delete(&url) + .header(reqwest::header::AUTHORIZATION, access_token) + .send() + .await + .unwrap(); + + match response.status() { + reqwest::StatusCode::OK => { + println!("Success!"); + } + other => { + panic!("Issue occurred: {:?}", other); + } + } + } + + fn retrieve_url(&self, song: &models::song::Song) -> String { + let api = &self.api; + let mut url: String = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + url += &String::from("/"); + url += &song.id.unwrap().to_string(); + + return url; } } diff --git a/src/syncers/download.rs b/src/syncers/download.rs index 2607afa..5abeba3 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -12,4 +12,15 @@ impl Default for Download { api: models::api::API::default(), } } +} + +impl Download { + pub async fn download_song(&self, token: &models::token::Token) { + } + + fn retrieve_url(&self) -> String { + let mut url: String = String::new(); + + return url; + } } \ No newline at end of file diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index b6039b1..538f151 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -1,7 +1,10 @@ use std::default::Default; +use std::io::Error; use crate::models; +// use super::syncer_base::Result; + pub struct RetrieveRecords { pub api: models::api::API, @@ -14,4 +17,50 @@ impl Default for RetrieveRecords { api: models::api::API::default(), } } +} + + +impl RetrieveRecords { + pub async fn get_all_songs(&self, token: &models::token::Token) + -> Result, Error> { + + let mut songs: Vec = Vec::new(); + let url = self.retrieve_url(); + let access_token = token.bearer_token(); + let client = reqwest::Client::new(); + let response = client.get(&url) + .header(reqwest::header::AUTHORIZATION, access_token) + .send() + .await + .unwrap(); + + + match response.status() { + reqwest::StatusCode::OK => { + // on success, parse our JSON to an APIResponse + let s = response.json::>().await; + match s { + // + Ok(parsed) => { + songs = parsed; + }, + Err(_) => println!("Hm, the response didn't match the shape we expected."), + }; + } + reqwest::StatusCode::UNAUTHORIZED => { + println!("Need to grab a new token"); + } + other => { + panic!("Uh oh! Something unexpected happened: {:?}", other); + } + } + + return Ok(songs); + } + + fn retrieve_url(&self) -> String { + let mut url: String = String::new(); + + return url; + } } \ No newline at end of file diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs index 7cbc353..e816945 100644 --- a/src/syncers/syncer_base.rs +++ b/src/syncers/syncer_base.rs @@ -1,24 +1,13 @@ -use crate::models; +// use crate::models; pub struct Syncer { + // pub api: models::api::API, ok: i32, unauthorized: i32, not_found: i32, } impl Syncer { - pub fn retrieve_url(api: &models::api::API, song: &models::song::Song) -> String { - let mut url: String = String::from(&api.url); - url += &String::from("api/"); - url += &String::from(&api.version); - url += &String::from("/"); - url += &String::from(&api.endpoint); - url += &String::from("/"); - url += &song.id.unwrap().to_string(); - - return url; - } - pub fn ok() -> i32 { return 200; } diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 809cc81..b463bc2 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1,5 +1,8 @@ use std::default::Default; +use reqwest; +use reqwest::Response; + use crate::models; pub struct Upload { @@ -12,4 +15,33 @@ impl Default for Upload { api: models::api::API::default(), } } +} + +impl Upload { + pub async fn upload_song(&self, token: &models::token::Token, song: &models::song::Song) { + let url = self.retrieve_url(&song); + let client = reqwest::Client::new(); + let access_token = token.bearer_token(); + let response = client.post(&url) + .header(reqwest::header::AUTHORIZATION, access_token) + .send() + .await + .unwrap(); + + match response.status() { + reqwest::StatusCode::OK => { + println!("Success!"); + } + other => { + panic!("Issue occurred: {:?}", other); + } + } + } + + + fn retrieve_url(&self, song: &models::song::Song) -> String { + let mut url: String = String::new(); + + return url; + } } \ No newline at end of file -- 2.47.3 From de9602f1a06a50e4aac1c29cb8b5c86417f05008 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 12 May 2024 16:47:31 -0400 Subject: [PATCH 29/47] Added more code to the syncers module It's not 100 percent done yet, I'll work on other modules --- src/syncers/download.rs | 43 ++++++++++++++++++++++++++++++--- src/syncers/retrieve_records.rs | 10 +++++++- src/syncers/upload.rs | 10 +++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/syncers/download.rs b/src/syncers/download.rs index 5abeba3..052c8ec 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -15,11 +15,48 @@ impl Default for Download { } impl Download { - pub async fn download_song(&self, token: &models::token::Token) { + pub async fn download_song(&self, token: &models::token::Token, song: &models::song::Song) { + let url = self.retrieve_url(&song); + let access_token = token.bearer_token(); + let client = reqwest::Client::new(); + let response = client.get(&url) + .header(reqwest::header::AUTHORIZATION, &access_token) + .send() + .await + .unwrap(); + + match response.status() { + reqwest::StatusCode::OK => { + // on success, parse our JSON to an APIResponse + /* + let s = response.json::>().await; + match s { + Ok(parsed) => { + println!("\nSuccess!"); + } + Err(_) => println!("Hm, the response didn't match the shape we expected."), + }; + */ + } + reqwest::StatusCode::UNAUTHORIZED => { + println!("Need to grab a new token"); + } + other => { + panic!("Uh oh! Something unexpected happened: {:?}", other); + } + } } - fn retrieve_url(&self) -> String { - let mut url: String = String::new(); + fn retrieve_url(&self, song: &models::song::Song) -> String { + // let mut url: String = String::new(); + let api = &self.api; + let mut url: String = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + url += &String::from("/"); + url += &song.id.unwrap().to_string(); return url; } diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index 538f151..c67dbfb 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -59,7 +59,15 @@ impl RetrieveRecords { } fn retrieve_url(&self) -> String { - let mut url: String = String::new(); + // let mut url: String = String::new(); + let api = &self.api; + let mut url: String = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + url += &String::from("/"); + // url += &song.id.unwrap().to_string(); return url; } diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index b463bc2..cc1c7e9 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -40,7 +40,15 @@ impl Upload { fn retrieve_url(&self, song: &models::song::Song) -> String { - let mut url: String = String::new(); + // let mut url: String = String::new(); + let api = &self.api; + let mut url: String = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + // url += &String::from("/"); + // url += &song.id.unwrap().to_string(); return url; } -- 2.47.3 From 7c84ce9a357779eda445855245c7681787163cd2 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 12 May 2024 17:36:00 -0400 Subject: [PATCH 30/47] Added more code to the managers module --- src/managers/commit_manager.rs | 7 +++- src/managers/token_manager.rs | 70 +++++++++++++++++++++++++++++++--- src/managers/user_manager.rs | 13 ++++++- 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 5c7023d..0d8e360 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use std::default::Default; use std::fs::File; use std::io::{Read, Error}; +use tokio::runtime::Runtime; +use futures::{FutureExt, TryFutureExt}; use serde::{Deserialize, Serialize}; use crate::{exit_program, managers}; @@ -184,7 +186,10 @@ impl CommitManager { api: api.clone(), }; - return tok_mgr.request_token(); + // let token = tok_mgr.request_token(); + let token = Runtime::new().unwrap().block_on(tok_mgr.request_token()); + + return token.unwrap(); } // TODO: Implement fn upload_song_with_metadata(&self) { diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index fec2a73..ac2f66f 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -7,18 +7,78 @@ pub struct TokenManager { pub api: models::api::API, } +impl Default for TokenManager { + fn default() -> Self { + let mut token = TokenManager { + user: models::user::User::default(), + api: models::api::API::default(), + }; + + token.init(); + + return token; + } +} + impl TokenManager { - pub fn request_token(&self) -> models::token::Token { - let usr_json = self.user.to_json(); + pub async fn request_token(&self) -> Result { println!("Sending request for a token"); let endpoint = self.construct_endpoint(); - let mut url: String = String::from(&self.api.url); - url += &endpoint; + let mut url = self.retrieve_url(); + // url += &endpoint; println!("URL: {}", url); - return models::token::Token::default(); + let mut token = models::token::Token::default(); + + + let client = reqwest::Client::new(); + let response = client.post(&url) + .json(&self.user) + .send() + .await + .unwrap(); + + match response.status() { + reqwest::StatusCode::OK => { + // on success, parse our JSON to an APIResponse + let s = response.json::().await; + match s { + // + Ok(parsed) => { + token = parsed; + }, + Err(_) => println!("Hm, the response didn't match the shape we expected."), + }; + } + reqwest::StatusCode::UNAUTHORIZED => { + println!("Need to grab a new token"); + } + other => { + panic!("Uh oh! Something unexpected happened: {:?}", other); + } + } + + return Ok(token); + } + + pub fn init(&mut self) { + let mut api = &mut self.api; + api.endpoint = String::from("api/v1/login"); + api.version = String::from("v1"); + } + + pub fn retrieve_url(&self) -> String { + let api = &self.api; + let mut url = String::from(&api.url); + url += &String::from("api/"); + url += &String::from(&api.version); + url += &String::from("/"); + url += &String::from(&api.endpoint); + url += &String::from("/"); + + return url; } fn construct_endpoint(&self) -> String { diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index 1479916..44ff366 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -1,6 +1,8 @@ +use std::default::Default; + use serde::{Deserialize, Serialize}; -use crate::models; +use crate::models::{self, user::User}; #[derive(Debug, Deserialize, Serialize)] pub struct UserManager { @@ -8,6 +10,15 @@ pub struct UserManager { pub ica_action: models::icarus_action::IcarusAction, } +impl Default for UserManager { + fn default() -> Self { + UserManager { + user: models::user::User::default(), + ica_action: models::icarus_action::IcarusAction::default(), + } + } +} + impl UserManager { pub fn retrieve_user(&self) -> models::user::User { return self.user.clone(); -- 2.47.3 From a3c0565863fd2180e3504a26de351209b1e0b0c7 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 26 May 2024 20:35:15 -0400 Subject: [PATCH 31/47] Added code to request a token --- src/managers/commit_manager.rs | 43 +++++++++++++++++++++++-- src/managers/file_manager.rs | 59 ++++++++++++++++++++++++++++++++++ src/managers/token_manager.rs | 12 +++---- src/models/icarus_action.rs | 2 +- src/models/token.rs | 12 +++++++ 5 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 src/managers/file_manager.rs diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 0d8e360..e4da341 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -181,10 +181,11 @@ impl CommitManager { usr_mgr.parse_user_from_actions(); let usr = usr_mgr.retrieve_user(); - let tok_mgr = managers::token_manager::TokenManager { + let mut tok_mgr = managers::token_manager::TokenManager { user: usr, api: api.clone(), }; + tok_mgr.init(); // let token = tok_mgr.request_token(); let token = Runtime::new().unwrap().block_on(tok_mgr.request_token()); @@ -193,8 +194,40 @@ impl CommitManager { } // TODO: Implement fn upload_song_with_metadata(&self) { - println!("Deleting song"); + println!("Uplodaring song with metadara"); + + let songpath = self.ica_action.retrieve_flag_value(&String::from("-s")); + let metadata_path = self.ica_action.retrieve_flag_value(&String::from("-m")); + let coverpath = self.ica_action.retrieve_flag_value(&String::from("-ca")); + let track_id = self.ica_action.retrieve_flag_value(&String::from("-t")); + + let single_target = songpath.len() > 0 && metadata_path.len() > 0 && coverpath.len() > 0 && + track_id.len() > 0; + // !songPath.empty() && !metadataPath.empty() && + // !coverPath.empty() && !trackID.empty() ? true : false; + + let uni = self.ica_action.retrieve_flag_value(&String::from("-smca")); + let multitarget = uni.len() > 0; + + if single_target && multitarget { + println!("Cannot upload from source and directory"); + } + + + if single_target { + println!("Song path: {}", songpath); + println!("Track ID: {}", track_id); + println!("metadata path: {}", coverpath); + println!("cover art path: {}", track_id); + + self.sing_target_upload(&songpath, &track_id, &metadata_path, &coverpath); + } else if multitarget { + self.multi_target_upload(&uni); + } else { + println!("Single or Multi target has not been chosen"); + } } + // TODO: Implement fn sing_target_upload( &self, @@ -221,7 +254,11 @@ impl CommitManager { std::process::exit(-1); } - // let mut cover_art = models:: + let mut cover_art = models::song::CoverArt::default(); + let mut songs: Vec = Vec::new(); + let mut metadatapath: String = String::new(); + + // iterate files in metadatapath } // Standards diff --git a/src/managers/file_manager.rs b/src/managers/file_manager.rs new file mode 100644 index 0000000..4f28b46 --- /dev/null +++ b/src/managers/file_manager.rs @@ -0,0 +1,59 @@ +use std::default::Default; + + +pub struct FileManager { + pub filepath: String, + pub filebuffer: String, + pub file_read: bool, + pub file_buffer_length: i32, +} + +impl Default for FileManager { + fn default() -> Self { + FileManager { + filepath: String::new(), + filebuffer: String::new(), + file_read: false, + file_buffer_length: -1 + } + } +} + + +impl FileManager { +// TODO: Implement +pub fn init(&mut self) { + self.read_file() +} + pub fn save_file(&mut self, filepath: &String) { + if !self.file_read { + self.read_file(); + } + + let mut file = File::open(filepath)?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; + self.file_buffer_length = buffer.len(); + self.filebuffer = String::from_utf8(buffer); // Assuming UTF-8 encoding + } + pub fn modify_file_path(&mut self, file: &String) { + self.filepath = file; + } + + pub fn retrieve_file_buffer(&self) -> String { + self.filebuffer; + } + + pub fn retrieve_file_length(&self) -> i32 { + self.file_buffer_length; + } + + fn read_file(&mut self) { + let mut file = File::open(self.filepath)?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; + self.file_buffer_length = buffer.len(); + self.filebuffer = String::from_utf8(buffer); // Assuming UTF-8 encoding + self.file_read = true; + } +} \ No newline at end of file diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index ac2f66f..ecd5cc3 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -24,7 +24,7 @@ impl TokenManager { pub async fn request_token(&self) -> Result { println!("Sending request for a token"); - let endpoint = self.construct_endpoint(); + // let endpoint = self.construct_endpoint(); let mut url = self.retrieve_url(); // url += &endpoint; @@ -32,7 +32,6 @@ impl TokenManager { let mut token = models::token::Token::default(); - let client = reqwest::Client::new(); let response = client.post(&url) .json(&self.user) @@ -65,22 +64,23 @@ impl TokenManager { pub fn init(&mut self) { let mut api = &mut self.api; - api.endpoint = String::from("api/v1/login"); api.version = String::from("v1"); + api.endpoint = String::from(format!("api/{}/login", api.version)); } pub fn retrieve_url(&self) -> String { let api = &self.api; let mut url = String::from(&api.url); - url += &String::from("api/"); - url += &String::from(&api.version); - url += &String::from("/"); + // url += &String::from("api/"); + // url += &String::from(&api.version); + // url += &String::from("/"); url += &String::from(&api.endpoint); url += &String::from("/"); return url; } + // NOTE: This can get deleted. Redundant fn construct_endpoint(&self) -> String { let mut endpoint: String = String::from("api/"); endpoint += &self.api.version; diff --git a/src/models/icarus_action.rs b/src/models/icarus_action.rs index e0e39cf..4ef6aad 100644 --- a/src/models/icarus_action.rs +++ b/src/models/icarus_action.rs @@ -25,7 +25,7 @@ impl IcarusAction { for f in self.flags.iter() { if f.flag == *flag { - val = flag.clone(); + val = f.value.clone(); break; } } diff --git a/src/models/token.rs b/src/models/token.rs index 25bf3d2..d9c1740 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -4,17 +4,29 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize)] pub struct Token { + #[serde(alias = "user_id")] + pub user_id: i32, + #[serde(alias = "username")] + pub username: Option, + #[serde(alias = "token")] pub access_token: Option, + #[serde(alias = "token_type")] pub token_type: Option, + #[serde(alias = "expiration")] pub expiration: Option, + #[serde(alias = "message")] + pub message: Option, } impl Default for Token { fn default() -> Self { Token { + user_id: -1, + username: None, access_token: None, token_type: None, expiration: None, + message: None, } } } -- 2.47.3 From c0dc1eb78cd3adf5c474abe4bf3dcd15a690fe09 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 26 May 2024 20:35:55 -0400 Subject: [PATCH 32/47] Cargo formatting --- src/managers/action_managers.rs | 1 - src/managers/commit_manager.rs | 31 +++++++++++++++---------------- src/managers/token_manager.rs | 12 ++++-------- src/models/token.rs | 3 +-- src/syncers/delete.rs | 5 +++-- src/syncers/download.rs | 7 ++++--- src/syncers/retrieve_records.rs | 22 ++++++++++------------ src/syncers/syncer_base.rs | 2 -- src/syncers/upload.rs | 8 ++++---- src/utilities/checks.rs | 9 +++------ 10 files changed, 44 insertions(+), 56 deletions(-) diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index e1d666b..6c7bb51 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -39,7 +39,6 @@ impl ActionManager { ]; } - pub fn initialize(&mut self) { self.validate_flags(); self.validate_action(); diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index e4da341..275a4c4 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,17 +1,17 @@ use std::collections::HashMap; use std::default::Default; use std::fs::File; -use std::io::{Read, Error}; +use std::io::{Error, Read}; use tokio::runtime::Runtime; use futures::{FutureExt, TryFutureExt}; use serde::{Deserialize, Serialize}; -use crate::{exit_program, managers}; use crate::models; use crate::parsers; use crate::syncers; use crate::utilities; +use crate::{exit_program, managers}; #[derive(Debug, Deserialize, Serialize)] pub struct CommitManager { @@ -86,7 +86,7 @@ impl CommitManager { ActionValues::UploadSongWithMetadata => self.upload_song_with_metadata(), _ => { println!("Nothing good here"); - }, + } } } @@ -142,9 +142,7 @@ impl CommitManager { } } - let del = syncers::delete::Delete { - api: api, - }; + let del = syncers::delete::Delete { api: api }; println!("Deleting song.."); @@ -201,9 +199,11 @@ impl CommitManager { let coverpath = self.ica_action.retrieve_flag_value(&String::from("-ca")); let track_id = self.ica_action.retrieve_flag_value(&String::from("-t")); - let single_target = songpath.len() > 0 && metadata_path.len() > 0 && coverpath.len() > 0 && - track_id.len() > 0; - // !songPath.empty() && !metadataPath.empty() && + let single_target = songpath.len() > 0 + && metadata_path.len() > 0 + && coverpath.len() > 0 + && track_id.len() > 0; + // !songPath.empty() && !metadataPath.empty() && // !coverPath.empty() && !trackID.empty() ? true : false; let uni = self.ica_action.retrieve_flag_value(&String::from("-smca")); @@ -213,7 +213,6 @@ impl CommitManager { println!("Cannot upload from source and directory"); } - if single_target { println!("Song path: {}", songpath); println!("Track ID: {}", track_id); @@ -417,13 +416,13 @@ impl CommitManager { let content = self.retrieve_file_content(&path); // let alb = serde_json::from_str(&content.unwrap()); - /* - let mut file: std::fs::File = std::fs::File::open(filepath).unwrap(); - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); + /* + let mut file: std::fs::File = std::fs::File::open(filepath).unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); - return serde_json::from_str(&data).unwrap(); - */ + return serde_json::from_str(&data).unwrap(); + */ // return alb.unwrap(); return serde_json::from_str(&content.unwrap()).unwrap(); diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index ecd5cc3..b256f3b 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -33,21 +33,17 @@ impl TokenManager { let mut token = models::token::Token::default(); let client = reqwest::Client::new(); - let response = client.post(&url) - .json(&self.user) - .send() - .await - .unwrap(); + let response = client.post(&url).json(&self.user).send().await.unwrap(); match response.status() { reqwest::StatusCode::OK => { // on success, parse our JSON to an APIResponse let s = response.json::().await; match s { - // + // Ok(parsed) => { - token = parsed; - }, + token = parsed; + } Err(_) => println!("Hm, the response didn't match the shape we expected."), }; } diff --git a/src/models/token.rs b/src/models/token.rs index d9c1740..e975fa2 100644 --- a/src/models/token.rs +++ b/src/models/token.rs @@ -39,8 +39,7 @@ impl Token { Some(tok) => { token += tok; } - None => { - } + None => {} } return token; diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index f07a910..9f1df55 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -29,12 +29,13 @@ impl Delete { let url = self.retrieve_url(&song); let client = reqwest::Client::new(); let access_token = token.bearer_token(); - let response = client.delete(&url) + let response = client + .delete(&url) .header(reqwest::header::AUTHORIZATION, access_token) .send() .await .unwrap(); - + match response.status() { reqwest::StatusCode::OK => { println!("Success!"); diff --git a/src/syncers/download.rs b/src/syncers/download.rs index 052c8ec..f7e2277 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -2,7 +2,7 @@ use std::default::Default; use crate::models; -pub struct Download{ +pub struct Download { pub api: models::api::API, } @@ -19,7 +19,8 @@ impl Download { let url = self.retrieve_url(&song); let access_token = token.bearer_token(); let client = reqwest::Client::new(); - let response = client.get(&url) + let response = client + .get(&url) .header(reqwest::header::AUTHORIZATION, &access_token) .send() .await @@ -60,4 +61,4 @@ impl Download { return url; } -} \ No newline at end of file +} diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index c67dbfb..2cf1637 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -5,12 +5,10 @@ use crate::models; // use super::syncer_base::Result; - pub struct RetrieveRecords { pub api: models::api::API, } - impl Default for RetrieveRecords { fn default() -> Self { RetrieveRecords { @@ -19,31 +17,31 @@ impl Default for RetrieveRecords { } } - impl RetrieveRecords { - pub async fn get_all_songs(&self, token: &models::token::Token) - -> Result, Error> { - + pub async fn get_all_songs( + &self, + token: &models::token::Token, + ) -> Result, Error> { let mut songs: Vec = Vec::new(); let url = self.retrieve_url(); let access_token = token.bearer_token(); let client = reqwest::Client::new(); - let response = client.get(&url) + let response = client + .get(&url) .header(reqwest::header::AUTHORIZATION, access_token) .send() .await .unwrap(); - match response.status() { reqwest::StatusCode::OK => { // on success, parse our JSON to an APIResponse let s = response.json::>().await; match s { - // + // Ok(parsed) => { songs = parsed; - }, + } Err(_) => println!("Hm, the response didn't match the shape we expected."), }; } @@ -54,7 +52,7 @@ impl RetrieveRecords { panic!("Uh oh! Something unexpected happened: {:?}", other); } } - + return Ok(songs); } @@ -71,4 +69,4 @@ impl RetrieveRecords { return url; } -} \ No newline at end of file +} diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs index e816945..6f8144f 100644 --- a/src/syncers/syncer_base.rs +++ b/src/syncers/syncer_base.rs @@ -26,5 +26,3 @@ pub enum Result { UNAUTHORIZED, NOTFOUND, } - - diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index cc1c7e9..6b5fd12 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -22,12 +22,13 @@ impl Upload { let url = self.retrieve_url(&song); let client = reqwest::Client::new(); let access_token = token.bearer_token(); - let response = client.post(&url) + let response = client + .post(&url) .header(reqwest::header::AUTHORIZATION, access_token) .send() .await .unwrap(); - + match response.status() { reqwest::StatusCode::OK => { println!("Success!"); @@ -38,7 +39,6 @@ impl Upload { } } - fn retrieve_url(&self, song: &models::song::Song) -> String { // let mut url: String = String::new(); let api = &self.api; @@ -52,4 +52,4 @@ impl Upload { return url; } -} \ No newline at end of file +} diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 1badc23..034e124 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -27,12 +27,9 @@ impl Checks { } // TODO: Implement - pub fn index_of_item_in_container( - container: &String, - item: &char, - func: F, - ) -> i32 - where F: Fn(&char, &char) -> bool, + pub fn index_of_item_in_container(container: &String, item: &char, func: F) -> i32 + where + F: Fn(&char, &char) -> bool, { let mut index = -1; -- 2.47.3 From d9cc4818a2741b278781c0abec88f144c6b18654 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 27 May 2024 19:59:15 -0400 Subject: [PATCH 33/47] Adding more code to multi target upload --- src/managers/commit_manager.rs | 50 ++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 275a4c4..dc7af38 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,11 +1,12 @@ use std::collections::HashMap; use std::default::Default; -use std::fs::File; -use std::io::{Error, Read}; -use tokio::runtime::Runtime; +use std::fs::{read_dir, DirEntry}; +use std::io::{Error, Read, Result}; +use std::path::Path; use futures::{FutureExt, TryFutureExt}; use serde::{Deserialize, Serialize}; +use tokio::runtime::Runtime; use crate::models; use crate::parsers; @@ -57,6 +58,14 @@ enum RetrieveTypes { Songs, } +#[derive(Clone, Debug)] +enum En { + ImageFile, + SongFile, + MetadataFile, + Other, +} + impl Album { pub fn print_info(&self) { println!("Album: {}", self.title); @@ -190,6 +199,7 @@ impl CommitManager { return token.unwrap(); } + // TODO: Implement fn upload_song_with_metadata(&self) { println!("Uplodaring song with metadara"); @@ -237,7 +247,7 @@ impl CommitManager { ) { } // TODO: Implement - fn multi_target_upload(&self, sourcepath: &String) { + fn multi_target_upload(&self, sourcepath: &String) -> std::io::Result<()> { let mut prsr = parsers::api_parser::APIParser { api: models::api::API::default(), ica_act: self.ica_action.clone(), @@ -258,6 +268,36 @@ impl CommitManager { let mut metadatapath: String = String::new(); // iterate files in metadatapath + let path = std::path::Path::new(directory_path); + // let entries = std::fs::read_dir(path); + + for entry in read_dir(path)? { + let entry = entry?; + + let file_type = entry.file_type(); + let file_name = entry.file_name(); + + println!("file type: {:?}", file_type); + println!("file name: {:?}", file_name); + + // TODO: Write code to determine file extension by + // the file path. The result will determine what + // behavior will happen + + match self.find_file_extension(&file_name) { + En::ImageFile => {} + En::MetadataFile => {} + En::SongFile => {} + _ => {} + } + } + + Ok(()) + } + + // TODO: Implement + fn find_file_extension(&self, file_name: &std::ffi::OsString) -> En { + return En::Other; } // Standards @@ -428,7 +468,7 @@ impl CommitManager { return serde_json::from_str(&content.unwrap()).unwrap(); } - fn retrieve_file_content(&self, path: &String) -> Result { + fn retrieve_file_content(&self, path: &String) -> Result { /* let mut file = File::open(path)?; let mut buffer = Vec::new(); -- 2.47.3 From ea24782a04dc441dad524be9d34c07a9929d7044 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 1 Jun 2024 21:18:25 -0400 Subject: [PATCH 34/47] Adding more multi-target upload code and formatted code --- src/main.rs | 2 +- src/managers/commit_manager.rs | 97 +++++++++++++++++++++++++++++----- src/utilities/checks.rs | 1 + 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 080b2f4..721abda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ fn main() { chosen_act.print_action_and_flags(); - let cmt_mgr = managers::commit_manager::CommitManager { + let mut cmt_mgr = managers::commit_manager::CommitManager { ica_action: chosen_act, }; diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index dc7af38..d3614de 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::default::Default; +use std::fmt::Display; use std::fs::{read_dir, DirEntry}; use std::io::{Error, Read, Result}; use std::path::Path; @@ -78,11 +79,11 @@ impl Album { } impl CommitManager { - pub fn commit_action(&self) { + pub fn commit_action(&mut self) { let action = &self.ica_action.action; println!("Committing {} action", action); - let mapped_actions = self.map_actions(); + let mapped_actions = &self.map_actions(); let mapped_action = self.find_mapped_action(&mapped_actions, action); println!("{:?}", mapped_action); @@ -201,7 +202,7 @@ impl CommitManager { } // TODO: Implement - fn upload_song_with_metadata(&self) { + fn upload_song_with_metadata(&mut self) { println!("Uplodaring song with metadara"); let songpath = self.ica_action.retrieve_flag_value(&String::from("-s")); @@ -213,8 +214,6 @@ impl CommitManager { && metadata_path.len() > 0 && coverpath.len() > 0 && track_id.len() > 0; - // !songPath.empty() && !metadataPath.empty() && - // !coverPath.empty() && !trackID.empty() ? true : false; let uni = self.ica_action.retrieve_flag_value(&String::from("-smca")); let multitarget = uni.len() > 0; @@ -247,7 +246,7 @@ impl CommitManager { ) { } // TODO: Implement - fn multi_target_upload(&self, sourcepath: &String) -> std::io::Result<()> { + fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> { let mut prsr = parsers::api_parser::APIParser { api: models::api::API::default(), ica_act: self.ica_action.clone(), @@ -285,21 +284,97 @@ impl CommitManager { // behavior will happen match self.find_file_extension(&file_name) { - En::ImageFile => {} - En::MetadataFile => {} - En::SongFile => {} + En::ImageFile => { + let directory_part = sourcepath.clone(); + let fname = self.o_to_string(&file_name); + let fullpath = directory_part + "/" + &fname.unwrap(); + cover_art.path = Some(fullpath); + } + En::MetadataFile => { + let directory_part = sourcepath.clone(); + let fname = self.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); + song.filepath = Some(fname.unwrap()); + song.directory = Some(sourcepath.clone()); + // song.filepath = Some( + self.initialize_disc_and_track(&mut song); + + songs.push(song) + } _ => {} } } + let album = self.retrieve_metadata(&metadatapath); + songs.clear(); + songs = album.songs.clone(); + + let mut up = syncers::upload::Upload::default(); + + for _ in songs { + // Upload each song + // TODO: Add functions to Upload struct that uploads song + // with metadata and img + } + Ok(()) } // TODO: Implement fn find_file_extension(&self, file_name: &std::ffi::OsString) -> En { + let file_name_str = Some(file_name.clone().into_string()); + + match file_name_str { + Some(string) => { + let a = string.unwrap(); + let mut split = a.split("."); + let mut last_index = 0; + + for _ in split.clone() { + last_index += 1; + } + + let mut extension = String::new(); + let mut index = 1; + + for word in split { + if index == last_index { + extension = word.to_string(); + break; + } + + index += 1; + } + + if extension == "wav" || extension == "flac" { + return En::SongFile; + } else if extension == "json" { + return En::MetadataFile; + } else if extension == "jpg" || extension == "jpeg" || extension == "png" { + return En::ImageFile; + } + } + // Err(err) => { + _ => { + return En::Other; + } + } + return En::Other; } + fn o_to_string(&self, val: &std::ffi::OsString) -> Result { + let res = val.clone().into_string(); + return match res { + Ok(sss) => Ok(sss), + Err(eee) => Ok(String::from("Error")), + }; + } + // Standards // * track01.cdda.wav - Disc 1, Track 1 // * track02d02.cdda.wav - Disc 2, Track 2 @@ -339,9 +414,7 @@ impl CommitManager { let mut t: String = String::new(); let mut index = 0; for a in filename.chars() { - if index <= ed { - t.push(a); - } else if index >= st { + if index >= st && index <= ed { t.push(a); } diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 034e124..42bd519 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -35,6 +35,7 @@ impl Checks { for c in container.chars() { if func(&c, item) { + index += 1; break; } -- 2.47.3 From ffc0d398f0cebfad22d67980c1c3c03b672a2114 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 2 Jun 2024 16:11:23 -0400 Subject: [PATCH 35/47] Added more multi-upload code --- Cargo.toml | 3 +- src/managers/commit_manager.rs | 125 ++++++++++++++++++++------------- src/models/song.rs | 56 +++++++++++++++ src/syncers/upload.rs | 116 ++++++++++++++++++++++++++++-- 4 files changed, 247 insertions(+), 53 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 75ab991..79a044e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,10 @@ edition = "2021" [dependencies] futures = { version = "0.3.30" } -reqwest = { version = "0.12.4", features = ["json", "blocking"] } +reqwest = { version = "0.12.4", features = ["json", "blocking", "multipart", "stream"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.37", features = ["full"] } +tokio-util = { version = "0.7.11", features = ["codec"] } # rodio = "0.17.3" # metadata = "0.1.8" diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index d3614de..a63b563 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize}; use tokio::runtime::Runtime; use crate::models; +use crate::models::song::Album; use crate::parsers; use crate::syncers; use crate::utilities; @@ -20,30 +21,6 @@ pub struct CommitManager { pub ica_action: models::icarus_action::IcarusAction, } -#[derive(Debug, Deserialize, Serialize)] -pub struct Album { - pub title: String, - pub album_artist: String, - pub genre: String, - pub year: i32, - pub track_count: i32, - pub disc_count: i32, - pub songs: Vec, -} - -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(), - } - } -} #[derive(Clone, Debug)] enum ActionValues { @@ -264,6 +241,7 @@ impl CommitManager { let mut cover_art = models::song::CoverArt::default(); let mut songs: Vec = Vec::new(); + let mut filenames: Vec = Vec::new(); let mut metadatapath: String = String::new(); // iterate files in metadatapath @@ -298,10 +276,16 @@ impl CommitManager { En::SongFile => { let mut song = models::song::Song::default(); let fname = self.o_to_string(&file_name); - song.filepath = Some(fname.unwrap()); - song.directory = Some(sourcepath.clone()); - // song.filepath = Some( - self.initialize_disc_and_track(&mut song); + + match fname { + Ok(s) => { + filenames.push(s.clone()); + song.filepath = Some(s.clone()); + song.directory = Some(sourcepath.clone()); + self.initialize_disc_and_track(&mut song); + }, + Err(er) => println!("Error: {:?}", er), + } songs.push(song) } @@ -309,22 +293,74 @@ impl CommitManager { } } - let album = self.retrieve_metadata(&metadatapath); - songs.clear(); - songs = album.songs.clone(); + let mut album = self.retrieve_metadata(&metadatapath); + + self.song_parsing(&mut album, &sourcepath, &filenames); + + // songs.clear(); + // songs = album.songs; let mut up = syncers::upload::Upload::default(); + let host = self.ica_action.retrieve_flag_value(&String::from("-h")); + up.set_api(&host); - for _ in songs { + for song in &album.songs { // Upload each song // TODO: Add functions to Upload struct that uploads song // with metadata and img + up.upload_song_with_metadata(&token, &song, &cover_art, &album); } Ok(()) } - // TODO: Implement + + // Makes sure the elements in album.songs is populated + fn song_parsing(&self, album: &mut models::song::Album, directory: &String, filenames: &Vec) { + // Apply directory + for song in &mut album.songs { + // let bor = song.as_mut(); + let mut 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.filepath = 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()); @@ -528,26 +564,19 @@ impl CommitManager { let content = self.retrieve_file_content(&path); // let alb = serde_json::from_str(&content.unwrap()); - - /* - let mut file: std::fs::File = std::fs::File::open(filepath).unwrap(); - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); - - return serde_json::from_str(&data).unwrap(); - */ + let val = content.unwrap(); // return alb.unwrap(); - return serde_json::from_str(&content.unwrap()).unwrap(); + let converted = serde_json::from_str(&val); + + match &converted { + Ok(res) => println!("Good!"), + Err(er) => println!("Error {:?}", er), + } + return converted.unwrap(); } fn retrieve_file_content(&self, path: &String) -> Result { - /* - let mut file = File::open(path)?; - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer)?; - */ - return std::fs::read_to_string(path); } } diff --git a/src/models/song.rs b/src/models/song.rs index 7060a27..bfdfe7a 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -1,4 +1,5 @@ use std::default::Default; +use std::io::Read; use serde::{Deserialize, Serialize}; @@ -20,6 +21,33 @@ pub struct Song { pub directory: Option, } +#[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, +} + +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 { @@ -62,6 +90,15 @@ impl Song { return buffer; } + pub fn to_data(&self) -> Result, std::io::Error> { + let path = self.song_path(); + // let content = std::fs::read_to_string(path); + let mut file = std::fs::File::open(path)?; + let mut buffer = Vec::new(); + file.read(&mut buffer)?; + Ok(buffer) + // return content; + } // 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(); @@ -103,3 +140,22 @@ impl Default for CoverArt { } } } + +impl CoverArt { + pub fn to_data(&self) -> Result, 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(&mut buffer)?; + Ok(buffer) + } +} \ No newline at end of file diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 6b5fd12..065e042 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1,7 +1,13 @@ use std::default::Default; +use reqwest::blocking::multipart; +use serde::{Deserialize, Serialize}; use reqwest; +// use reqwest::blocking:: +use reqwest::{Body, Client}; +use reqwest::multipart::{Form, Part}; use reqwest::Response; +use tokio::fs::File; use crate::models; @@ -9,6 +15,22 @@ pub struct Upload { pub api: models::api::API, } + +#[derive(Debug, Deserialize, Serialize)] +struct Song { + title: String, + album: String, + artist: String, + album_artist: String, + year: i32, + genre: String, + duration: f64, + track: i32, + track_count: i32, + disc: i32, + disc_count: i32, +} + impl Default for Upload { fn default() -> Self { Upload { @@ -39,17 +61,103 @@ impl Upload { } } + // TODO: Implement + pub async fn upload_song_with_metadata(&mut self, token: &models::token::Token, song: &models::song::Song, + cover: &models::song::CoverArt, album: &models::song::Album) { + self.api.endpoint = String::from("song/data/upload/with/data"); + let url = self.retrieve_url(&song); + let client = reqwest::Client::new(); + let new_song = self.initialize_song(&song, &album); + let access_token = token.bearer_token(); + + let song_data = song.to_data(); + let cover_data = cover.to_data(); + + match song_data { + Ok(sd) => { + }, + Err(er) => { + println!("Error: {:?}", er); + std::process::exit(-1); + } + } + + match cover_data { + Ok(_) => {}, + Err(er) => { + println!("Error: {:?}", er); + std::process::exit(-1); + } + } + + if url.is_empty() { + println!("Url is empty"); + } + + /* + + let s_file = std::fs::File::open(song.song_path()); + let s_stream = tokio_util::codec::FramedRead::new(s_file, tokio_util::codec::BytesCodec::new()); + let s_file_body = Body::wrap_stream(s_stream); + let s_some_file = multipart::Part::stream(s_file_body) + .file_name("track.cdda.wav"); + + let s_data = Part::file(song.song_path()); + let c_data = multipart::Part::stream(&cover.path); + + let mut form = Form::new(); + let meta = serde_json::to_string_pretty(&new_song); + form = form.text("metadata", meta.unwrap()); + + form = form.part("file", s_some_file) + .part("cover", c_data); + + let response = client.post(url).multipart(form).send(); + let result = response.text; + + return Ok(result); + */ + } + + + + pub fn set_api(&mut self, host: &String) { + let mut api = models::api::API::default(); + api.url = host.clone(); + api.version = String::from("v1"); + self.api = api; + } fn retrieve_url(&self, song: &models::song::Song) -> String { - // let mut url: String = String::new(); let api = &self.api; - let mut url: String = String::from(&api.url); + let mut buffer = api.url.clone(); + let count = buffer.len(); + + if buffer.chars().nth(count - 1) != Some('/') { + buffer += "/"; + } + + let mut url: String = String::from(&buffer); url += &String::from("api/"); url += &String::from(&api.version); url += &String::from("/"); url += &String::from(&api.endpoint); - // url += &String::from("/"); - // url += &song.id.unwrap().to_string(); return url; } + + fn initialize_song(&self, song: &models::song::Song, album: &models::song::Album) -> Song { + return Song { + title: String::from(&song.title.clone().unwrap()), + album: album.title.clone(), + artist: String::from(&song.artist.clone().unwrap().clone()), + album_artist: album.album_artist.clone(), + year: album.year.clone(), + genre: album.genre.clone(), + duration: song.duration.clone().unwrap(), + track: (song.track.clone().unwrap()), + track_count: album.track_count.clone(), + disc: song.disc.clone().unwrap(), + disc_count: album.disc_count.clone(), + }; + } } -- 2.47.3 From 9c3d5d67c53b0e608a7fc67ca80bdc680c7ea785 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 2 Jun 2024 16:11:43 -0400 Subject: [PATCH 36/47] cargo fmt --- src/managers/commit_manager.rs | 25 +++++++++++++----------- src/models/song.rs | 8 ++++---- src/syncers/upload.rs | 35 +++++++++++++++++----------------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index a63b563..d333aa7 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -21,7 +21,6 @@ pub struct CommitManager { pub ica_action: models::icarus_action::IcarusAction, } - #[derive(Clone, Debug)] enum ActionValues { DeleteAct, @@ -283,7 +282,7 @@ impl CommitManager { song.filepath = Some(s.clone()); song.directory = Some(sourcepath.clone()); self.initialize_disc_and_track(&mut song); - }, + } Err(er) => println!("Error: {:?}", er), } @@ -314,9 +313,13 @@ impl CommitManager { Ok(()) } - // Makes sure the elements in album.songs is populated - fn song_parsing(&self, album: &mut models::song::Album, directory: &String, filenames: &Vec) { + fn song_parsing( + &self, + album: &mut models::song::Album, + directory: &String, + filenames: &Vec, + ) { // Apply directory for song in &mut album.songs { // let bor = song.as_mut(); @@ -325,7 +328,7 @@ impl CommitManager { Some(s) => println!("{}", s), None => { song.directory = Some(directory.clone()); - }, + } } } @@ -339,24 +342,24 @@ impl CommitManager { for song in &mut album.songs { match &mut song.album { - Some(_) => {}, + Some(_) => {} None => { song.album = Some(album.title.clone()); - }, + } } match &mut song.genre { - Some(_) => {}, + Some(_) => {} None => { song.genre = Some(album.genre.clone()); - }, + } } match &mut song.year { - Some(_) => {}, + Some(_) => {} None => { song.year = Some(album.year.clone()); - }, + } } } } diff --git a/src/models/song.rs b/src/models/song.rs index bfdfe7a..bad0947 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -93,7 +93,7 @@ impl Song { pub fn to_data(&self) -> Result, std::io::Error> { let path = self.song_path(); // let content = std::fs::read_to_string(path); - let mut file = std::fs::File::open(path)?; + let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); file.read(&mut buffer)?; Ok(buffer) @@ -147,10 +147,10 @@ impl CoverArt { match &self.path { Some(val) => { path = String::from(val); - }, + } None => { (); - }, + } } let mut file = std::fs::File::open(path)?; @@ -158,4 +158,4 @@ impl CoverArt { file.read(&mut buffer)?; Ok(buffer) } -} \ No newline at end of file +} diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 065e042..95d67a8 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1,12 +1,12 @@ use std::default::Default; +use reqwest; use reqwest::blocking::multipart; use serde::{Deserialize, Serialize}; -use reqwest; // use reqwest::blocking:: -use reqwest::{Body, Client}; use reqwest::multipart::{Form, Part}; use reqwest::Response; +use reqwest::{Body, Client}; use tokio::fs::File; use crate::models; @@ -15,7 +15,6 @@ pub struct Upload { pub api: models::api::API, } - #[derive(Debug, Deserialize, Serialize)] struct Song { title: String, @@ -62,20 +61,24 @@ impl Upload { } // TODO: Implement - pub async fn upload_song_with_metadata(&mut self, token: &models::token::Token, song: &models::song::Song, - cover: &models::song::CoverArt, album: &models::song::Album) { - self.api.endpoint = String::from("song/data/upload/with/data"); - let url = self.retrieve_url(&song); - let client = reqwest::Client::new(); - let new_song = self.initialize_song(&song, &album); - let access_token = token.bearer_token(); - + pub async fn upload_song_with_metadata( + &mut self, + token: &models::token::Token, + song: &models::song::Song, + cover: &models::song::CoverArt, + album: &models::song::Album, + ) { + self.api.endpoint = String::from("song/data/upload/with/data"); + let url = self.retrieve_url(&song); + let client = reqwest::Client::new(); + let new_song = self.initialize_song(&song, &album); + let access_token = token.bearer_token(); + let song_data = song.to_data(); let cover_data = cover.to_data(); match song_data { - Ok(sd) => { - }, + Ok(sd) => {} Err(er) => { println!("Error: {:?}", er); std::process::exit(-1); @@ -83,7 +86,7 @@ impl Upload { } match cover_data { - Ok(_) => {}, + Ok(_) => {} Err(er) => { println!("Error: {:?}", er); std::process::exit(-1); @@ -111,7 +114,7 @@ impl Upload { form = form.part("file", s_some_file) .part("cover", c_data); - + let response = client.post(url).multipart(form).send(); let result = response.text; @@ -119,8 +122,6 @@ impl Upload { */ } - - pub fn set_api(&mut self, host: &String) { let mut api = models::api::API::default(); api.url = host.clone(); -- 2.47.3 From a4f38fd91745be04482584b6b0f9df310eb15d06 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Fri, 7 Jun 2024 22:37:51 -0400 Subject: [PATCH 37/47] Got uploading functional and cargo fmt-ing --- Cargo.toml | 2 + src/managers/commit_manager.rs | 8 +++- src/models/song.rs | 11 +++-- src/syncers/upload.rs | 85 ++++++++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 79a044e..882ee20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ edition = "2021" [dependencies] futures = { version = "0.3.30" } reqwest = { version = "0.12.4", features = ["json", "blocking", "multipart", "stream"] } +http = { version = "1.1.0" } +# reqwest = { version = "0.12.4", features = ["full"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.37", features = ["full"] } diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index d333aa7..a8390b1 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -303,11 +303,17 @@ impl CommitManager { let host = self.ica_action.retrieve_flag_value(&String::from("-h")); up.set_api(&host); + println!(""); + for song in &album.songs { // Upload each song // TODO: Add functions to Upload struct that uploads song // with metadata and img - up.upload_song_with_metadata(&token, &song, &cover_art, &album); + println!("Sending song..."); + let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album); + let tken = Runtime::new().unwrap().block_on(res); + // let data = futures::executor::block_on(res); + println!("{:?}", tken); } Ok(()) diff --git a/src/models/song.rs b/src/models/song.rs index bad0947..8f17fcd 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -92,12 +92,17 @@ impl Song { pub fn to_data(&self) -> Result, std::io::Error> { let path = self.song_path(); + println!("Converting song to data"); + println!("Path: {:?}", path); // let content = std::fs::read_to_string(path); let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); - file.read(&mut buffer)?; + file.read_to_end(&mut buffer)?; + if buffer.len() == 0 { + println!("Why is it empty?"); + } + Ok(buffer) - // return content; } // if 1 - wav, if 0 - mp3, anything else defaults to wav pub fn generate_filename_from_track(&mut self, i_type: i32) -> i32 { @@ -155,7 +160,7 @@ impl CoverArt { let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); - file.read(&mut buffer)?; + file.read_to_end(&mut buffer)?; Ok(buffer) } } diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 95d67a8..b8b784d 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1,5 +1,8 @@ use std::default::Default; +use http::header; +use http::HeaderMap; +use http::HeaderValue; use reqwest; use reqwest::blocking::multipart; use serde::{Deserialize, Serialize}; @@ -30,6 +33,12 @@ struct Song { disc_count: i32, } +impl Song { + pub fn to_metadata_json(&self) -> Result { + return serde_json::to_string_pretty(&self); + } +} + impl Default for Upload { fn default() -> Self { Upload { @@ -67,7 +76,7 @@ impl Upload { song: &models::song::Song, cover: &models::song::CoverArt, album: &models::song::Album, - ) { + ) -> Result { self.api.endpoint = String::from("song/data/upload/with/data"); let url = self.retrieve_url(&song); let client = reqwest::Client::new(); @@ -76,9 +85,16 @@ impl Upload { let song_data = song.to_data(); let cover_data = cover.to_data(); + let song_detail = new_song.to_metadata_json().unwrap(); + + let mut song_raw_data: Vec = Vec::new(); + let mut cover_raw_data: Vec = Vec::new(); match song_data { - Ok(sd) => {} + Ok(sd) => { + println!("song converted to data. Length {:?}", sd.len()); + song_raw_data = sd; + } Err(er) => { println!("Error: {:?}", er); std::process::exit(-1); @@ -86,7 +102,9 @@ impl Upload { } match cover_data { - Ok(_) => {} + Ok(cv) => { + cover_raw_data = cv; + } Err(er) => { println!("Error: {:?}", er); std::process::exit(-1); @@ -97,6 +115,67 @@ impl Upload { println!("Url is empty"); } + println!("Url: {}", url); + + println!("Length: {:?}", song_raw_data.len()); + + // Adding text data + // form = form.text("metadata", song_detail); + + // Adding a file + // let file_path = "path/to/your/file.txt"; + // let file = reqwest::blocking::multipart::Part::file(file_path); + let mut headers = Vec::new(); + headers.push("application/octet-stream"); + headers.push("Content-type"); + + let mut headers = HeaderMap::new(); + headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/octet-stream"), + ); + + let file = reqwest::multipart::Part::bytes(song_raw_data.clone()).headers(headers); + // headers.clear(); + let mut headers_i = HeaderMap::new(); + headers_i.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("image/jpeg"), + ); + let mut image_dis = String::new(); + image_dis = "form-data; name='cover'; filename='audio.wav'".to_owned(); + // headers_i.insert(http::header::CONTENT_DISPOSITION, HeaderValue::from_static("form-data; name=\"cover\"; filename=\"file.jpeg\"")); + + let cover = reqwest::multipart::Part::bytes(cover_raw_data.clone()).headers(headers_i); + let song_filepath = "ss"; + let mut p = reqwest::multipart::Part::stream(song_raw_data.clone()); + // p.file_name("file"); + let mut q = reqwest::multipart::Part::stream(cover_raw_data.clone()); + // q.file_name("cover"); + // let ee = reqwest::multipart::Part::file_name(song_filepath); + // let content_type = http::header::ContentType::from_mime_type("audio/mpeg").unwrap(); + + // let mut disposition = http::header::ContentDisposition::form_data_binary(); + // disposition.set_filename("my_file.mp3"); + + let mut form = Form::new(); + form = form + .part("cover", cover.file_name("cover.jpeg")) + .text("metadata", song_detail) + .part("file", file.file_name("audio.wav")); + + let response = client + .post(url) + .multipart(form) + .header(reqwest::header::AUTHORIZATION, access_token) + .send() + .await; + let response_text = response.unwrap(); + println!("Something was sent"); + println!("{:?}", response_text); + + return Ok(response_text); + /* let s_file = std::fs::File::open(song.song_path()); -- 2.47.3 From 08b5fef3db003da78d9f9eb020b5af51bd656740 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 8 Jun 2024 12:13:22 -0400 Subject: [PATCH 38/47] Uploading multi target works, but is buggy Not all of the songs are being uploaded --- src/managers/commit_manager.rs | 50 ++++++----------- src/models/song.rs | 1 + src/syncers/upload.rs | 99 +++++++++++----------------------- 3 files changed, 50 insertions(+), 100 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index a8390b1..3d60d84 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -171,7 +171,6 @@ impl CommitManager { }; tok_mgr.init(); - // let token = tok_mgr.request_token(); let token = Runtime::new().unwrap().block_on(tok_mgr.request_token()); return token.unwrap(); @@ -245,7 +244,6 @@ impl CommitManager { // iterate files in metadatapath let path = std::path::Path::new(directory_path); - // let entries = std::fs::read_dir(path); for entry in read_dir(path)? { let entry = entry?; @@ -256,9 +254,6 @@ impl CommitManager { println!("file type: {:?}", file_type); println!("file name: {:?}", file_name); - // TODO: Write code to determine file extension by - // the file path. The result will determine what - // behavior will happen match self.find_file_extension(&file_name) { En::ImageFile => { @@ -292,12 +287,12 @@ impl CommitManager { } } + filenames.sort(); + let mut album = self.retrieve_metadata(&metadatapath); self.song_parsing(&mut album, &sourcepath, &filenames); - // songs.clear(); - // songs = album.songs; let mut up = syncers::upload::Upload::default(); let host = self.ica_action.retrieve_flag_value(&String::from("-h")); @@ -307,13 +302,20 @@ impl CommitManager { for song in &album.songs { // Upload each song - // TODO: Add functions to Upload struct that uploads song - // with metadata and img println!("Sending song..."); let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album); let tken = Runtime::new().unwrap().block_on(res); - // let data = futures::executor::block_on(res); - println!("{:?}", tken); + + match &tken { + Ok(o) => { + println!("Successfully sent {:?}", o); + }, + Err(er) => { + println!("Some error {:?}", er); + } + } + + println!(""); } Ok(()) @@ -328,8 +330,7 @@ impl CommitManager { ) { // Apply directory for song in &mut album.songs { - // let bor = song.as_mut(); - let mut dir = &song.directory; + let dir = &song.directory; match dir { Some(s) => println!("{}", s), None => { @@ -376,7 +377,7 @@ impl CommitManager { match file_name_str { Some(string) => { let a = string.unwrap(); - let mut split = a.split("."); + let split = a.split("."); let mut last_index = 0; for _ in split.clone() { @@ -403,7 +404,6 @@ impl CommitManager { return En::ImageFile; } } - // Err(err) => { _ => { return En::Other; } @@ -416,7 +416,7 @@ impl CommitManager { let res = val.clone().into_string(); return match res { Ok(sss) => Ok(sss), - Err(eee) => Ok(String::from("Error")), + Err(_) => Ok(String::from("Error")), }; } @@ -427,11 +427,9 @@ impl CommitManager { let mut disc = 1; let mut track = 1; let mut mode = 0; - let songpath = song.song_path(); let filename = & as Clone>::clone(&song.filepath).unwrap(); - // let directory = & as Clone>::clone(&self.directory).unwrap(); let trd = filename.contains("trackd"); let tr = filename.contains("track"); @@ -559,27 +557,13 @@ impl CommitManager { } fn retrieve_metadata(&self, path: &String) -> Album { - /* - let mut alb = Album { - title: String::from(""), - album_artist: String::from(""), - genre: String::from(""), - year: 0, - track_count: 0, - disc_count: 0, - songs: Vec::new(), - }; - */ - let content = self.retrieve_file_content(&path); - // let alb = serde_json::from_str(&content.unwrap()); let val = content.unwrap(); - // return alb.unwrap(); let converted = serde_json::from_str(&val); match &converted { - Ok(res) => println!("Good!"), + Ok(_) => println!("Good!"), Err(er) => println!("Error {:?}", er), } return converted.unwrap(); diff --git a/src/models/song.rs b/src/models/song.rs index 8f17fcd..e61e37e 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -70,6 +70,7 @@ impl Default for Song { impl Song { pub fn print_info(&self) { println!("Title: {:?}", self.title); + println!("Artist: {:?}", self.artist); } pub fn song_path(&self) -> String { diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index b8b784d..8079699 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -26,7 +26,7 @@ struct Song { album_artist: String, year: i32, genre: String, - duration: f64, + duration: i32, track: i32, track_count: i32, disc: i32, @@ -49,7 +49,7 @@ impl Default for Upload { impl Upload { pub async fn upload_song(&self, token: &models::token::Token, song: &models::song::Song) { - let url = self.retrieve_url(&song); + let url = self.retrieve_url(); let client = reqwest::Client::new(); let access_token = token.bearer_token(); let response = client @@ -78,7 +78,7 @@ impl Upload { album: &models::song::Album, ) -> Result { self.api.endpoint = String::from("song/data/upload/with/data"); - let url = self.retrieve_url(&song); + let url = self.retrieve_url(); let client = reqwest::Client::new(); let new_song = self.initialize_song(&song, &album); let access_token = token.bearer_token(); @@ -116,53 +116,12 @@ impl Upload { } println!("Url: {}", url); - println!("Length: {:?}", song_raw_data.len()); + println!("Token: {}", access_token); - // Adding text data - // form = form.text("metadata", song_detail); + let form = self.initialize_form(song_raw_data, cover_raw_data, song_detail.clone()); - // Adding a file - // let file_path = "path/to/your/file.txt"; - // let file = reqwest::blocking::multipart::Part::file(file_path); - let mut headers = Vec::new(); - headers.push("application/octet-stream"); - headers.push("Content-type"); - - let mut headers = HeaderMap::new(); - headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/octet-stream"), - ); - - let file = reqwest::multipart::Part::bytes(song_raw_data.clone()).headers(headers); - // headers.clear(); - let mut headers_i = HeaderMap::new(); - headers_i.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("image/jpeg"), - ); - let mut image_dis = String::new(); - image_dis = "form-data; name='cover'; filename='audio.wav'".to_owned(); - // headers_i.insert(http::header::CONTENT_DISPOSITION, HeaderValue::from_static("form-data; name=\"cover\"; filename=\"file.jpeg\"")); - - let cover = reqwest::multipart::Part::bytes(cover_raw_data.clone()).headers(headers_i); - let song_filepath = "ss"; - let mut p = reqwest::multipart::Part::stream(song_raw_data.clone()); - // p.file_name("file"); - let mut q = reqwest::multipart::Part::stream(cover_raw_data.clone()); - // q.file_name("cover"); - // let ee = reqwest::multipart::Part::file_name(song_filepath); - // let content_type = http::header::ContentType::from_mime_type("audio/mpeg").unwrap(); - - // let mut disposition = http::header::ContentDisposition::form_data_binary(); - // disposition.set_filename("my_file.mp3"); - - let mut form = Form::new(); - form = form - .part("cover", cover.file_name("cover.jpeg")) - .text("metadata", song_detail) - .part("file", file.file_name("audio.wav")); + println!("Form: {:?}", form); let response = client .post(url) @@ -171,34 +130,36 @@ impl Upload { .send() .await; let response_text = response.unwrap(); + println!("Something was sent"); println!("{:?}", response_text); return Ok(response_text); + } - /* + fn initialize_form(&self, song_raw_data: Vec, cover_raw_data: Vec, song_detail: String) -> Form { + let mut headers = HeaderMap::new(); + headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/octet-stream"), + ); - let s_file = std::fs::File::open(song.song_path()); - let s_stream = tokio_util::codec::FramedRead::new(s_file, tokio_util::codec::BytesCodec::new()); - let s_file_body = Body::wrap_stream(s_stream); - let s_some_file = multipart::Part::stream(s_file_body) - .file_name("track.cdda.wav"); + let file = reqwest::multipart::Part::bytes(song_raw_data).headers(headers); + let mut headers_i = HeaderMap::new(); + headers_i.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("image/jpeg"), + ); - let s_data = Part::file(song.song_path()); - let c_data = multipart::Part::stream(&cover.path); + let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); let mut form = Form::new(); - let meta = serde_json::to_string_pretty(&new_song); - form = form.text("metadata", meta.unwrap()); + form = form + .part("cover", cover.file_name("cover.jpeg")) + .text("metadata", song_detail) + .part("file", file.file_name("audio.wav")); - form = form.part("file", s_some_file) - .part("cover", c_data); - - let response = client.post(url).multipart(form).send(); - let result = response.text; - - return Ok(result); - */ + return form; } pub fn set_api(&mut self, host: &String) { @@ -207,7 +168,8 @@ impl Upload { api.version = String::from("v1"); self.api = api; } - fn retrieve_url(&self, song: &models::song::Song) -> String { + + fn retrieve_url(&self) -> String { let api = &self.api; let mut buffer = api.url.clone(); let count = buffer.len(); @@ -226,6 +188,9 @@ impl Upload { } fn initialize_song(&self, song: &models::song::Song, album: &models::song::Album) -> Song { + let dur = song.duration.clone().unwrap(); + println!("Duration: {}", dur); + return Song { title: String::from(&song.title.clone().unwrap()), album: album.title.clone(), @@ -233,7 +198,7 @@ impl Upload { album_artist: album.album_artist.clone(), year: album.year.clone(), genre: album.genre.clone(), - duration: song.duration.clone().unwrap(), + duration: f64::round(dur) as i32, track: (song.track.clone().unwrap()), track_count: album.track_count.clone(), disc: song.disc.clone().unwrap(), -- 2.47.3 From 06256bebf730a2212f4a7ababf6e65420a0b8619 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 8 Jun 2024 17:59:54 -0400 Subject: [PATCH 39/47] Added single target upload --- src/managers/commit_manager.rs | 142 ++++++++++++++++++++++++++++++--- src/models/song.rs | 4 +- src/syncers/upload.rs | 44 ++++++---- 3 files changed, 166 insertions(+), 24 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 3d60d84..35bbb55 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -4,13 +4,14 @@ use std::fmt::Display; use std::fs::{read_dir, DirEntry}; use std::io::{Error, Read, Result}; use std::path::Path; +use std::str::FromStr; use futures::{FutureExt, TryFutureExt}; use serde::{Deserialize, Serialize}; use tokio::runtime::Runtime; -use crate::models; use crate::models::song::Album; +use crate::models::{self, song}; use crate::parsers; use crate::syncers; use crate::utilities; @@ -52,6 +53,27 @@ impl Album { println!("Track Count: {}", self.track_count); println!("Disc Count: {}\n", self.disc_count); } + + pub fn retrieve_song(&self, track: i32, disc: i32) -> Result { + 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", + )); + } } impl CommitManager { @@ -195,13 +217,14 @@ impl CommitManager { if single_target && multitarget { println!("Cannot upload from source and directory"); + panic!("What??"); } if single_target { println!("Song path: {}", songpath); println!("Track ID: {}", track_id); - println!("metadata path: {}", coverpath); - println!("cover art path: {}", track_id); + println!("metadata path: {}", metadata_path); + println!("cover art path: {}", coverpath); self.sing_target_upload(&songpath, &track_id, &metadata_path, &coverpath); } else if multitarget { @@ -213,12 +236,112 @@ impl CommitManager { // TODO: Implement fn sing_target_upload( - &self, + &mut self, songpath: &String, track_id: &String, meta_path: &String, cover_path: &String, - ) { + ) -> Result<()> { + let mut prsr = parsers::api_parser::APIParser { + api: models::api::API::default(), + ica_act: self.ica_action.clone(), + }; + prsr.parse_api(); + + let api = prsr.retrieve_api(); + let token = self.parse_token(&api); + + let song_file = std::path::Path::new(&songpath); + + if !song_file.exists() { + println!("Song file does not exist"); + panic!("Error"); + } + + let mut cover_art = models::song::CoverArt::default(); + let mut song = models::song::Song::default(); + let mut filenames = Vec::new(); + let mut fp = String::new(); + let mut dir = String::new(); + + // song_file.file_name(); + + // for entry in read_dir(song_file)? { + // for entry in read_file(song_file)? { + let entry = &song_file; + + // let file_type = entry.file_type(); + let file_name = std::ffi::OsString::from(entry.file_name().unwrap()); + + // println!("file type: {:?}", file_type); + println!("file name: {:?}", file_name); + + match self.find_file_extension(&file_name) { + En::ImageFile => { + // let directory_part = sourcepath.clone(); + // let fname = self.o_to_string(&file_name); + // let fullpath = directory_part + "/" + &fname.unwrap(); + // cover_art.path = Some(fullpath); + } + En::MetadataFile => { + // let directory_part = sourcepath.clone(); + // let fname = self.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()); + fp = s.clone(); + dir = song_file.parent().unwrap().display().to_string(); + song.filepath = Some(s.clone()); + song.directory = Some(dir.clone()); + self.initialize_disc_and_track(&mut song); + } + Err(er) => println!("Error: {:?}", er), + } + + // songs.push(song) + } + _ => {} + } + // } + + cover_art.path = Some(cover_path.clone()); + + let mut album = self.retrieve_metadata(&meta_path); + // self.song_parsing(&mut album, &song.directory.unwrap(), &filenames); + let trck = i32::from_str(track_id).unwrap(); + let mut s = album.retrieve_song(trck, 1).unwrap(); + s.filepath = 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()); + + cover_art.data = Some(cover_art.to_data().unwrap()); + + let mut up = syncers::upload::Upload::default(); + let host = self.ica_action.retrieve_flag_value(&String::from("-h")); + up.set_api(&host); + + let res = up.upload_song_with_metadata(&token, &s, &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); + } + } + + Ok(()) } // TODO: Implement fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> { @@ -254,7 +377,6 @@ impl CommitManager { println!("file type: {:?}", file_type); println!("file name: {:?}", file_name); - match self.find_file_extension(&file_name) { En::ImageFile => { let directory_part = sourcepath.clone(); @@ -276,6 +398,7 @@ impl CommitManager { filenames.push(s.clone()); song.filepath = 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), @@ -293,11 +416,12 @@ impl CommitManager { self.song_parsing(&mut album, &sourcepath, &filenames); - 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()); + println!(""); for song in &album.songs { @@ -309,12 +433,12 @@ impl CommitManager { match &tken { Ok(o) => { println!("Successfully sent {:?}", o); - }, + } Err(er) => { println!("Some error {:?}", er); } } - + println!(""); } diff --git a/src/models/song.rs b/src/models/song.rs index e61e37e..51184db 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -14,7 +14,7 @@ pub struct Song { pub duration: Option, pub track: Option, pub disc: Option, - pub data: Option, + pub data: Option>, // use filepath instead // pub song_path: String, pub filepath: Option, @@ -135,6 +135,7 @@ pub struct CoverArt { pub id: Option, pub title: Option, pub path: Option, + pub data: Option>, } impl Default for CoverArt { @@ -143,6 +144,7 @@ impl Default for CoverArt { id: None, title: None, path: None, + data: None, } } } diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 8079699..525b58e 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -79,17 +79,19 @@ impl Upload { ) -> Result { self.api.endpoint = String::from("song/data/upload/with/data"); let url = self.retrieve_url(); - let client = reqwest::Client::new(); let new_song = self.initialize_song(&song, &album); let access_token = token.bearer_token(); - let song_data = song.to_data(); - let cover_data = cover.to_data(); + let song_data = song.data.clone().unwrap(); + let cover_data = cover.data.clone().unwrap(); let song_detail = new_song.to_metadata_json().unwrap(); - let mut song_raw_data: Vec = Vec::new(); - let mut cover_raw_data: Vec = Vec::new(); + let song_raw_data_as = (async { song_data.clone() }); + let cover_raw_data_as = async { cover_data.clone() }; + let song_raw_data = song_raw_data_as.await; + let cover_raw_data: Vec = cover_raw_data_as.await; + /* match song_data { Ok(sd) => { println!("song converted to data. Length {:?}", sd.len()); @@ -110,6 +112,7 @@ impl Upload { std::process::exit(-1); } } + */ if url.is_empty() { println!("Url is empty"); @@ -119,14 +122,25 @@ impl Upload { println!("Length: {:?}", song_raw_data.len()); println!("Token: {}", access_token); - let form = self.initialize_form(song_raw_data, cover_raw_data, song_detail.clone()); + let form_as = async { + self.initialize_form( + song_raw_data.clone(), + cover_raw_data.clone(), + song_detail.clone(), + ) + }; + + // let form = self.initialize_form(song_raw_data, cover_raw_data, song_detail.clone()); + let form = form_as.await; println!("Form: {:?}", form); - let response = client + // let mut client = reqwest::Client::new(); + let response = reqwest::Client::new() .post(url) .multipart(form) .header(reqwest::header::AUTHORIZATION, access_token) + .header(reqwest::header::CONTENT_TYPE, "multipart/form-data") .send() .await; let response_text = response.unwrap(); @@ -137,29 +151,31 @@ impl Upload { return Ok(response_text); } - fn initialize_form(&self, song_raw_data: Vec, cover_raw_data: Vec, song_detail: String) -> Form { + fn initialize_form( + &self, + song_raw_data: Vec, + cover_raw_data: Vec, + song_detail: String, + ) -> Form { let mut headers = HeaderMap::new(); headers.insert( http::header::CONTENT_TYPE, http::HeaderValue::from_static("application/octet-stream"), ); - let file = reqwest::multipart::Part::bytes(song_raw_data).headers(headers); + let mut file = reqwest::multipart::Part::bytes(song_raw_data).headers(headers); let mut headers_i = HeaderMap::new(); headers_i.insert( http::header::CONTENT_TYPE, http::HeaderValue::from_static("image/jpeg"), ); - let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); + let mut cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); - let mut form = Form::new(); - form = form + return reqwest::multipart::Form::new() .part("cover", cover.file_name("cover.jpeg")) .text("metadata", song_detail) .part("file", file.file_name("audio.wav")); - - return form; } pub fn set_api(&mut self, host: &String) { -- 2.47.3 From a71a33b51894d935a136c95b20adbff3d2d70d09 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 9 Jun 2024 15:32:07 -0400 Subject: [PATCH 40/47] Single target upload is functional but need to revisit multi-target upload Multi-target upload is broken now. Needs to be revisited --- Cargo.toml | 5 +- src/constants/file_extensions.rs | 3 ++ src/constants/mod.rs | 1 + src/main.rs | 1 + src/models/song.rs | 11 +++-- src/syncers/upload.rs | 82 ++++++++++++++++++-------------- 6 files changed, 60 insertions(+), 43 deletions(-) create mode 100644 src/constants/file_extensions.rs create mode 100644 src/constants/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 882ee20..4c91136 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "icarus-dm" -version = "0.1.0" +version = "0.4.0" edition = "2021" @@ -12,10 +12,7 @@ edition = "2021" futures = { version = "0.3.30" } reqwest = { version = "0.12.4", features = ["json", "blocking", "multipart", "stream"] } http = { version = "1.1.0" } -# reqwest = { version = "0.12.4", features = ["full"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.37", features = ["full"] } tokio-util = { version = "0.7.11", features = ["codec"] } -# rodio = "0.17.3" -# metadata = "0.1.8" diff --git a/src/constants/file_extensions.rs b/src/constants/file_extensions.rs new file mode 100644 index 0000000..e490697 --- /dev/null +++ b/src/constants/file_extensions.rs @@ -0,0 +1,3 @@ +pub const WAV_FILE_EXTENSION: &str = ".wav"; +pub const MP3_FILE_EXTENSION: &str = ".mp3"; +pub const JPG_FILE_EXTENSION: &str = ".jpg"; diff --git a/src/constants/mod.rs b/src/constants/mod.rs new file mode 100644 index 0000000..071d79c --- /dev/null +++ b/src/constants/mod.rs @@ -0,0 +1 @@ +pub mod file_extensions; diff --git a/src/main.rs b/src/main.rs index 721abda..abcd279 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod constants; mod managers; mod models; mod parsers; diff --git a/src/models/song.rs b/src/models/song.rs index 51184db..2a897f7 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -3,6 +3,10 @@ use std::io::Read; use serde::{Deserialize, Serialize}; +use crate::constants; + +// use crate::constants; + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { pub id: Option, @@ -95,7 +99,7 @@ impl Song { let path = self.song_path(); println!("Converting song to data"); println!("Path: {:?}", path); - // let content = std::fs::read_to_string(path); + let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; @@ -105,6 +109,7 @@ impl Song { 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(); @@ -115,9 +120,9 @@ impl Song { filename += &self.track.unwrap().to_string(); if i_type == 0 { - filename += ".mp3"; + filename += constants::file_extensions::MP3_FILE_EXTENSION; } else { - filename += ".wav"; + filename += constants::file_extensions::WAV_FILE_EXTENSION; } self.filepath = Some(filename); diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 525b58e..059bbfe 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -1,17 +1,13 @@ use std::default::Default; -use http::header; use http::HeaderMap; use http::HeaderValue; use reqwest; -use reqwest::blocking::multipart; +use reqwest::multipart::Form; use serde::{Deserialize, Serialize}; -// use reqwest::blocking:: -use reqwest::multipart::{Form, Part}; -use reqwest::Response; -use reqwest::{Body, Client}; use tokio::fs::File; +use crate::constants; use crate::models; pub struct Upload { @@ -48,6 +44,7 @@ impl Default for Upload { } impl Upload { + /* pub async fn upload_song(&self, token: &models::token::Token, song: &models::song::Song) { let url = self.retrieve_url(); let client = reqwest::Client::new(); @@ -68,6 +65,7 @@ impl Upload { } } } + */ // TODO: Implement pub async fn upload_song_with_metadata( @@ -91,29 +89,6 @@ impl Upload { let song_raw_data = song_raw_data_as.await; let cover_raw_data: Vec = cover_raw_data_as.await; - /* - match song_data { - Ok(sd) => { - println!("song converted to data. Length {:?}", sd.len()); - song_raw_data = sd; - } - Err(er) => { - println!("Error: {:?}", er); - std::process::exit(-1); - } - } - - match cover_data { - Ok(cv) => { - cover_raw_data = cv; - } - Err(er) => { - println!("Error: {:?}", er); - std::process::exit(-1); - } - } - */ - if url.is_empty() { println!("Url is empty"); } @@ -122,6 +97,7 @@ impl Upload { println!("Length: {:?}", song_raw_data.len()); println!("Token: {}", access_token); + /* let form_as = async { self.initialize_form( song_raw_data.clone(), @@ -129,18 +105,47 @@ impl Upload { song_detail.clone(), ) }; + */ // let form = self.initialize_form(song_raw_data, cover_raw_data, song_detail.clone()); - let form = form_as.await; + // let form = form_as.await; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert( + reqwest::header::AUTHORIZATION, + HeaderValue::from_str(&access_token.clone()).unwrap(), + ); + headers.insert(reqwest::header::ACCEPT, HeaderValue::from_static("*/*")); + + let songpath = song.song_path(); + let coverpath = cover.path.clone().unwrap(); + + println!("\n{}\n", song_detail); + + let mut song_filename = String::from("audio"); + song_filename += constants::file_extensions::WAV_FILE_EXTENSION; + let mut cover_filename = String::from("cover"); + cover_filename += constants::file_extensions::JPG_FILE_EXTENSION; + + let form = reqwest::multipart::Form::new() + .part( + "file", + reqwest::multipart::Part::bytes(std::fs::read(songpath)?).file_name(song_filename), + ) + .part( + "cover", + reqwest::multipart::Part::bytes(std::fs::read(coverpath)?) + .file_name(cover_filename), + ) + .text("metadata", song_detail); println!("Form: {:?}", form); - // let mut client = reqwest::Client::new(); - let response = reqwest::Client::new() + let client = reqwest::Client::builder().build().unwrap(); + let response = client .post(url) + .headers(headers) .multipart(form) - .header(reqwest::header::AUTHORIZATION, access_token) - .header(reqwest::header::CONTENT_TYPE, "multipart/form-data") .send() .await; let response_text = response.unwrap(); @@ -172,10 +177,15 @@ impl Upload { let mut cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); + let mut song_filename = String::from("audio"); + song_filename += constants::file_extensions::WAV_FILE_EXTENSION; + let mut cover_filename = String::from("cover"); + cover_filename += constants::file_extensions::JPG_FILE_EXTENSION; + return reqwest::multipart::Form::new() - .part("cover", cover.file_name("cover.jpeg")) + .part("cover", cover.file_name(cover_filename)) .text("metadata", song_detail) - .part("file", file.file_name("audio.wav")); + .part("file", file.file_name(song_filename)); } pub fn set_api(&mut self, host: &String) { -- 2.47.3 From 6c932628f608e64bd8e40649e2ee07192e58c3e3 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 9 Jun 2024 19:35:35 -0400 Subject: [PATCH 41/47] Fixed multi target upload --- src/managers/commit_manager.rs | 45 ++++++------------ src/syncers/upload.rs | 83 ++++++++++++++-------------------- 2 files changed, 49 insertions(+), 79 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 35bbb55..2afeabb 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -167,10 +167,9 @@ impl CommitManager { println!("Deleting song"); } - // TODO: Implement - // NOTE: Might not need to implement. I will see how this goes fn upload_song(&self) { println!("Deleting song"); + panic!("Not supported"); } fn parse_token(&self, api: &models::api::API) -> models::token::Token { @@ -198,7 +197,6 @@ impl CommitManager { return token.unwrap(); } - // TODO: Implement fn upload_song_with_metadata(&mut self) { println!("Uplodaring song with metadara"); @@ -234,7 +232,6 @@ impl CommitManager { } } - // TODO: Implement fn sing_target_upload( &mut self, songpath: &String, @@ -264,32 +261,16 @@ impl CommitManager { let mut fp = String::new(); let mut dir = String::new(); - // song_file.file_name(); - - // for entry in read_dir(song_file)? { - // for entry in read_file(song_file)? { let entry = &song_file; - // let file_type = entry.file_type(); let file_name = std::ffi::OsString::from(entry.file_name().unwrap()); - // println!("file type: {:?}", file_type); println!("file name: {:?}", file_name); match self.find_file_extension(&file_name) { - En::ImageFile => { - // let directory_part = sourcepath.clone(); - // let fname = self.o_to_string(&file_name); - // let fullpath = directory_part + "/" + &fname.unwrap(); - // cover_art.path = Some(fullpath); - } - En::MetadataFile => { - // let directory_part = sourcepath.clone(); - // let fname = self.o_to_string(&file_name); - // metadatapath = directory_part + "/" + &fname.unwrap(); - } + En::ImageFile => {} + En::MetadataFile => {} En::SongFile => { - // let mut song = models::song::Song::default(); let fname = self.o_to_string(&file_name); match fname { @@ -303,17 +284,13 @@ impl CommitManager { } Err(er) => println!("Error: {:?}", er), } - - // songs.push(song) } _ => {} } - // } cover_art.path = Some(cover_path.clone()); - let mut album = self.retrieve_metadata(&meta_path); - // self.song_parsing(&mut album, &song.directory.unwrap(), &filenames); + 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.filepath = Some(fp); @@ -343,7 +320,7 @@ impl CommitManager { Ok(()) } - // TODO: Implement + fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> { let mut prsr = parsers::api_parser::APIParser { api: models::api::API::default(), @@ -356,8 +333,7 @@ impl CommitManager { let directory_path = std::path::Path::new(&sourcepath); if !directory_path.exists() { - println!("Directory does not exist"); - std::process::exit(-1); + panic!("Directory does not exist"); } let mut cover_art = models::song::CoverArt::default(); @@ -424,6 +400,15 @@ impl CommitManager { 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..."); diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 059bbfe..84c5d0d 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -27,6 +27,8 @@ struct Song { track_count: i32, disc: i32, disc_count: i32, + #[serde(skip_serializing)] + songpath: String, } impl Song { @@ -67,7 +69,6 @@ impl Upload { } */ - // TODO: Implement pub async fn upload_song_with_metadata( &mut self, token: &models::token::Token, @@ -77,39 +78,17 @@ impl Upload { ) -> Result { self.api.endpoint = String::from("song/data/upload/with/data"); let url = self.retrieve_url(); - let new_song = self.initialize_song(&song, &album); + let mut new_song = self.initialize_song(&song, &album); + new_song.songpath = song.song_path(); let access_token = token.bearer_token(); - let song_data = song.data.clone().unwrap(); - let cover_data = cover.data.clone().unwrap(); - let song_detail = new_song.to_metadata_json().unwrap(); - - let song_raw_data_as = (async { song_data.clone() }); - let cover_raw_data_as = async { cover_data.clone() }; - let song_raw_data = song_raw_data_as.await; - let cover_raw_data: Vec = cover_raw_data_as.await; - if url.is_empty() { println!("Url is empty"); } println!("Url: {}", url); - println!("Length: {:?}", song_raw_data.len()); println!("Token: {}", access_token); - /* - let form_as = async { - self.initialize_form( - song_raw_data.clone(), - cover_raw_data.clone(), - song_detail.clone(), - ) - }; - */ - - // let form = self.initialize_form(song_raw_data, cover_raw_data, song_detail.clone()); - // let form = form_as.await; - let mut headers = reqwest::header::HeaderMap::new(); headers.insert( reqwest::header::AUTHORIZATION, @@ -117,30 +96,7 @@ impl Upload { ); headers.insert(reqwest::header::ACCEPT, HeaderValue::from_static("*/*")); - let songpath = song.song_path(); - let coverpath = cover.path.clone().unwrap(); - - println!("\n{}\n", song_detail); - - let mut song_filename = String::from("audio"); - song_filename += constants::file_extensions::WAV_FILE_EXTENSION; - let mut cover_filename = String::from("cover"); - cover_filename += constants::file_extensions::JPG_FILE_EXTENSION; - - let form = reqwest::multipart::Form::new() - .part( - "file", - reqwest::multipart::Part::bytes(std::fs::read(songpath)?).file_name(song_filename), - ) - .part( - "cover", - reqwest::multipart::Part::bytes(std::fs::read(coverpath)?) - .file_name(cover_filename), - ) - .text("metadata", song_detail); - - println!("Form: {:?}", form); - + let form = self.init_form(&new_song, &cover); let client = reqwest::Client::builder().build().unwrap(); let response = client .post(url) @@ -188,6 +144,34 @@ impl Upload { .part("file", file.file_name(song_filename)); } + fn init_form(&self, song: &Song, cover: &models::song::CoverArt) -> reqwest::multipart::Form { + let songpath = song.songpath.clone(); + let coverpath = cover.path.clone().unwrap(); + let song_detail = song.to_metadata_json().unwrap(); + + println!("\n{}\n", song_detail); + + let mut song_filename = String::from("audio"); + song_filename += constants::file_extensions::WAV_FILE_EXTENSION; + let mut cover_filename = String::from("cover"); + cover_filename += constants::file_extensions::JPG_FILE_EXTENSION; + + let form = reqwest::multipart::Form::new() + .part( + "file", + reqwest::multipart::Part::bytes(std::fs::read(songpath).unwrap()) + .file_name(song_filename), + ) + .part( + "cover", + reqwest::multipart::Part::bytes(std::fs::read(coverpath).unwrap()) + .file_name(cover_filename), + ) + .text("metadata", song_detail); + + return form; + } + pub fn set_api(&mut self, host: &String) { let mut api = models::api::API::default(); api.url = host.clone(); @@ -229,6 +213,7 @@ impl Upload { track_count: album.track_count.clone(), disc: song.disc.clone().unwrap(), disc_count: album.disc_count.clone(), + songpath: String::new(), }; } } -- 2.47.3 From 9a13ac27769fe1cbd4f85260ea01e7c26bb9f399 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 9 Jun 2024 19:52:42 -0400 Subject: [PATCH 42/47] Can now retrieve songs --- src/managers/commit_manager.rs | 28 ++++++++++++++++++++++++++++ src/syncers/retrieve_records.rs | 18 ++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 2afeabb..9c808bb 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -165,6 +165,34 @@ impl CommitManager { // TODO: Implement fn retrieve_object(&self) { println!("Deleting song"); + let rt = self.ica_action.retrieve_flag_value(&String::from("-rt")); + + if rt != "songs" { + panic!("Unsupported -rt: {}", rt); + } + + let mut prsr = parsers::api_parser::APIParser { + api: models::api::API::default(), + ica_act: self.ica_action.clone(), + }; + prsr.parse_api(); + + let api = prsr.retrieve_api(); + let token = self.parse_token(&api); + 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 { + Ok(o) => { + for song in o { + println!("{:?} - {:?}", song.artist, song.title); + } + } + Err(er) => { + println!("Error: {:?}", er); + } + } } fn upload_song(&self) { diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index 2cf1637..7fb3162 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -19,13 +19,25 @@ impl Default for RetrieveRecords { impl RetrieveRecords { pub async fn get_all_songs( - &self, + &mut self, token: &models::token::Token, ) -> Result, Error> { + self.api.endpoint = String::from("song"); let mut songs: Vec = Vec::new(); let url = self.retrieve_url(); let access_token = token.bearer_token(); - let client = reqwest::Client::new(); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert( + reqwest::header::AUTHORIZATION, + http::header::HeaderValue::from_str(&access_token.clone()).unwrap(), + ); + headers.insert( + reqwest::header::CONTENT_TYPE, + http::header::HeaderValue::from_static("application/json"), + ); + + let client = reqwest::Client::builder().build().unwrap(); let response = client .get(&url) .header(reqwest::header::AUTHORIZATION, access_token) @@ -57,7 +69,6 @@ impl RetrieveRecords { } fn retrieve_url(&self) -> String { - // let mut url: String = String::new(); let api = &self.api; let mut url: String = String::from(&api.url); url += &String::from("api/"); @@ -65,7 +76,6 @@ impl RetrieveRecords { url += &String::from("/"); url += &String::from(&api.endpoint); url += &String::from("/"); - // url += &song.id.unwrap().to_string(); return url; } -- 2.47.3 From 4334d6be7b32b9cf8884812c1951ded05a535742 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 9 Jun 2024 20:46:14 -0400 Subject: [PATCH 43/47] Downloading functionality is working --- src/managers/commit_manager.rs | 36 +++++++++++++++++++++++++---- src/syncers/download.rs | 42 ++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index 9c808bb..d280713 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::default::Default; use std::fmt::Display; use std::fs::{read_dir, DirEntry}; -use std::io::{Error, Read, Result}; +use std::io::{Error, Read, Result, Write}; use std::path::Path; use std::str::FromStr; @@ -12,9 +12,9 @@ use tokio::runtime::Runtime; use crate::models::song::Album; use crate::models::{self, song}; -use crate::parsers; use crate::syncers; use crate::utilities; +use crate::{constants, parsers}; use crate::{exit_program, managers}; #[derive(Debug, Deserialize, Serialize)] @@ -157,12 +157,40 @@ impl CommitManager { del.delete_song(&token, &song); } - // TODO: Implement fn download_song(&self) { println!("Deleting song"); + let dwn = self.ica_action.retrieve_flag_value(&String::from("-b")); + let num: i32 = dwn.parse::().unwrap(); + + let mut prsr = parsers::api_parser::APIParser { + api: models::api::API::default(), + ica_act: self.ica_action.clone(), + }; + prsr.parse_api(); + + let api = prsr.retrieve_api(); + let token = self.parse_token(&api); + + let mut dwn_loader = syncers::download::Download { api: api.clone() }; + let mut song = models::song::Song::default(); + song.id = Some(num); + let result_fut = dwn_loader.download_song(&token, &song); + let result = Runtime::new().unwrap().block_on(result_fut); + match result { + Ok(o) => { + println!("Success"); + let mut filename = String::from("audio"); + filename += constants::file_extensions::WAV_FILE_EXTENSION; + let data = o.as_bytes(); + let mut file = std::fs::File::create(filename).expect("Failed to save"); + file.write_all(&data).expect("ff"); + } + Err(er) => { + println!("Error {:?}", er); + } + } } - // TODO: Implement fn retrieve_object(&self) { println!("Deleting song"); let rt = self.ica_action.retrieve_flag_value(&String::from("-rt")); diff --git a/src/syncers/download.rs b/src/syncers/download.rs index f7e2277..4282e0a 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -14,11 +14,29 @@ impl Default for Download { } } +#[derive(Debug)] +pub enum MyError { + Request(reqwest::Error), + Other(String), +} + impl Download { - pub async fn download_song(&self, token: &models::token::Token, song: &models::song::Song) { + pub async fn download_song( + &mut self, + token: &models::token::Token, + song: &models::song::Song, + ) -> Result { + self.api.endpoint = String::from("song/data/download"); let url = self.retrieve_url(&song); let access_token = token.bearer_token(); - let client = reqwest::Client::new(); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert( + reqwest::header::AUTHORIZATION, + http::header::HeaderValue::from_str(&access_token.clone()).unwrap(), + ); + + let client = reqwest::Client::builder().build().unwrap(); let response = client .get(&url) .header(reqwest::header::AUTHORIZATION, &access_token) @@ -28,16 +46,15 @@ impl Download { match response.status() { reqwest::StatusCode::OK => { - // on success, parse our JSON to an APIResponse - /* - let s = response.json::>().await; - match s { - Ok(parsed) => { - println!("\nSuccess!"); + let data = response.text(); + match data.await { + Ok(e) => { + return Ok(e); } - Err(_) => println!("Hm, the response didn't match the shape we expected."), - }; - */ + Err(er) => { + println!("Error {:?}", er); + } + } } reqwest::StatusCode::UNAUTHORIZED => { println!("Need to grab a new token"); @@ -46,10 +63,11 @@ impl Download { panic!("Uh oh! Something unexpected happened: {:?}", other); } } + + return Err(MyError::Other(String::from("Error downloading"))); } fn retrieve_url(&self, song: &models::song::Song) -> String { - // let mut url: String = String::new(); let api = &self.api; let mut url: String = String::from(&api.url); url += &String::from("api/"); -- 2.47.3 From 188a81beca7d105fc997c749be47884e93da19e6 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 11 Jun 2024 20:09:16 -0400 Subject: [PATCH 44/47] Delete functionality is operational --- Cargo.toml | 2 +- README.md | 63 ++++++++++---------------------- src/constants/file_extensions.rs | 2 +- src/main.rs | 7 ---- src/managers/action_managers.rs | 4 +- src/managers/commit_manager.rs | 45 +++++++++++++---------- src/managers/token_manager.rs | 11 ++---- src/managers/user_manager.rs | 2 +- src/models/song.rs | 7 ++-- src/models/user.rs | 2 +- src/parsers/api_parser.rs | 6 +-- src/syncers/delete.rs | 29 ++++++++++----- src/syncers/download.rs | 2 +- src/syncers/mod.rs | 1 - src/syncers/retrieve_records.rs | 2 - src/syncers/syncer_base.rs | 28 -------------- src/syncers/upload.rs | 7 ++-- src/utilities/checks.rs | 17 ++++----- src/utilities/conversions.rs | 6 +-- 19 files changed, 93 insertions(+), 150 deletions(-) delete mode 100644 src/syncers/syncer_base.rs diff --git a/Cargo.toml b/Cargo.toml index 4c91136..4f4458b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ edition = "2021" [dependencies] futures = { version = "0.3.30" } -reqwest = { version = "0.12.4", features = ["json", "blocking", "multipart", "stream"] } http = { version = "1.1.0" } +reqwest = { version = "0.12.4", features = ["json", "blocking", "multipart", "stream"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.37", features = ["full"] } diff --git a/README.md b/README.md index 6eb57d6..212eb62 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,67 @@ # IcarusDownloadManager -IcarusDownloadManager is a Linux CLI software client application that has the feature of uploading and downloading songs from the [Icarus](https://github.com/kdeng00/Icarus) Music Server. +IcarusDownloadManager is a CLI software client application that has the feature of uploading and downloading songs from the [Icarus](https://github.com/kdeng00/Icarus) Music Server. ## Built With -* C++ with C++20 features -* CMake -* GCC >= 10 or Visual Studio >= 17 [2022] -* [vcpkg](https://github.com/microsoft/vcpkg) -* [json](https://github.com/nlohmann/json) -* [openssl](https://github.com/openssl/openssl) -* [curl](https://github.com/curl/curl) -* [cpr](https://github.com/libcpr/cpr) +* Rust +* Cargo +* futures +* http +* reqwst +* serde +* serde_json +* tokio +* tokio-util ### Getting Started Clone the repo -``` +```BASH git clone --recursive https://github.com/kdeng00/IcarusDownloadManager ``` -Install packages - -``` -vcpkg install nlohman-json -vcpkg install openssl -vcpkg install curl -vcpkg install cpr -``` - Build the project: -``` +```BASH cd IcarusDownloadManager -mkdir build -cd build - -cmake .. -cmake --build . --config release -j +cargo build ``` -The program has been built and can be executed by the binary file *icd*. For information on how to use icd, merely execute the program without any command line arguments. +The program has been built and can be executed by the binary file *icarus-dm*. For information on how to use icarua-dm, merely execute the program without any command line arguments. ### Downloading Song ```BASH -icd download -u spacecadet -p stellar40 -h https://icarus.com -b 15 -``` - -### Uploading Song - -```BASH -icd upload -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3 +icarus-dm download -u spacecadet -p stellar40 -h https://icarus.com -b 15 ``` ### Uploading Song with metadata ```BASH -icd upload-meta -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3 -t 1 -m /path/to/metadata/config/collection.json -ca /path/to/cover/art/image.png +icarus-dm upload-meta -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3 -t 1 -m /path/to/metadata/config/collection.json -ca /path/to/cover/art/image.png ``` ### Uploading Song with metadata from directory ```BASH -icd upload-meta -u spacecadet -p stellar40 -h https://icarus.com -smca /path/where/songs/and/metadata/exists/ +icarus-dm upload-meta -u spacecadet -p stellar40 -h https://icarus.com -smca /path/where/songs/and/metadata/exists/ ``` - ### Retrieving Song in json ```Bash -icd retrieve -u spacecadet -p stellar40 -h https://icarus.com -rt songs +icarus-dm retrieve -u spacecadet -p stellar40 -h https://icarus.com -rt songs ``` ### Deleting Song ```BASH -icd delete -u spacecadet -p stellar40 -h https://icarus.com -D 15 +icarus-dm delete -u spacecadet -p stellar40 -h https://icarus.com -D 15 ``` @@ -97,12 +78,6 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduc [v0.1.1](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.1.1) [v0.1.0](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/0.1.0) -## Authors - -* **Kun Deng** - [kdeng00](https://github.com/kdeng00) - -See also the list of [contributors](https://github.com/kdeng00/Icarus/graphs/contributors) who participated in this project. - ## License This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details diff --git a/src/constants/file_extensions.rs b/src/constants/file_extensions.rs index e490697..edf058e 100644 --- a/src/constants/file_extensions.rs +++ b/src/constants/file_extensions.rs @@ -1,3 +1,3 @@ pub const WAV_FILE_EXTENSION: &str = ".wav"; -pub const MP3_FILE_EXTENSION: &str = ".mp3"; +pub const _MP3_FILE_EXTENSION: &str = ".mp3"; pub const JPG_FILE_EXTENSION: &str = ".jpg"; diff --git a/src/main.rs b/src/main.rs index abcd279..1b90844 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,6 @@ fn print_help() { Actions download - upload (Search NOTE) upload-meta retrieve delete @@ -29,12 +28,6 @@ fn print_help() { -p password -h host - Required for upload - -s path of song - -sd directory where to search for songs to upload (Optional) - -sr directory where to recursively search for songs to upload (Optional) - -nc will not prompt the user when uploading from a directory - Required for upload with metadata -s path of song -t track number diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 6c7bb51..68d52b4 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -124,7 +124,7 @@ impl ActionManager { } } - fn print_action(&self) { + fn _print_action(&self) { if self.action.len() == 0 { println!("Action is empty"); } else { @@ -132,7 +132,7 @@ impl ActionManager { } } - fn print_flags(&self) { + fn _print_flags(&self) { println!("Printing flags..."); for flag in &self.flags { println!("Flag {}", flag.flag); diff --git a/src/managers/commit_manager.rs b/src/managers/commit_manager.rs index d280713..400f0a3 100644 --- a/src/managers/commit_manager.rs +++ b/src/managers/commit_manager.rs @@ -1,21 +1,18 @@ use std::collections::HashMap; use std::default::Default; -use std::fmt::Display; -use std::fs::{read_dir, DirEntry}; -use std::io::{Error, Read, Result, Write}; -use std::path::Path; +use std::fs::read_dir; +use std::io::{Result, Write}; use std::str::FromStr; -use futures::{FutureExt, TryFutureExt}; use serde::{Deserialize, Serialize}; use tokio::runtime::Runtime; +use crate::managers; use crate::models::song::Album; -use crate::models::{self, song}; +use crate::models::{self}; use crate::syncers; use crate::utilities; use crate::{constants, parsers}; -use crate::{exit_program, managers}; #[derive(Debug, Deserialize, Serialize)] pub struct CommitManager { @@ -32,7 +29,7 @@ enum ActionValues { None, } -enum RetrieveTypes { +enum _RetrieveTypes { Songs, } @@ -45,7 +42,7 @@ enum En { } impl Album { - pub fn print_info(&self) { + pub fn _print_info(&self) { println!("Album: {}", self.title); println!("Album Artist: {}", self.album_artist); println!("Genre: {}", self.genre); @@ -126,7 +123,6 @@ impl CommitManager { return actions; } - // TODO: Implement fn delete_song(&self) { let mut prsr = parsers::api_parser::APIParser { ica_act: self.ica_action.clone(), @@ -150,11 +146,20 @@ impl CommitManager { } } - let del = syncers::delete::Delete { api: api }; + let mut del = syncers::delete::Delete { api: api.clone() }; println!("Deleting song.."); - del.delete_song(&token, &song); + let res_fut = del.delete_song(&token, &song); + let result = Runtime::new().unwrap().block_on(res_fut); + match result { + Ok(o) => { + println!("Song (Id {:?}) has been successfully deleted", o.id); + } + Err(er) => { + println!("Error {:?}", er); + } + } } fn download_song(&self) { @@ -213,8 +218,8 @@ impl CommitManager { let result = Runtime::new().unwrap().block_on(result_fut); match result { Ok(o) => { - for song in o { - println!("{:?} - {:?}", song.artist, song.title); + for son in o { + son.print_info(); } } Err(er) => { @@ -280,9 +285,9 @@ impl CommitManager { println!("metadata path: {}", metadata_path); println!("cover art path: {}", coverpath); - self.sing_target_upload(&songpath, &track_id, &metadata_path, &coverpath); + let _ = self.sing_target_upload(&songpath, &track_id, &metadata_path, &coverpath); } else if multitarget { - self.multi_target_upload(&uni); + let _ = self.multi_target_upload(&uni); } else { println!("Single or Multi target has not been chosen"); } @@ -681,8 +686,8 @@ impl CommitManager { song.track = Some(track); } - fn parse_disc_and_track(&self, song: &mut models::song::Song, track_id: &String) { - let sep = |a: &char, b: &char| -> bool { + fn _parse_disc_and_track(&self, song: &mut models::song::Song, track_id: &String) { + let sep = |_a: &char, _b: &char| -> bool { return false; }; @@ -690,7 +695,7 @@ impl CommitManager { if index == -1 { let mut d_str: String = String::new(); - let mut t_str = String::new(); + let t_str = String::new(); for c in track_id.chars().skip(0).take(index as usize) { d_str.push(c); @@ -712,7 +717,7 @@ impl CommitManager { } } - fn check_for_no_confirm(&self) -> bool { + fn _check_for_no_confirm(&self) -> bool { for flag in self.ica_action.flags.iter() { if flag.flag == "-nc" { return true; diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index b256f3b..48689c8 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -24,9 +24,7 @@ impl TokenManager { pub async fn request_token(&self) -> Result { println!("Sending request for a token"); - // let endpoint = self.construct_endpoint(); - let mut url = self.retrieve_url(); - // url += &endpoint; + let url = self.retrieve_url(); println!("URL: {}", url); @@ -59,7 +57,7 @@ impl TokenManager { } pub fn init(&mut self) { - let mut api = &mut self.api; + let api = &mut self.api; api.version = String::from("v1"); api.endpoint = String::from(format!("api/{}/login", api.version)); } @@ -67,9 +65,6 @@ impl TokenManager { pub fn retrieve_url(&self) -> String { let api = &self.api; let mut url = String::from(&api.url); - // url += &String::from("api/"); - // url += &String::from(&api.version); - // url += &String::from("/"); url += &String::from(&api.endpoint); url += &String::from("/"); @@ -77,7 +72,7 @@ impl TokenManager { } // NOTE: This can get deleted. Redundant - fn construct_endpoint(&self) -> String { + fn _construct_endpoint(&self) -> String { let mut endpoint: String = String::from("api/"); endpoint += &self.api.version; endpoint += "/login"; diff --git a/src/managers/user_manager.rs b/src/managers/user_manager.rs index 44ff366..61607e2 100644 --- a/src/managers/user_manager.rs +++ b/src/managers/user_manager.rs @@ -2,7 +2,7 @@ use std::default::Default; use serde::{Deserialize, Serialize}; -use crate::models::{self, user::User}; +use crate::models::{self}; #[derive(Debug, Deserialize, Serialize)] pub struct UserManager { diff --git a/src/models/song.rs b/src/models/song.rs index 2a897f7..068010a 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -9,6 +9,7 @@ use crate::constants; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { + #[serde(alias = "song_id")] pub id: Option, pub title: Option, pub artist: Option, @@ -111,7 +112,7 @@ impl Song { } // if 1 - wav, if 0 - mp3, anything else defaults to wav - pub fn generate_filename_from_track(&mut self, i_type: i32) -> i32 { + 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"; @@ -120,7 +121,7 @@ impl Song { filename += &self.track.unwrap().to_string(); if i_type == 0 { - filename += constants::file_extensions::MP3_FILE_EXTENSION; + filename += constants::file_extensions::_MP3_FILE_EXTENSION; } else { filename += constants::file_extensions::WAV_FILE_EXTENSION; } @@ -130,7 +131,7 @@ impl Song { return 0; } - pub fn to_metadata_json(&self) -> Result { + pub fn _to_metadata_json(&self) -> Result { return serde_json::to_string_pretty(&self); } } diff --git a/src/models/user.rs b/src/models/user.rs index d788787..46a37c0 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -18,7 +18,7 @@ impl Default for User { } impl User { - pub fn to_json(&self) -> Result { + pub fn _to_json(&self) -> Result { return serde_json::to_string_pretty(&self); } } diff --git a/src/parsers/api_parser.rs b/src/parsers/api_parser.rs index 790c3b7..7a8396f 100644 --- a/src/parsers/api_parser.rs +++ b/src/parsers/api_parser.rs @@ -15,22 +15,18 @@ impl APIParser { let flags = self.ica_act.flags.clone(); println!("Parsing api"); - let mut i = 0; - // for (i, elem) in flags { for elem in flags { let arg = elem.flag; let value = elem.value; if arg == "-h" { - if value.chars().nth((value.len() - 1)) == Some('/') { + if value.chars().nth(value.len() - 1) == Some('/') { self.api.url = value; } else { self.api.url = value + "/"; } break; } - - i += 1; } self.api.version = "v1".to_string(); diff --git a/src/syncers/delete.rs b/src/syncers/delete.rs index 9f1df55..8ae73f2 100644 --- a/src/syncers/delete.rs +++ b/src/syncers/delete.rs @@ -1,16 +1,9 @@ use std::default::Default; -use std::io::Error; use reqwest; -use reqwest::Response; -use serde; -// use serde::Deserialize; -// use serde::Serialize; use crate::models; -use super::syncer_base; - #[derive(Clone, Debug)] pub struct Delete { pub api: models::api::API, @@ -25,9 +18,14 @@ impl Default for Delete { } impl Delete { - pub async fn delete_song(&self, token: &models::token::Token, song: &models::song::Song) { + pub async fn delete_song( + &mut self, + token: &models::token::Token, + song: &models::song::Song, + ) -> Result { + self.api.endpoint = "song/data/delete".to_owned(); let url = self.retrieve_url(&song); - let client = reqwest::Client::new(); + let client = reqwest::Client::builder().build().unwrap(); let access_token = token.bearer_token(); let response = client .delete(&url) @@ -35,15 +33,28 @@ impl Delete { .send() .await .unwrap(); + let mut sng = models::song::Song::default(); match response.status() { reqwest::StatusCode::OK => { println!("Success!"); + let s = response.json::().await; + match s { + // + Ok(parsed) => { + sng = parsed; + } + Err(er) => { + println!("Error {:?}", er); + } + }; } other => { panic!("Issue occurred: {:?}", other); } } + + return Ok(sng); } fn retrieve_url(&self, song: &models::song::Song) -> String { diff --git a/src/syncers/download.rs b/src/syncers/download.rs index 4282e0a..39f0c12 100644 --- a/src/syncers/download.rs +++ b/src/syncers/download.rs @@ -16,7 +16,7 @@ impl Default for Download { #[derive(Debug)] pub enum MyError { - Request(reqwest::Error), + _Request(reqwest::Error), Other(String), } diff --git a/src/syncers/mod.rs b/src/syncers/mod.rs index 29f57f6..cb8e326 100644 --- a/src/syncers/mod.rs +++ b/src/syncers/mod.rs @@ -1,5 +1,4 @@ pub mod delete; pub mod download; pub mod retrieve_records; -pub mod syncer_base; pub mod upload; diff --git a/src/syncers/retrieve_records.rs b/src/syncers/retrieve_records.rs index 7fb3162..b312cb4 100644 --- a/src/syncers/retrieve_records.rs +++ b/src/syncers/retrieve_records.rs @@ -3,8 +3,6 @@ use std::io::Error; use crate::models; -// use super::syncer_base::Result; - pub struct RetrieveRecords { pub api: models::api::API, } diff --git a/src/syncers/syncer_base.rs b/src/syncers/syncer_base.rs deleted file mode 100644 index 6f8144f..0000000 --- a/src/syncers/syncer_base.rs +++ /dev/null @@ -1,28 +0,0 @@ -// use crate::models; - -pub struct Syncer { - // pub api: models::api::API, - ok: i32, - unauthorized: i32, - not_found: i32, -} - -impl Syncer { - pub fn ok() -> i32 { - return 200; - } - - pub fn unauthorized() -> i32 { - return 401; - } - - pub fn not_found() -> i32 { - return 404; - } -} - -pub enum Result { - OK, - UNAUTHORIZED, - NOTFOUND, -} diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 84c5d0d..8c9a240 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -5,7 +5,6 @@ use http::HeaderValue; use reqwest; use reqwest::multipart::Form; use serde::{Deserialize, Serialize}; -use tokio::fs::File; use crate::constants; use crate::models; @@ -112,7 +111,7 @@ impl Upload { return Ok(response_text); } - fn initialize_form( + fn _initialize_form( &self, song_raw_data: Vec, cover_raw_data: Vec, @@ -124,14 +123,14 @@ impl Upload { http::HeaderValue::from_static("application/octet-stream"), ); - let mut file = reqwest::multipart::Part::bytes(song_raw_data).headers(headers); + let file = reqwest::multipart::Part::bytes(song_raw_data).headers(headers); let mut headers_i = HeaderMap::new(); headers_i.insert( http::header::CONTENT_TYPE, http::HeaderValue::from_static("image/jpeg"), ); - let mut cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); + let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); let mut song_filename = String::from("audio"); song_filename += constants::file_extensions::WAV_FILE_EXTENSION; diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 42bd519..48f97c4 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -9,24 +9,23 @@ impl Checks { } // TODO: Implement - pub fn item_in_container( - container: &Vec, - item: &String, - func: fn(a: &String, b: &String) -> String, + pub fn _item_in_container( + _container: &Vec, + _item: &String, + _func: fn(a: &String, b: &String) -> String, ) -> String { return String::from(""); } // TODO: Implement - pub fn item_iter_in_container( - container: &Vec, - item: &String, - func: fn(a: &String, b: &String) -> String, + pub fn _item_iter_in_container( + _container: &Vec, + _item: &String, + _func: fn(a: &String, b: &String) -> String, ) -> String { return String::from(""); } - // TODO: Implement pub fn index_of_item_in_container(container: &String, item: &char, func: F) -> i32 where F: Fn(&char, &char) -> bool, diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs index 53493d1..d404723 100644 --- a/src/utilities/conversions.rs +++ b/src/utilities/conversions.rs @@ -4,15 +4,15 @@ use serde::{Deserialize, Serialize}; pub struct Conversions {} impl Conversions { - pub fn to_lower_char(val: &mut char) { + pub fn _to_lower_char(val: &mut char) { if val.is_alphabetic() { *val = val.to_lowercase().next().unwrap(); } } - pub fn initialize_values(&self) {} + pub fn _initialize_values(&self) {} - pub fn print_value(&self, val: T) { + pub fn _print_value(&self, val: T) { println!("Going to print value"); println!("{:?}", val); } -- 2.47.3 From be107cc0ad2beebe00bbce191dbf1f5865bc5de9 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 12 Jun 2024 20:01:59 -0400 Subject: [PATCH 45/47] Updated README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 212eb62..6e9f2c5 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduc ## Versioning +[v0.4.0](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.4.0) [v0.3.2](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.3.2) [v0.3.0](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.3.0) [v0.2.0](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.2.0) -- 2.47.3 From 52c22d831972c6eb25548dc47217390e2e2f8692 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 15 Jun 2024 11:24:55 -0400 Subject: [PATCH 46/47] More cleanup --- src/main.rs | 2 +- src/managers/file_manager.rs | 25 +++++++++++++++---------- src/managers/token_manager.rs | 9 --------- src/models/api.rs | 6 +++--- src/models/song.rs | 3 --- src/syncers/upload.rs | 23 ----------------------- src/utilities/checks.rs | 18 ------------------ src/utilities/conversions.rs | 19 ------------------- src/utilities/mod.rs | 1 - 9 files changed, 19 insertions(+), 87 deletions(-) delete mode 100644 src/utilities/conversions.rs diff --git a/src/main.rs b/src/main.rs index 1b90844..68c11ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,7 +62,7 @@ fn main() { println!("Argument count: {}", args_len); let mut act_mgr = managers::action_managers::ActionManager { - action: String::from(""), + action: String::new(), flags: Vec::new(), params: args, param_count: args_len, diff --git a/src/managers/file_manager.rs b/src/managers/file_manager.rs index 4f28b46..b76a4f4 100644 --- a/src/managers/file_manager.rs +++ b/src/managers/file_manager.rs @@ -21,21 +21,23 @@ impl Default for FileManager { impl FileManager { -// TODO: Implement -pub fn init(&mut self) { - self.read_file() -} + // TODO: Implement + pub fn init(&mut self) { + self.read_file() + } + pub fn save_file(&mut self, filepath: &String) { if !self.file_read { self.read_file(); } - let mut file = File::open(filepath)?; - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer)?; + let mut file = File::open(filepath)?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; self.file_buffer_length = buffer.len(); - self.filebuffer = String::from_utf8(buffer); // Assuming UTF-8 encoding + self.filebuffer = String::from_utf8(buffer); // Assuming UTF-8 encoding } + pub fn modify_file_path(&mut self, file: &String) { self.filepath = file; } @@ -48,12 +50,15 @@ pub fn init(&mut self) { self.file_buffer_length; } - fn read_file(&mut self) { + fn read_file(&mut self) -> Vec { let mut file = File::open(self.filepath)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; self.file_buffer_length = buffer.len(); self.filebuffer = String::from_utf8(buffer); // Assuming UTF-8 encoding self.file_read = true; + + return buffer; } -} \ No newline at end of file +} + diff --git a/src/managers/token_manager.rs b/src/managers/token_manager.rs index 48689c8..8ba8a1d 100644 --- a/src/managers/token_manager.rs +++ b/src/managers/token_manager.rs @@ -70,13 +70,4 @@ impl TokenManager { return url; } - - // NOTE: This can get deleted. Redundant - fn _construct_endpoint(&self) -> String { - let mut endpoint: String = String::from("api/"); - endpoint += &self.api.version; - endpoint += "/login"; - - return endpoint; - } } diff --git a/src/models/api.rs b/src/models/api.rs index d8665f1..aeb9269 100644 --- a/src/models/api.rs +++ b/src/models/api.rs @@ -12,9 +12,9 @@ pub struct API { impl Default for API { fn default() -> Self { API { - url: String::from(""), - endpoint: String::from(""), - version: String::from(""), + url: String::new(), + endpoint: String::new(), + version: String::new(), } } } diff --git a/src/models/song.rs b/src/models/song.rs index 068010a..e5ab5c8 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; use crate::constants; -// use crate::constants; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { @@ -20,8 +19,6 @@ pub struct Song { pub track: Option, pub disc: Option, pub data: Option>, - // use filepath instead - // pub song_path: String, pub filepath: Option, pub directory: Option, } diff --git a/src/syncers/upload.rs b/src/syncers/upload.rs index 8c9a240..bb8b65b 100644 --- a/src/syncers/upload.rs +++ b/src/syncers/upload.rs @@ -45,29 +45,6 @@ impl Default for Upload { } impl Upload { - /* - pub async fn upload_song(&self, token: &models::token::Token, song: &models::song::Song) { - let url = self.retrieve_url(); - let client = reqwest::Client::new(); - let access_token = token.bearer_token(); - let response = client - .post(&url) - .header(reqwest::header::AUTHORIZATION, access_token) - .send() - .await - .unwrap(); - - match response.status() { - reqwest::StatusCode::OK => { - println!("Success!"); - } - other => { - panic!("Issue occurred: {:?}", other); - } - } - } - */ - pub async fn upload_song_with_metadata( &mut self, token: &models::token::Token, diff --git a/src/utilities/checks.rs b/src/utilities/checks.rs index 48f97c4..96537ad 100644 --- a/src/utilities/checks.rs +++ b/src/utilities/checks.rs @@ -8,24 +8,6 @@ impl Checks { text.parse::().is_ok() } - // TODO: Implement - pub fn _item_in_container( - _container: &Vec, - _item: &String, - _func: fn(a: &String, b: &String) -> String, - ) -> String { - return String::from(""); - } - - // TODO: Implement - pub fn _item_iter_in_container( - _container: &Vec, - _item: &String, - _func: fn(a: &String, b: &String) -> String, - ) -> String { - return String::from(""); - } - pub fn index_of_item_in_container(container: &String, item: &char, func: F) -> i32 where F: Fn(&char, &char) -> bool, diff --git a/src/utilities/conversions.rs b/src/utilities/conversions.rs deleted file mode 100644 index d404723..0000000 --- a/src/utilities/conversions.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Deserialize, Serialize)] -pub struct Conversions {} - -impl Conversions { - pub fn _to_lower_char(val: &mut char) { - if val.is_alphabetic() { - *val = val.to_lowercase().next().unwrap(); - } - } - - pub fn _initialize_values(&self) {} - - pub fn _print_value(&self, val: T) { - println!("Going to print value"); - println!("{:?}", val); - } -} diff --git a/src/utilities/mod.rs b/src/utilities/mod.rs index f2a82e4..f6b5329 100644 --- a/src/utilities/mod.rs +++ b/src/utilities/mod.rs @@ -1,2 +1 @@ pub mod checks; -pub mod conversions; -- 2.47.3 From 5246667224f0be6abc6f55198ca9e443b1e41e16 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 15 Jun 2024 12:12:07 -0400 Subject: [PATCH 47/47] Added test --- src/managers/action_managers.rs | 68 +++++++++++++++++++++++++++++++++ src/models/song.rs | 1 - 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/managers/action_managers.rs b/src/managers/action_managers.rs index 68d52b4..d92af04 100644 --- a/src/managers/action_managers.rs +++ b/src/managers/action_managers.rs @@ -151,3 +151,71 @@ impl ActionManager { return parsed; } } + +#[cfg(test)] +mod tests { + use crate::managers::action_managers::ActionManager; + + #[test] + fn minimum_action_and_args() { + let args: Vec = vec![ + "icarus-dm".to_string(), + "download".to_string(), + "-u".to_string(), + "jamborie".to_string(), + "-p".to_string(), + "somethingsecr3t!".to_string(), + "-h".to_string(), + "https://music-server.com".to_string(), + ]; + let arg_count = args.len() as i32; + let minimum_arg_count = 8; + assert!(arg_count >= minimum_arg_count); + + let mut act_mgr = ActionManager { + action: String::new(), + flags: Vec::new(), + params: args, + param_count: arg_count, + }; + act_mgr.initialize(); + let ica = act_mgr.retrieve_icarus_action(); + let action = &ica.action; + let flags = &ica.flags; + + assert!(action != ""); + assert!(flags.len() > 2); + assert!( + !(action != "download" + && action != "upload" + && action != "retrieve" + && action != "upload-meta") + ); + + let mut all_flags_found = false; + let mut found_count = 0; + let mut flags_already_read = Vec::new(); + + for flag in flags { + if flags_already_read.contains(&flag.flag) { + continue; + } + + if flag.flag == "-u" { + found_count += 1; + flags_already_read.push(flag.flag.clone()); + } else if flag.flag == "-p" { + found_count += 1; + flags_already_read.push(flag.flag.clone()); + } else if flag.flag == "-h" { + found_count += 1; + flags_already_read.push(flag.flag.clone()); + } + } + + all_flags_found = found_count == 3; + + assert_eq!(found_count, 3, "Three flags are required: -u, -p, -h"); + assert!(all_flags_found, "All flags have not been found"); + } +} diff --git a/src/models/song.rs b/src/models/song.rs index e5ab5c8..7568e45 100644 --- a/src/models/song.rs +++ b/src/models/song.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; use crate::constants; - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Song { #[serde(alias = "song_id")] -- 2.47.3