41 Commits

Author SHA1 Message Date
Kun Deng c96ee39c6a Merge pull request #17 from kdeng00/cleanup
Cleanup
2022-08-28 10:53:23 -04:00
Kun Deng 389f41ecea Updates
Updated CMakeLists file, removed conan file, and have all windows configs targeting C++20
2022-08-28 10:53:00 -04:00
Kun Deng 10bf0fb0e1 Clean up and version change 2022-08-28 10:49:28 -04:00
Kun Deng 4429f7e766 Merge pull request #16 from kdeng00/bug_fix
Bug fix
2022-08-28 10:36:11 -04:00
Kun Deng e5d119d343 Bug fix 2022-08-28 10:34:27 -04:00
Kun Deng 1d88a3ccf6 Update README.md 2022-08-07 21:40:23 -04:00
Kun Deng 2768c1e351 Update README.md 2022-08-07 21:40:01 -04:00
Kun Deng 3955942988 Merge pull request #15 from kdeng00/v0.3
V0.3
2022-08-07 21:37:39 -04:00
Kun Deng bfd7a02970 Merge pull request #14 from kdeng00/vs
Vs
2022-08-07 21:35:55 -04:00
kdeng00 77acd15105 Able to debug with Visual Studio 2022-08-07 21:34:41 -04:00
kdeng00 435a0df941 Added build files
Added Visual studio build files
2022-08-07 21:15:54 -04:00
kdeng00 c624c4de51 Missing include 2022-08-07 21:15:07 -04:00
Kun Deng 1d6cd804be Merge pull request #13 from kdeng00/vcpkg
Vcpkg
2022-08-07 20:46:24 -04:00
kdeng00 2743543102 Clean up 2022-08-07 20:44:37 -04:00
kdeng00 3195011f99 vcpkg is operational 2022-08-07 20:42:11 -04:00
kdeng00 ed5ceedb44 vcpkg version
Version 2022.07.25
2022-08-07 20:04:57 -04:00
kdeng00 f70acba704 Added vcpkg 2022-08-07 20:04:02 -04:00
Kun Deng f224b5738b Merge pull request #12 from kdeng00/build_fix
Fixed build issue
2022-08-07 19:59:29 -04:00
kdeng00 c41cd9dbb7 Fixed build issue 2022-08-07 19:51:29 -04:00
Kun Deng 9420ee97b4 Merge pull request #9 from kdeng00/support_new_upload_endpoint
Support new upload endpoint
2022-01-09 18:07:50 -05:00
Kun Deng c46f386d70 Merge branch 'master' into support_new_upload_endpoint 2022-01-09 18:07:44 -05:00
kdeng00 d9962749c8 Ready for release 2022-01-09 18:06:43 -05:00
kdeng00 c8e8c1a460 Changed cmake version 2022-01-09 02:16:51 -05:00
kdeng00 dcfa9951d9 Updated Readme 2022-01-09 02:04:56 -05:00
kdeng00 e90278995a Saving changes 2022-01-09 00:31:43 -05:00
kdeng00 7c8e77f233 Formatting 2022-01-08 23:52:46 -05:00
Kun Deng a1b2e5f64a Merge branch 'master' into support_new_upload_endpoint 2022-01-08 23:46:43 -05:00
kdeng00 25e8774968 Visual Studio support 2022-01-08 21:12:55 -05:00
kdeng00 10ed33d412 Formatting 2022-01-08 21:09:40 -05:00
kdeng00 1ef40bcbfb Got functionality working 2022-01-01 00:39:35 -05:00
kdeng00 3e25dd77b5 Updates
Updating required flags for uploading a song with metadata
2021-12-31 22:15:17 -05:00
kdeng00 14d3c9acc6 Made progress 2021-12-31 19:09:31 -05:00
kdeng00 9930aab985 Updated Readme 2021-12-31 16:00:45 -05:00
kdeng00 0839731ee8 upload-meta command 2021-12-29 15:58:14 -05:00
Kun Deng 7a04b802f0 Merge pull request #8 from kdeng00/package_manager-switch
Package manager switch
2021-12-29 15:50:28 -05:00
kdeng00 63d6022d16 Updated Readme
Added link to conan repo
2021-12-29 15:47:21 -05:00
kdeng00 db1a6302ad Updated Readme 2021-12-29 15:45:12 -05:00
kdeng00 bd819f0332 package manager switch
Moving from Hunter to conan
2021-12-29 15:38:28 -05:00
kdeng00 7177b01a98 added flag to prevent the user from being prompted when uploading songs from a directory 2019-11-12 22:07:44 -05:00
kdeng00 996b84c25c Prompt user when uploading songs from a directory 2019-11-11 22:54:53 -05:00
Kun Deng 9d8122df5c Update README.md 2019-10-26 10:22:12 -04:00
53 changed files with 2630 additions and 1817 deletions
+3
View File
@@ -0,0 +1,3 @@
/.vs/*
/build
/x64
+3
View File
@@ -0,0 +1,3 @@
[submodule "3rdparty/vcpkg"]
path = 3rdparty/vcpkg
url = https://github.com/microsoft/vcpkg
Vendored Submodule
+1
Submodule 3rdparty/vcpkg added at f93ba152d5
+66 -49
View File
@@ -1,31 +1,63 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.23.3)
set(VCPKG_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vcpkg)
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()
include("cmake/HunterGate.cmake") set(SOFTWARE_DESCRIPTION
HunterGate( "A tool to interact with the Icarus Music streaming API")
URL "https://github.com/ruslo/hunter/archive/v0.23.184.tar.gz" set(SOFTWARE_VERSION
SHA1 "fe3fb05d51c21499c7eebbe7d0e102742a54a9cd" "0.3.2")
)
project(IcarusDownloadManager)
project(IcarusDownloadManager VERSION ${SOFTWARE_VERSION} DESCRIPTION ${SOFTWARE_DESCRIPTION} LANGUAGES CXX)
if(NOT ${CMAKE_VERSION} LESS 3.2)
set(CMAKE_CXX_STANDARD 11) message(STATUS "Checking compiler flags for C++20 support.")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
else() # Set C++20 support flags for various compilers
message(STATUS "Checking compiler flags for C++17 support.")
# Set C++17 support flags for various compilers
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++17" COMPILER_SUPPORTS_CXX17)
check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if(WIN32)
if(COMPILER_SUPPORTS_CXX17) message("Windows environment")
message(STATUS "C++17 is supported.")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if (MSVC_VERSION GREATER_EQUAL "1900")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=libc++") 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() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") 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() endif()
elseif(COMPILER_SUPPORTS_CXX0X) elseif(COMPILER_SUPPORTS_CXX0X)
message(STATUS "C++0x is supported.") message(STATUS "C++0x is supported.")
@@ -35,7 +67,7 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif() endif()
else() else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++17 support. Please use a different C++ compiler.") message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++20 support. Please use a different C++ compiler.")
endif() endif()
endif() endif()
@@ -47,6 +79,7 @@ set(SOURCES
src/Managers/FileManager.cpp src/Managers/FileManager.cpp
src/Managers/TokenManager.cpp src/Managers/TokenManager.cpp
src/Managers/UserManager.cpp src/Managers/UserManager.cpp
src/Models/Song.cpp
src/Parsers/APIParser.cpp src/Parsers/APIParser.cpp
src/Syncers/Delete.cpp src/Syncers/Delete.cpp
src/Syncers/Download.cpp src/Syncers/Download.cpp
@@ -54,36 +87,20 @@ set(SOURCES
src/Syncers/Upload.cpp src/Syncers/Upload.cpp
src/Utilities/Conversions.cpp src/Utilities/Conversions.cpp
) )
set(HEADERS
include/Managers/ActionManager.h
include/Managers/CommitManager.h
include/Managers/FileManager.h
include/Managers/TokenManager.h
include/Managers/UserManager.h
include/Models/API.h
include/Models/Flags.h
include/Models/IcarusAction.h
include/Models/Song.h
include/Models/Token.h
include/Models/UploadForm.h
include/Models/User.h
include/Parsers/APIParser.h
include/Syncers/Delete.h
include/Syncers/Download.h
include/Syncers/RetrieveRecords.h
include/Syncers/SyncerBase.h
include/Syncers/Upload.h
include/Utilities/Conversions.h
)
set(IDM_INCLUDE_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include")
include_directories(${IDM_INCLUDE_DIR})
set(USE_SYSTEM_CURL OFF)
set(BUILD_CPR_TESTS OFF)
hunter_add_package(nlohmann_json)
find_package(nlohmann_json CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
hunter_add_package(cpr) find_package(CURL REQUIRED)
find_package(cpr CONFIG REQUIRED) find_package(cpr CONFIG REQUIRED)
add_executable(icd ${SOURCES} ${HEADERS}) add_executable(icd ${SOURCES})
target_link_libraries(icd PUBLIC nlohmann_json::nlohmann_json cpr::cpr) target_link_libraries(icd PRIVATE nlohmann_json::nlohmann_json OpenSSL::SSL OpenSSL::Crypto CURL::libcurl cpr::cpr)
include_directories(include/)
+99
View File
@@ -0,0 +1,99 @@
// 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
+31
View File
@@ -0,0 +1,31 @@
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
+165
View File
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{12955990-643F-4A99-95E5-4752AFA179B0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(ProjectDir)include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(ProjectDir)include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Main.cpp" />
<ClCompile Include="src\managers\ActionManager.cpp" />
<ClCompile Include="src\managers\CommitManager.cpp" />
<ClCompile Include="src\managers\FileManager.cpp" />
<ClCompile Include="src\managers\TokenManager.cpp" />
<ClCompile Include="src\managers\UserManager.cpp" />
<ClCompile Include="src\models\Song.cpp" />
<ClCompile Include="src\parsers\APIParser.cpp" />
<ClCompile Include="src\syncers\Delete.cpp" />
<ClCompile Include="src\syncers\Download.cpp" />
<ClCompile Include="src\syncers\RetrieveRecords.cpp" />
<ClCompile Include="src\syncers\Upload.cpp" />
<ClCompile Include="src\utilities\Conversions.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\managers\ActionManager.h" />
<ClInclude Include="include\managers\CommitManager.h" />
<ClInclude Include="include\managers\FileManager.h" />
<ClInclude Include="include\managers\TokenManager.h" />
<ClInclude Include="include\managers\UserManager.h" />
<ClInclude Include="include\models\API.h" />
<ClInclude Include="include\models\Flags.h" />
<ClInclude Include="include\models\IcarusAction.h" />
<ClInclude Include="include\models\Song.h" />
<ClInclude Include="include\models\Token.h" />
<ClInclude Include="include\models\UploadForm.h" />
<ClInclude Include="include\models\User.h" />
<ClInclude Include="include\parsers\APIParser.h" />
<ClInclude Include="include\syncers\Delete.h" />
<ClInclude Include="include\syncers\Download.h" />
<ClInclude Include="include\syncers\RetrieveRecords.h" />
<ClInclude Include="include\syncers\SyncerBase.h" />
<ClInclude Include="include\syncers\Upload.h" />
<ClInclude Include="include\utilities\Checks.h" />
<ClInclude Include="include\utilities\Conversions.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="IcarusDownloadManager.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\managers\ActionManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\managers\CommitManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\managers\FileManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\managers\TokenManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\managers\UserManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\models\Song.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\parsers\APIParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\syncers\Delete.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\syncers\Download.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\syncers\RetrieveRecords.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\syncers\Upload.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\utilities\Conversions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\managers\ActionManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\managers\CommitManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\managers\FileManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\managers\TokenManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\managers\UserManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\API.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\Flags.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\IcarusAction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\Song.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\UploadForm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\models\User.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\parsers\APIParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\syncers\Delete.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\syncers\Download.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\syncers\RetrieveRecords.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\syncers\SyncerBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\syncers\Upload.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\utilities\Checks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\utilities\Conversions.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>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"</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>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"</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
+83 -25
View File
@@ -1,33 +1,88 @@
# IcarusDownloadManager # IcarusDownloadManager
IcarusDownloadManager is a Linux UI software client application that has the feature of uploading and downloading songs from the [Icarus](https://github.com/amazing-username/Icarus) Music Server. 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.
### Getting Started
Build the project:
```
export HUNTER_ROOT=/path/to/download/hunter/files/for/dependencies
mkdir _build
cd _build
cmake -H. -B_builds -DHUNTER_STATUS_DEBUG=ON -DCMAKE_BUILD_TYPE=DEBUG
cmake --build _builds --config Debug
make
```
The program has been built and can be executed by the binary file *icd*
## Built With ## Built With
* C++ * C++ with C++20 features
* CMake * CMake
* GCC * GCC >= 10 or Visual Studio >= 17 [2022]
* [Hunter](https://github.com/ruslo/hunter) * [vcpkg](https://github.com/microsoft/vcpkg)
* libCurl
* [json](https://github.com/nlohmann/json) * [json](https://github.com/nlohmann/json)
* [cpr](http://whoshuu.github.io/cpr/) * [openssl](https://github.com/openssl/openssl)
* [curl](https://github.com/curl/curl)
* [cpr](https://github.com/libcpr/cpr)
### Getting Started
Clone the repo
```
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:
```
cd IcarusDownloadManager
mkdir build
cd build
cmake ..
cmake --build . --config release -j
```
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.
### 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
```
### 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
```
### 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/
```
### Retrieving Song in json
```Bash
icd 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
```
## Contributing ## Contributing
@@ -35,13 +90,16 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduc
## Versioning ## Versioning
[v0.1.0](https://github.com/amazing-username/IcarusDownloadManager/releases/tag/0.1.0) [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)
[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 ## Authors
* **Kun Deng** - [amazing-username](https://github.com/amazing-username) * **Kun Deng** - [kdeng00](https://github.com/kdeng00)
See also the list of [contributors](https://github.com/amazing-username/Icarus/graphs/contributors) who participated in this project. See also the list of [contributors](https://github.com/kdeng00/Icarus/graphs/contributors) who participated in this project.
## License ## License
-528
View File
@@ -1,528 +0,0 @@
# Copyright (c) 2013-2019, Ruslan Baratov
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is a gate file to Hunter package manager.
# Include this file using `include` command and add package you need, example:
#
# cmake_minimum_required(VERSION 3.2)
#
# include("cmake/HunterGate.cmake")
# HunterGate(
# URL "https://github.com/path/to/hunter/archive.tar.gz"
# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
# )
#
# project(MyProject)
#
# hunter_add_package(Foo)
# hunter_add_package(Boo COMPONENTS Bar Baz)
#
# Projects:
# * https://github.com/hunter-packages/gate/
# * https://github.com/ruslo/hunter
option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
if(HUNTER_ENABLED)
if(CMAKE_VERSION VERSION_LESS "3.2")
message(
FATAL_ERROR
"At least CMake version 3.2 required for Hunter dependency management."
" Update CMake or set HUNTER_ENABLED to OFF."
)
endif()
endif()
include(CMakeParseArguments) # cmake_parse_arguments
option(HUNTER_STATUS_PRINT "Print working status" ON)
option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON)
set(HUNTER_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors")
function(hunter_gate_status_print)
if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
message(STATUS "[hunter] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_status_debug)
if(HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
string(TIMESTAMP timestamp)
message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_error_page error_page)
message("------------------------------ ERROR ------------------------------")
message(" ${HUNTER_ERROR_PAGE}/${error_page}.html")
message("-------------------------------------------------------------------")
message("")
message(FATAL_ERROR "")
endfunction()
function(hunter_gate_internal_error)
message("")
foreach(print_message ${ARGV})
message("[hunter ** INTERNAL **] ${print_message}")
endforeach()
message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_error_page("error.internal")
endfunction()
function(hunter_gate_fatal_error)
cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}")
if("${hunter_ERROR_PAGE}" STREQUAL "")
hunter_gate_internal_error("Expected ERROR_PAGE")
endif()
message("")
foreach(x ${hunter_UNPARSED_ARGUMENTS})
message("[hunter ** FATAL ERROR **] ${x}")
endforeach()
message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_error_page("${hunter_ERROR_PAGE}")
endfunction()
function(hunter_gate_user_error)
hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data")
endfunction()
function(hunter_gate_self root version sha1 result)
string(COMPARE EQUAL "${root}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("root is empty")
endif()
string(COMPARE EQUAL "${version}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("version is empty")
endif()
string(COMPARE EQUAL "${sha1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("sha1 is empty")
endif()
string(SUBSTRING "${sha1}" 0 7 archive_id)
set(
hunter_self
"${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked"
)
set("${result}" "${hunter_self}" PARENT_SCOPE)
endfunction()
# Set HUNTER_GATE_ROOT cmake variable to suitable value.
function(hunter_gate_detect_root)
# Check CMake variable
string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable")
return()
endif()
# Check environment variable
string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by environment variable")
return()
endif()
# Check HOME environment variable
string(COMPARE NOTEQUAL "$ENV{HOME}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable")
return()
endif()
# Check SYSTEMDRIVE and USERPROFILE environment variable (windows only)
if(WIN32)
string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using SYSTEMDRIVE environment variable"
)
return()
endif()
string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using USERPROFILE environment variable"
)
return()
endif()
endif()
hunter_gate_fatal_error(
"Can't detect HUNTER_ROOT"
ERROR_PAGE "error.detect.hunter.root"
)
endfunction()
function(hunter_gate_download dir)
string(
COMPARE
NOTEQUAL
"$ENV{HUNTER_DISABLE_AUTOINSTALL}"
""
disable_autoinstall
)
if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL)
hunter_gate_fatal_error(
"Hunter not found in '${dir}'"
"Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'"
"Settings:"
" HUNTER_ROOT: ${HUNTER_GATE_ROOT}"
" HUNTER_SHA1: ${HUNTER_GATE_SHA1}"
ERROR_PAGE "error.run.install"
)
endif()
string(COMPARE EQUAL "${dir}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("Empty 'dir' argument")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_SHA1 empty")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_URL empty")
endif()
set(done_location "${dir}/DONE")
set(sha1_location "${dir}/SHA1")
set(build_dir "${dir}/Build")
set(cmakelists "${dir}/CMakeLists.txt")
hunter_gate_status_debug("Locking directory: ${dir}")
file(LOCK "${dir}" DIRECTORY GUARD FUNCTION)
hunter_gate_status_debug("Lock done")
if(EXISTS "${done_location}")
# while waiting for lock other instance can do all the job
hunter_gate_status_debug("File '${done_location}' found, skip install")
return()
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(MAKE_DIRECTORY "${build_dir}") # check directory permissions
# Disabling languages speeds up a little bit, reduces noise in the output
# and avoids path too long windows error
file(
WRITE
"${cmakelists}"
"cmake_minimum_required(VERSION 3.2)\n"
"project(HunterDownload LANGUAGES NONE)\n"
"include(ExternalProject)\n"
"ExternalProject_Add(\n"
" Hunter\n"
" URL\n"
" \"${HUNTER_GATE_URL}\"\n"
" URL_HASH\n"
" SHA1=${HUNTER_GATE_SHA1}\n"
" DOWNLOAD_DIR\n"
" \"${dir}\"\n"
" TLS_VERIFY\n"
" ${HUNTER_TLS_VERIFY}\n"
" SOURCE_DIR\n"
" \"${dir}/Unpacked\"\n"
" CONFIGURE_COMMAND\n"
" \"\"\n"
" BUILD_COMMAND\n"
" \"\"\n"
" INSTALL_COMMAND\n"
" \"\"\n"
")\n"
)
if(HUNTER_STATUS_DEBUG)
set(logging_params "")
else()
set(logging_params OUTPUT_QUIET)
endif()
hunter_gate_status_debug("Run generate")
# Need to add toolchain file too.
# Otherwise on Visual Studio + MDD this will fail with error:
# "Could not find an appropriate version of the Windows 10 SDK installed on this machine"
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE)
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}")
else()
# 'toolchain_arg' can't be empty
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=")
endif()
string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make)
if(no_make)
set(make_arg "")
else()
# Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM
set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}")
endif()
execute_process(
COMMAND
"${CMAKE_COMMAND}"
"-H${dir}"
"-B${build_dir}"
"-G${CMAKE_GENERATOR}"
"${toolchain_arg}"
${make_arg}
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error(
"Configure project failed."
"To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}"
"In directory ${dir}"
)
endif()
hunter_gate_status_print(
"Initializing Hunter workspace (${HUNTER_GATE_SHA1})"
" ${HUNTER_GATE_URL}"
" -> ${dir}"
)
execute_process(
COMMAND "${CMAKE_COMMAND}" --build "${build_dir}"
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error("Build project failed")
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}")
file(WRITE "${done_location}" "DONE")
hunter_gate_status_debug("Finished")
endfunction()
# Must be a macro so master file 'cmake/Hunter' can
# apply all variables easily just by 'include' command
# (otherwise PARENT_SCOPE magic needed)
macro(HunterGate)
if(HUNTER_GATE_DONE)
# variable HUNTER_GATE_DONE set explicitly for external project
# (see `hunter_download`)
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
# First HunterGate command will init Hunter, others will be ignored
get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET)
if(NOT HUNTER_ENABLED)
# Empty function to avoid error "unknown function"
function(hunter_add_package)
endfunction()
set(
_hunter_gate_disabled_mode_dir
"${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode"
)
if(EXISTS "${_hunter_gate_disabled_mode_dir}")
hunter_gate_status_debug(
"Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}"
)
list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}")
endif()
elseif(_hunter_gate_done)
hunter_gate_status_debug("Secondary HunterGate (use old settings)")
hunter_gate_self(
"${HUNTER_CACHED_ROOT}"
"${HUNTER_VERSION}"
"${HUNTER_SHA1}"
_hunter_self
)
include("${_hunter_self}/cmake/Hunter")
else()
set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}")
string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name)
if(_have_project_name)
hunter_gate_fatal_error(
"Please set HunterGate *before* 'project' command. "
"Detected project: ${PROJECT_NAME}"
ERROR_PAGE "error.huntergate.before.project"
)
endif()
cmake_parse_arguments(
HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV}
)
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1)
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url)
string(
COMPARE
NOTEQUAL
"${HUNTER_GATE_UNPARSED_ARGUMENTS}"
""
_have_unparsed
)
string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global)
string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath)
if(_have_unparsed)
hunter_gate_user_error(
"HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}"
)
endif()
if(_empty_sha1)
hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory")
endif()
if(_empty_url)
hunter_gate_user_error("URL suboption of HunterGate is mandatory")
endif()
if(_have_global)
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)")
endif()
endif()
if(HUNTER_GATE_LOCAL)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)")
endif()
endif()
if(_have_filepath)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)")
endif()
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)")
endif()
endif()
hunter_gate_detect_root() # set HUNTER_GATE_ROOT
# Beautify path, fix probable problems with windows path slashes
get_filename_component(
HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE
)
hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}")
if(NOT HUNTER_ALLOW_SPACES_IN_PATH)
string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces)
if(NOT _contain_spaces EQUAL -1)
hunter_gate_fatal_error(
"HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces."
"Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error"
"(Use at your own risk!)"
ERROR_PAGE "error.spaces.in.hunter.root"
)
endif()
endif()
string(
REGEX
MATCH
"[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*"
HUNTER_GATE_VERSION
"${HUNTER_GATE_URL}"
)
string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty)
if(_is_empty)
set(HUNTER_GATE_VERSION "unknown")
endif()
hunter_gate_self(
"${HUNTER_GATE_ROOT}"
"${HUNTER_GATE_VERSION}"
"${HUNTER_GATE_SHA1}"
_hunter_self
)
set(_master_location "${_hunter_self}/cmake/Hunter")
get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE)
set(_done_location "${_archive_id_location}/DONE")
set(_sha1_location "${_archive_id_location}/SHA1")
# Check Hunter already downloaded by HunterGate
if(NOT EXISTS "${_done_location}")
hunter_gate_download("${_archive_id_location}")
endif()
if(NOT EXISTS "${_done_location}")
hunter_gate_internal_error("hunter_gate_download failed")
endif()
if(NOT EXISTS "${_sha1_location}")
hunter_gate_internal_error("${_sha1_location} not found")
endif()
file(READ "${_sha1_location}" _sha1_value)
string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal)
if(NOT _is_equal)
hunter_gate_internal_error(
"Short SHA1 collision:"
" ${_sha1_value} (from ${_sha1_location})"
" ${HUNTER_GATE_SHA1} (HunterGate)"
)
endif()
if(NOT EXISTS "${_master_location}")
hunter_gate_user_error(
"Master file not found:"
" ${_master_location}"
"try to update Hunter/HunterGate"
)
endif()
include("${_master_location}")
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
endmacro()
+60 -11
View File
@@ -1,7 +1,9 @@
#ifndef ACTIONMANAGER_H_ #ifndef ACTIONMANAGER_H_
#define ACTIONMANAGER_H_ #define ACTIONMANAGER_H_
#include<algorithm>
#include<string> #include<string>
#include<string_view>
#include<array> #include<array>
#include<vector> #include<vector>
@@ -10,6 +12,9 @@
namespace Managers namespace Managers
{ {
class ActionManager class ActionManager
{ {
public: public:
@@ -17,28 +22,72 @@ namespace Managers
Models::IcarusAction retrieveIcarusAction() const; Models::IcarusAction retrieveIcarusAction() const;
private: private:
bool isNumber(std::string); constexpr std::array<const char*, 16> supportedFlags() noexcept
{
constexpr std::array<const char*, 16> allFlags{"-u", "-p", "-t", "-h", "-s",
"-sd", "-sr", "-d", "-D", "-b", "-rt", "-nc",
"-m", "-ca", "-smca", "-t"};
return allFlags;
}
constexpr std::array<const char*, 4> supportedActions() noexcept;
void initialize(); void initialize();
void validateFlags(); void validateFlags();
// Checks to see if the flag is valid
template<typename Str>
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<typename Str>
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<Str>(*i))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
void printAction() noexcept;
void printFlags() noexcept;
std::vector<std::string> parsedFlags(); std::vector<std::string> parsedFlags();
void printAction();
void printFlags();
std::string action; std::string action;
std::array<std::string, 4> supportedActions{
"download", "upload", "retrieve", "delete"
};
std::array<std::string, 11> supportedFlags{
"-u", "-p", "-t", "-h", "-s", "-sd",
"-sr", "-d", "-D", "-b", "-rt"
};
std::vector<Models::Flags> flags; std::vector<Models::Flags> flags;
char **params; char **params;
int paramCount; int paramCount;
}; };
} }
#endif #endif
+179 -10
View File
@@ -2,14 +2,20 @@
#define COMMITMANAGER_H_ #define COMMITMANAGER_H_
#include<map> #include<map>
#include<iostream>
#include<filesystem>
#include<string> #include<string>
#include<string_view>
#include"Models/API.h" #include"Models/API.h"
#include"Models/Token.h"
#include"Models/IcarusAction.h" #include"Models/IcarusAction.h"
#include"Models/Song.h"
#include"Models/Token.h"
#include"Utilities/Checks.h"
namespace Managers namespace Managers
{ {
class CommitManager class CommitManager
{ {
public: public:
@@ -17,35 +23,198 @@ namespace Managers
void commitAction(); void commitAction();
enum RetrieveTypes
enum class RetrieveTypes
{ {
songs 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<Models::Song> songs;
};
private: private:
Models::Token parseToken(Models::API); enum class ActionValues;
std::map<std::string, ActionValues> mapActions() noexcept;
void deleteSong(); void deleteSong();
void downloadSong(); void downloadSong();
void retrieveObjects(); void retrieveObjects();
void uploadSong(); void uploadSong();
enum ActionValues 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<typename Song, typename Str>
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<char, Str>(filename, 'd', dl);
auto k = Utilities::Checks::itemIterInContainer<char, Str>(filename, 'k', dl);
auto dot = Utilities::Checks::itemIterInContainer<char, Str>(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: "<<dStr<<" TStr: " << tStr<<"\n";
if (Utilities::Checks::isNumber(tStr))
{
track = std::atoi(tStr.c_str());
}
else if (Utilities::Checks::isNumber(dStr))
{
disc = std::atoi(dStr.c_str());
}
}
break;
}
}
song.disc = disc;
song.track = track;
}
template<typename Song, typename Str>
void parseDiscAndTrack(Song &song, const Str &trackID)
{
auto sep = [](char c, char t) { return c == t; };
auto separator = Utilities::Checks::itemIterInContainer<char, Str>(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, deleteAct,
downloadAct, downloadAct,
retrieveAct, retrieveAct,
uploadAct uploadAct,
UPLOAD_SONG_WITH_METADATA // Uploads the song with metadata, including cover art
}; };
std::map<std::string, ActionValues> mapActions{
{"delete", deleteAct}, {"download", downloadAct},
{"retrieve", retrieveAct},
{"upload", uploadAct}
};
Models::IcarusAction icaAction; Models::IcarusAction icaAction;
}; };
} }
#endif #endif
+2
View File
@@ -5,6 +5,7 @@
namespace Managers namespace Managers
{ {
class FileManager class FileManager
{ {
public: public:
@@ -24,6 +25,7 @@ namespace Managers
bool fileRead; bool fileRead;
int fileBufferLength; int fileBufferLength;
}; };
} }
#endif #endif
+2
View File
@@ -7,6 +7,7 @@
namespace Managers namespace Managers
{ {
class TokenManager class TokenManager
{ {
public: public:
@@ -18,6 +19,7 @@ namespace Managers
Models::API api; Models::API api;
Models::User user; Models::User user;
}; };
} }
#endif #endif
+2
View File
@@ -8,6 +8,7 @@
namespace Managers namespace Managers
{ {
class UserManager class UserManager
{ {
public: public:
@@ -21,6 +22,7 @@ namespace Managers
Models::User user; Models::User user;
Models::IcarusAction icaAction; Models::IcarusAction icaAction;
}; };
} }
#endif #endif
+4 -1
View File
@@ -5,12 +5,15 @@
namespace Models namespace Models
{ {
struct API
class API
{ {
public:
std::string url; std::string url;
std::string endpoint; std::string endpoint;
std::string version; std::string version;
}; };
} }
#endif #endif
+4 -1
View File
@@ -5,11 +5,14 @@
namespace Models namespace Models
{ {
struct Flags
class Flags
{ {
public:
std::string flag; std::string flag;
std::string value; std::string value;
}; };
} }
#endif #endif
+36 -1
View File
@@ -2,17 +2,52 @@
#define ICARUSACTION_H_ #define ICARUSACTION_H_
#include<string> #include<string>
#include<algorithm>
#include<string_view>
#include<vector> #include<vector>
#include<iostream>
#include"Flags.h" #include"Flags.h"
namespace Models namespace Models
{ {
struct IcarusAction
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: "<<this->action<<"\n";
std::cout<<"Flag count: "<<this->flags.size()<<"\n";
for (const auto &flag : this->flags)
{
std::cout<<"flag "<<flag.flag<<" value "<<flag.value<<"\n";
}
std::cout<<"\n";
}
std::string action; std::string action;
std::vector<Flags> flags; std::vector<Flags> flags;
}; };
} }
#endif #endif
+67 -1
View File
@@ -2,12 +2,65 @@
#define SONG_H_ #define SONG_H_
#include <string> #include <string>
#include <iostream>
#include <sstream>
namespace Models namespace Models
{ {
struct Song
class Song
{ {
public:
Song() = default;
void printInfo()
{
std::cout<<"Title: "<<this->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; int id;
std::string title; std::string title;
std::string artist; std::string artist;
@@ -16,9 +69,22 @@ namespace Models
int year; int year;
int duration; int duration;
int track; int track;
int disc;
std::string data; std::string data;
[[deprecated("Use song_path() function instead")]]
std::string songPath; std::string songPath;
std::string filename;
std::string directory;
}; };
class CoverArt
{
public:
int id;
std::string title;
std::string path;
};
} }
#endif #endif
+2
View File
@@ -5,12 +5,14 @@
namespace Models namespace Models
{ {
struct Token struct Token
{ {
std::string accessToken; std::string accessToken;
std::string tokenType; std::string tokenType;
int expiration; int expiration;
}; };
} }
#endif #endif
+2
View File
@@ -6,11 +6,13 @@
namespace Models namespace Models
{ {
struct UploadForm struct UploadForm
{ {
std::string url; std::string url;
std::string filePath; std::string filePath;
}; };
} }
#endif #endif
+2
View File
@@ -5,11 +5,13 @@
namespace Models namespace Models
{ {
struct User struct User
{ {
std::string username; std::string username;
std::string password; std::string password;
}; };
} }
#endif #endif
+2
View File
@@ -6,6 +6,7 @@
namespace Parsers namespace Parsers
{ {
class APIParser class APIParser
{ {
public: public:
@@ -18,6 +19,7 @@ namespace Parsers
Models::API api; Models::API api;
Models::IcarusAction icaAct; Models::IcarusAction icaAct;
}; };
} }
#endif #endif
+2
View File
@@ -9,6 +9,7 @@
namespace Syncers namespace Syncers
{ {
class Delete : SyncerBase class Delete : SyncerBase
{ {
public: public:
@@ -18,6 +19,7 @@ namespace Syncers
private: private:
std::string retrieveUrl(Models::Song); std::string retrieveUrl(Models::Song);
}; };
} }
#endif #endif
+2
View File
@@ -12,6 +12,7 @@
namespace Syncers namespace Syncers
{ {
class Download : SyncerBase class Download : SyncerBase
{ {
public: public:
@@ -26,6 +27,7 @@ namespace Syncers
std::string downloadFilePath; std::string downloadFilePath;
void saveSong(Models::Song&); void saveSong(Models::Song&);
}; };
} }
#endif #endif
+2
View File
@@ -8,6 +8,7 @@
namespace Syncers namespace Syncers
{ {
class RetrieveRecords: public SyncerBase class RetrieveRecords: public SyncerBase
{ {
public: public:
@@ -21,6 +22,7 @@ namespace Syncers
Models::API api; Models::API api;
Models::Token token; Models::Token token;
}; };
} }
#endif #endif
+9
View File
@@ -7,6 +7,7 @@
namespace Syncers namespace Syncers
{ {
class SyncerBase class SyncerBase
{ {
protected: protected:
@@ -14,7 +15,15 @@ namespace Syncers
const int OK = 200; const int OK = 200;
const int UNAUTHORIZED = 401; const int UNAUTHORIZED = 401;
const int NOTFOUND = 404; const int NOTFOUND = 404;
enum class Result
{
OK = 200,
UNAUTHORIZED = 401,
NOTFOUND = 404
}; };
};
} }
#endif #endif
+13 -5
View File
@@ -7,6 +7,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "Managers/CommitManager.h"
#include "Managers/FileManager.h" #include "Managers/FileManager.h"
#include "Models/API.h" #include "Models/API.h"
#include "Models/Song.h" #include "Models/Song.h"
@@ -18,18 +19,24 @@ namespace fs = std::filesystem;
namespace Syncers namespace Syncers
{ {
class Upload class Upload
{ {
public: public:
Upload(); Upload() = default;
Upload(Models::API); Upload(Models::API api, Models::Token token) : m_token(token), api(api)
{
this->api.endpoint = "song/data";
}
Models::Song uploadSong(const Models::Token&, Models::Song&); Models::Song uploadSong(Models::Song&);
void uploadSongsFromDirectory(const Models::Token&, const std::string&, bool); void uploadSongsFromDirectory(const std::string&, const bool, bool);
void uploadSongWithMetadata(Managers::CommitManager::Album&, Models::Song&, Models::CoverArt&);
private: private:
Managers::FileManager fMgr; Managers::FileManager fMgr;
Models::API api; Models::API api;
Models::Song song; Models::Song song;
Models::Token m_token;
std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&, std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&,
bool); bool);
@@ -40,8 +47,9 @@ namespace Syncers
void printSongDetails(); void printSongDetails();
void printSongDetails(std::vector<Models::Song>&); void printSongDetails(std::vector<Models::Song>&);
void printJsonData(nlohmann::json); void printJsonData(const nlohmann::json&);
}; };
} }
#endif #endif
+2
View File
@@ -13,6 +13,7 @@
namespace UI namespace UI
{ {
class AboutWindow: public QDialog, public CommonWindow class AboutWindow: public QDialog, public CommonWindow
{ {
Q_OBJECT Q_OBJECT
@@ -29,6 +30,7 @@ namespace UI
private slots: private slots:
void closeWindow(); void closeWindow();
}; };
} }
#endif #endif
+6
View File
@@ -10,6 +10,9 @@
#include<QPushButton> #include<QPushButton>
namespace UI
{
class CommonWindow class CommonWindow
{ {
public: public:
@@ -24,4 +27,7 @@ protected:
std::unique_ptr<QVBoxLayout> subLayoutTwoQt; std::unique_ptr<QVBoxLayout> subLayoutTwoQt;
int windowHeight, windowWidth; int windowHeight, windowWidth;
}; };
}
#endif #endif
+2
View File
@@ -22,6 +22,7 @@
namespace UI namespace UI
{ {
class MainWindow: public QMainWindow, public CommonWindow class MainWindow: public QMainWindow, public CommonWindow
{ {
Q_OBJECT Q_OBJECT
@@ -77,6 +78,7 @@ namespace UI
void displaySoftwareInformation(); void displaySoftwareInformation();
void setCurrentIndex(int); void setCurrentIndex(int);
}; };
} }
#endif #endif
+67
View File
@@ -0,0 +1,67 @@
#ifndef CHECKS_H_
#define CHECKS_H_
#include<algorithm>
#include<string>
#include<cstdlib>
#include<ctype.h>
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<typename Item, typename Container, typename Func>
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<typename Item, typename Container, typename Func>
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
+11 -1
View File
@@ -6,17 +6,27 @@
namespace Utilities namespace Utilities
{ {
class Conversions class Conversions
{ {
public: public:
Conversions(); Conversions();
static void toLowerChar(char &c)
{
if (std::isalpha(c))
{
c = std::tolower(c);
}
}
void initializeValues(); void initializeValues();
template<typename T> template<typename T>
void printValue(T); void printValue(T val);
private: private:
}; };
} }
#endif #endif
+14
View File
@@ -0,0 +1,14 @@
//{{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
-1
View File
@@ -1 +0,0 @@
cmake -H. -B_builds -DHUNTER_STATUS_DEBUG=ON -DCMAKE_BUILD_TYPE=DEBUG
-1
View File
@@ -1 +0,0 @@
cmake --build _builds --config Debug
-1
View File
@@ -1 +0,0 @@
cmake --build _builds --config Release
+20 -4
View File
@@ -12,6 +12,11 @@ using std::string;
using Managers::ActionManager; using Managers::ActionManager;
using Managers::CommitManager; using Managers::CommitManager;
constexpr static auto IcarusDownloadManager_version()
{
return "v0.3.2";
}
void printHelp() void printHelp()
{ {
cout<<"icd [Action] [flag]\n\n"; cout<<"icd [Action] [flag]\n\n";
@@ -19,6 +24,7 @@ void printHelp()
cout<<"Actions\n"; cout<<"Actions\n";
cout<<"download\n"; cout<<"download\n";
cout<<"upload\n"; cout<<"upload\n";
cout<<"upload-meta\n";
cout<<"retrieve\n"; cout<<"retrieve\n";
cout<<"delete\n\n"; cout<<"delete\n\n";
@@ -31,7 +37,15 @@ void printHelp()
cout<<"Required for upload\n"; cout<<"Required for upload\n";
cout<<"-s path of song\n"; cout<<"-s path of song\n";
cout<<"-sd directory where to search for songs to upload (Optional)\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\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<<"Required for download\n";
cout<<"-b song id\n"; cout<<"-b song id\n";
@@ -50,13 +64,15 @@ int main(int argc, char** argv)
if (argc < 2) if (argc < 2)
{ {
printHelp(); printHelp();
return 1; return -1;
} }
ActionManager actMgr{argv, argc}; ActionManager actMgr(argv, argc);
auto chosenAction = actMgr.retrieveIcarusAction(); auto chosenAction = actMgr.retrieveIcarusAction();
CommitManager commitMgr{chosenAction}; chosenAction.print_action_and_flags();
CommitManager commitMgr(chosenAction);
commitMgr.commitAction(); commitMgr.commitAction();
return 0; return 0;
+32 -39
View File
@@ -8,6 +8,7 @@
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::string; using std::string;
using std::string_view;
using std::vector; using std::vector;
using Models::Flags; using Models::Flags;
@@ -15,33 +16,27 @@ using Models::IcarusAction;
namespace Managers namespace Managers
{ {
#pragma
#pragma region Constructors
ActionManager::ActionManager(char **param, int paramCount) : ActionManager::ActionManager(char **param, int paramCount) :
params(std::move(param)), paramCount(paramCount) params(std::move(param)), paramCount(paramCount)
{ {
initialize(); initialize();
} }
#pragma Constructors #pragma endregion
#pragma #pragma region Functions
IcarusAction ActionManager::retrieveIcarusAction() const IcarusAction ActionManager::retrieveIcarusAction() const
{ {
auto icarusAction = IcarusAction{}; IcarusAction icarusAction;
icarusAction.flags = flags; icarusAction.flags = flags;
icarusAction.action = action; icarusAction.action = action;
return icarusAction; return icarusAction;
} }
bool ActionManager::isNumber(string val)
{
return !val.empty() && std::find_if(val.begin(),
val.end(), [](char c)
{
return !std::isdigit(c);
}) == val.end();
}
void ActionManager::initialize() void ActionManager::initialize()
{ {
@@ -53,54 +48,51 @@ namespace Managers
} }
void ActionManager::validateFlags() void ActionManager::validateFlags()
{ {
cout<<"Validating flags"<<endl; cout<<"Validating flags\n";
auto flagVals = parsedFlags(); const auto flagVals = parsedFlags();
Flags flg{}; for (auto flag = flagVals.begin(); flag != flagVals.end(); ++flag)
for (auto flag : flagVals)
{ {
if (flag.size() > 3 || isNumber(flag)) Flags flg;
cout<<"Value: "<<*flag<<"\n";
if (isValidFlag<string>(*flag) && doesFlagHaveValue<string>(*flag))
{ {
flg.value = flag; cout<<"Flag has value\n";
//cout<<"flag value "<<flg.value<<endl; flg.flag = *flag;
flags.push_back(flg); flg.value = *(++flag);
flg = Flags{};
continue;
} }
else if (isValidFlag<string>(*flag))
if (std::any_of(supportedFlags.begin(), supportedFlags.end(),
[&](string& val)
{ {
return !val.compare(flag); cout<<"Flag does not have a value\n";
})) flg.flag = *flag;
{
//cout<<"flag "<<flag<<endl;
flg.flag = flag;
} }
else else
{ {
cout<<"Action is not valid"<<endl; cout<<"Flag "<<*flag<<" is not valid"<<endl;
exit(1); exit(1);
} }
flags.emplace_back(std::move(flg));
} }
} }
vector<string> ActionManager::parsedFlags() vector<string> ActionManager::parsedFlags()
{ {
auto parsed = vector<string>{}; auto parsed = vector<string>();
for (auto i = 2; i < paramCount; ++i) for (auto i = 2; i < paramCount; ++i)
{ {
parsed.push_back(std::move(*(params + i))); const std::string flag(std::move(*(params + i)));
parsed.push_back(std::move(flag));
} }
return parsed; return parsed;
} }
#pragma #pragma region Testing
void ActionManager::printAction() void ActionManager::printAction() noexcept
{ {
if (action.empty()) if (action.empty())
{ {
@@ -111,7 +103,7 @@ namespace Managers
cout<<"Action is "<<action<<endl; cout<<"Action is "<<action<<endl;
} }
} }
void ActionManager::printFlags() void ActionManager::printFlags() noexcept
{ {
cout<<"\nPrinting flags..."<<endl; cout<<"\nPrinting flags..."<<endl;
for (auto flag: flags) for (auto flag: flags)
@@ -120,6 +112,7 @@ namespace Managers
cout<<"value "<<flag.value<<endl; cout<<"value "<<flag.value<<endl;
} }
} }
#pragma Testing #pragma endregion
#pragma Functions #pragma endregion
} }
+267 -15
View File
@@ -1,6 +1,11 @@
#include"Managers/CommitManager.h" #include"Managers/CommitManager.h"
#include <iostream> #include <iostream>
#include <fstream>
#include <sstream>
#include <filesystem>
#include "nlohmann/json.hpp"
#include "Models/API.h" #include "Models/API.h"
#include "Models/Song.h" #include "Models/Song.h"
@@ -31,39 +36,70 @@ using Syncers::Download;
using Syncers::RetrieveRecords; using Syncers::RetrieveRecords;
using Syncers::Upload; using Syncers::Upload;
namespace filesystem = std::filesystem;
namespace Managers namespace Managers
{ {
#pragma
#pragma region Constructors
CommitManager::CommitManager(IcarusAction& icaAct) : icaAction(std::move(icaAct)) CommitManager::CommitManager(IcarusAction& icaAct) : icaAction(std::move(icaAct))
{ } { }
#pragma Constructors; #pragma endregion
#pragma #pragma region Functions
void CommitManager::commitAction() void CommitManager::commitAction()
{ {
auto action = icaAction.action; auto action = icaAction.action;
cout<<"Commiting "<<action<<" action"<<endl; cout<<"Commiting "<<action<<" action"<<endl;
switch (mapActions[action])
switch (mapActions()[action])
{ {
case deleteAct: case ActionValues::deleteAct:
deleteSong(); deleteSong();
break; break;
case downloadAct: case ActionValues::downloadAct:
downloadSong(); downloadSong();
break; break;
case retrieveAct: case ActionValues::retrieveAct:
retrieveObjects(); retrieveObjects();
break; break;
case uploadAct: case ActionValues::uploadAct:
uploadSong(); uploadSong();
break; break;
case ActionValues::UPLOAD_SONG_WITH_METADATA:
uploadSongWithMetadata();
break;
default:
break;
} }
} }
std::map<std::string, CommitManager::ActionValues>
CommitManager::mapActions() noexcept
{
const std::map<std::string, ActionValues> 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) Token CommitManager::parseToken(API api)
{ {
cout<<"fetching token"<<endl; cout<<"fetching token\n";
UserManager usrMgr{icaAction}; UserManager usrMgr{icaAction};
auto user = usrMgr.retrieveUser(); auto user = usrMgr.retrieveUser();
@@ -155,10 +191,12 @@ namespace Managers
songs.retrieve(retrieveType); songs.retrieve(retrieveType);
} }
void CommitManager::uploadSong() void CommitManager::uploadSong()
{ {
bool uploadSingleSong = true; auto uploadSingleSong = true;
bool recursiveDirectory = false; auto recursiveDirectory = false;
const auto noConfirm = checkForNoConfirm();
string songDirectory; string songDirectory;
APIParser apiPrs{icaAction}; APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI(); auto api = apiPrs.retrieveAPI();
@@ -189,17 +227,231 @@ namespace Managers
} }
} }
Upload upld{api}; Upload upld{api, token};
if (uploadSingleSong) if (uploadSingleSong)
{ {
cout<<"Uploading song..."<<endl; cout<<"Uploading song..."<<endl;
upld.uploadSong(token, song); upld.uploadSong(song);
} }
else else
{ {
cout<<"Uploading songs from " << songDirectory << endl; cout<<"Uploading songs from " << songDirectory << endl;
upld.uploadSongsFromDirectory(token, songDirectory, recursiveDirectory); upld.uploadSongsFromDirectory(songDirectory, noConfirm, recursiveDirectory);
} }
} }
#pragma Functions
void CommitManager::uploadSongWithMetadata()
{
cout<<"Uploading single song with metadata\n\n";
// Either the set of "-s", "-m", "-ca", "-t" flags or "-smca" must exist with values
// in order to be valid but not both
const auto songPath = this->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: "<<songPath<<"\n";
cout<<"TrackID: "<<trackID<<"\n";
cout<<"Metadata path: "<<metadataPath<<"\n";
cout<<"Cover Art path: "<<coverPath<<"\n";
if (singleTarget)
{
singTargetUpload(songPath, trackID, metadataPath, coverPath);
}
else if (multiTarget)
{
multiTargetUpload(uni);
}
}
void CommitManager::singTargetUpload(const std::string &songPath, const std::string &trackID,
const std::string &metaPath, const std::string &coverPath)
{
APIParser apiPrs(icaAction);
auto api = apiPrs.retrieveAPI();
const auto token = parseToken(api);
auto album = retrieveMetadata(metaPath);
album.printInfo();
Song song;
song.track = 1;
song.disc = 1;
cout<<"TrackID: "<<trackID<<"\n";
parseDiscAndTrack<Song, std::string>(song, trackID);
auto c = [](const Song &songA, const Song &songB) { return songA.track == songB.track && songA.disc == songB.disc; };
auto sng = Utilities::Checks::itemIterInContainer<Song, std::vector<Song>>(album.songs, song, c);
if (sng == album.songs.end())
{
cout<<"Not found with disc "<<song.disc<<" track "<<song.track<<"\n";
std::exit(-1);
}
song = *sng;
const auto p = filesystem::path(songPath);
song.directory = p.parent_path().string();
song.generate_filename_from_track();
Models::CoverArt cover;
cover.title = song.title;
cover.path = coverPath;
Upload up(api, token);
up.uploadSongWithMetadata(album, song, cover);
}
void CommitManager::multiTargetUpload(const std::string &sourcePath)
{
APIParser apiPrs(icaAction);
auto api = apiPrs.retrieveAPI();
const auto token = parseToken(api);
if (!fs::is_directory(sourcePath))
{
cout<<sourcePath<<" is not a directory\n";
std::exit(-1);
}
std::vector<Song> 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 "<<stem<<" Extension "<<extension<<"\n";
auto validImg = [](const std::string& ext)
{
std::vector<string> 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, std::string>(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<std::string>();
album.albumArtist = serialized["album_artist"].get<std::string>();
album.genre = serialized["genre"].get<std::string>();
album.year = serialized["year"].get<int>();
album.trackCount = serialized["track_count"].get<int>();
album.discCount = serialized["disc_count"].get<int>();
album.songs.reserve(album.trackCount);
for (auto &j : serialized["tracks"])
{
Song song;
song.title = j["title"].get<std::string>();
song.track = j["track"].get<int>();
song.disc = j["disc"].get<int>();
song.artist = j["artist"].get<std::string>();
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<<file.rdbuf();
file.close();
value.assign(buffer.str());
return value;
}
#pragma endregion
void CommitManager::Album::printInfo()
{
std::cout<<"Album: "<<this->album<<"\n";
std::cout<<"Album Artist: "<<this->albumArtist<<"\n";
std::cout<<"Genre: "<<this->genre<<"\n";
std::cout<<"Year: "<<this->year<<"\n";
std::cout<<"Track count: "<<this->trackCount<<"\n";
std::cout<<"Disc count: "<<this->discCount<<"\n";
std::cout<<"\n";
}
#pragma region Functions
} }
+7
View File
@@ -11,14 +11,18 @@ using std::string;
namespace Managers namespace Managers
{ {
#pragma region Constructors
FileManager::FileManager() {} FileManager::FileManager() {}
FileManager::FileManager(string filePath) FileManager::FileManager(string filePath)
{ {
this->filePath = filePath; this->filePath = filePath;
readFile(); readFile();
} }
#pragma endregion
#pragma region Functions
void FileManager::saveFile(string newFilePath) void FileManager::saveFile(string newFilePath)
{ {
if (!fileRead) if (!fileRead)
@@ -63,4 +67,7 @@ namespace Managers
} }
int FileManager::retrieveFileBufferLength() const { return fileBufferLength; } int FileManager::retrieveFileBufferLength() const { return fileBufferLength; }
#pragma endregion
} }
+6 -4
View File
@@ -17,7 +17,8 @@ using Models::User;
namespace Managers namespace Managers
{ {
#pragma
#pragma region Constructors
TokenManager::TokenManager(const User& user) TokenManager::TokenManager(const User& user)
{ {
this->user = user; this->user = user;
@@ -29,10 +30,10 @@ namespace Managers
this->api.endpoint = "api/" + api.version this->api.endpoint = "api/" + api.version
+ "/login"; + "/login";
} }
#pragma Constructors #pragma endregion
#pragma #pragma region Functions
Token TokenManager::requestToken() Token TokenManager::requestToken()
{ {
Token token{}; Token token{};
@@ -56,5 +57,6 @@ namespace Managers
return token; return token;
} }
#pragma Functions #pragma endregion
} }
+6 -4
View File
@@ -12,7 +12,8 @@ using Models::User;
namespace Managers namespace Managers
{ {
#pragma
#pragma region Constructors
UserManager::UserManager(User user) UserManager::UserManager(User user)
{ {
this->user = user; this->user = user;
@@ -23,10 +24,10 @@ namespace Managers
this->user = User{}; this->user = User{};
parseUserFromActions(); parseUserFromActions();
} }
#pragma Constructors #pragma endregion
#pragma #pragma region Functions
User UserManager::retrieveUser() const User UserManager::retrieveUser() const
{ {
return user; return user;
@@ -49,5 +50,6 @@ namespace Managers
} }
} }
} }
#pragma Functions #pragma endregion
} }
+22
View File
@@ -0,0 +1,22 @@
#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();
}
}
+6 -5
View File
@@ -10,7 +10,8 @@ using Models::IcarusAction;
namespace Parsers namespace Parsers
{ {
#pragma
#pragma region Constructors
APIParser::APIParser(IcarusAction icaAct) : icaAct(icaAct) APIParser::APIParser(IcarusAction icaAct) : icaAct(icaAct)
{ {
api = API{}; api = API{};
@@ -19,7 +20,7 @@ namespace Parsers
#pragma endregion #pragma endregion
#pragma #pragma region Functions
API APIParser::retrieveAPI() const API APIParser::retrieveAPI() const
{ {
return api; return api;
@@ -40,13 +41,13 @@ namespace Parsers
api.url = (value[value.size()-1] == '/') ? value : value + "/"; api.url = (value[value.size()-1] == '/') ? value : value + "/";
break; break;
} }
} }
// TODO: For now I will hard code // NOTE: For now I will hard code
// the api version since I am only // the api version since I am only
// on version 1 // on version 1
api.version = "v1"; api.version = "v1";
} }
#pragma functions #pragma endregion
} }
+6 -4
View File
@@ -16,16 +16,17 @@ using Models::Token;
namespace Syncers namespace Syncers
{ {
#pragma
#pragma region Constructors
Delete::Delete(API api) Delete::Delete(API api)
{ {
this->api = api; this->api = api;
this->api.endpoint = "song/data"; this->api.endpoint = "song/data";
} }
#pragma Constructors #pragma endregion
#pragma #pragma region Functions
void Delete::deleteSong(const Token token, Song song) void Delete::deleteSong(const Token token, Song song)
{ {
try try
@@ -58,5 +59,6 @@ namespace Syncers
return url; return url;
} }
#pragma Functions #pragma endregion
} }
+6 -4
View File
@@ -18,7 +18,8 @@ using Models::Token;
namespace Syncers namespace Syncers
{ {
#pragma
#pragma region Constructors
Download::Download() { } Download::Download() { }
Download::Download(API api) Download::Download(API api)
{ {
@@ -29,10 +30,10 @@ namespace Syncers
{ {
downloadFilePath = filePath; downloadFilePath = filePath;
} }
#pragma Constructors #pragma endregion
#pragma #pragma region Functions
void Download::downloadSong(const Token token, Song song) void Download::downloadSong(const Token token, Song song)
{ {
try try
@@ -87,5 +88,6 @@ namespace Syncers
saveSong.write(data, bufferLength); saveSong.write(data, bufferLength);
saveSong.close(); saveSong.close();
} }
#pragma Functions #pragma endregion
} }
+5
View File
@@ -20,10 +20,13 @@ using Utilities::Conversions;
namespace Syncers namespace Syncers
{ {
#pragma region Constructors
RetrieveRecords::RetrieveRecords() { } RetrieveRecords::RetrieveRecords() { }
RetrieveRecords::RetrieveRecords(API api, Token token) RetrieveRecords::RetrieveRecords(API api, Token token)
: token(token), api(api) { } : token(token), api(api) { }
#pragma endregion
#pragma region Functions
void RetrieveRecords::retrieve(CommitManager::RetrieveTypes type) void RetrieveRecords::retrieve(CommitManager::RetrieveTypes type)
{ {
switch (type) switch (type)
@@ -59,4 +62,6 @@ namespace Syncers
writeData<<songData.dump(4); writeData<<songData.dump(4);
writeData.close(); writeData.close();
} }
#pragma endregion
} }
+87 -31
View File
@@ -2,12 +2,13 @@
#include <filesystem> #include <filesystem>
#include <exception> #include <exception>
#include<cpr/cpr.h> #include "cpr/cpr.h"
#include<nlohmann/json.hpp>
#include "Syncers/Upload.h" #include "Syncers/Upload.h"
#include "Utilities/Conversions.h"
using std::cout; using std::cout;
using std::cin;
using std::endl; using std::endl;
using std::exception; using std::exception;
using std::string; using std::string;
@@ -23,22 +24,21 @@ using namespace cpr;
namespace Syncers namespace Syncers
{ {
Upload::Upload() { }
Upload::Upload(API api) : api(api) #pragma region Constructors
{ #pragma endregion
this->api.endpoint = "song/data";
}
Song Upload::uploadSong(const Models::Token& token, Song& song) #pragma region Functions
Song Upload::uploadSong(Song& song)
{ {
try try
{ {
auto url = retrieveUrl(); auto url = retrieveUrl();
cout<<"url "<<url<<endl; cout<<"url "<<url<<endl;
string auth{token.tokenType}; string auth{this->m_token.tokenType};
auth.append(" " + token.accessToken); auth.append(" " + this->m_token.accessToken);
auto r = cpr::Post(cpr::Url{url}, auto r = cpr::Post(cpr::Url{url},
cpr::Multipart{{"key", "small value"}, cpr::Multipart{{"key", "small value"},
{"file", cpr::File{song.songPath}}}, {"file", cpr::File{song.songPath}}},
@@ -46,6 +46,7 @@ namespace Syncers
); );
cout << "status code: " << r.status_code<< std::endl; cout << "status code: " << r.status_code<< std::endl;
cout << r.text << endl;
auto result = nlohmann::json::parse(r.text); auto result = nlohmann::json::parse(r.text);
cout<<"Finished"<<endl; cout<<"Finished"<<endl;
song.id = result["id"].get<int>(); song.id = result["id"].get<int>();
@@ -59,7 +60,7 @@ namespace Syncers
return song; return song;
} }
catch (exception e) catch (exception& e)
{ {
auto msg = e.what(); auto msg = e.what();
cout<<msg<<endl; cout<<msg<<endl;
@@ -68,16 +69,32 @@ namespace Syncers
return song; return song;
} }
void Upload::uploadSongsFromDirectory(const Models::Token& token, void Upload::uploadSongsFromDirectory(const std::string& directory,
const std::string& directory, const bool noConfirm, bool recursive = false)
bool recursive = false)
{ {
try try
{ {
auto songs = retrieveAllSongsFromDirectory(directory, recursive); auto songs = retrieveAllSongsFromDirectory(directory, recursive);
auto confirmUpload = true;
while (!noConfirm)
{
auto answer = 'a';
cout << "are you sure you want to upload " << songs.size() << " songs? [y/n]";
cin >> answer;
Utilities::Conversions::toLowerChar(answer);
if (answer == 'y' || answer == 'Y')
{
confirmUpload = true;
break;
}
}
cout << "uploading songs\n";
for (auto& song: songs) for (auto& song: songs)
{ {
song = uploadSong(token, song); song = uploadSong(song);
} }
} }
catch (exception& e) catch (exception& e)
@@ -87,10 +104,57 @@ namespace Syncers
} }
void Upload::uploadSongWithMetadata(Managers::CommitManager::Album &album, Models::Song& song, Models::CoverArt &cover)
{
this->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"<<meta<<"\n";
cout << "Filepath: " << song.song_path() << "\n";
auto multipart = cpr::Multipart{{"cover", cpr::File{cover.path}},
{"metadata", meta},
{"file", cpr::File{song.song_path()}}};
auto r = cpr::Post(cpr::Url{url}, multipart,
cpr::Header{{"authorization", auth}}
);
cout << "status code: " << r.status_code<< std::endl;
cout << r.text << endl;
}
catch (exception &e)
{
auto msg = e.what();
cout<<"Error: "<<msg<<"\n";
}
}
std::vector<Song> Upload::retrieveAllSongsFromDirectory(const std::string& directory, std::vector<Song> Upload::retrieveAllSongsFromDirectory(const std::string& directory,
bool recursive) bool recursive)
{ {
std::vector<Song> allSongs; std::vector<Song> allSongs;
if (recursive) if (recursive)
{ {
for (auto p: fs::recursive_directory_iterator(directory)) for (auto p: fs::recursive_directory_iterator(directory))
@@ -141,18 +205,8 @@ namespace Syncers
} }
#pragma #pragma region Testing
void Upload::printSongDetails()
{
cout<<"Song details: "<<endl;
cout<<"Id: "<<song.id<<endl;
cout<<"Title: "<<song.title<<endl;
cout<<"Artist: "<<song.artist<<endl;
cout<<"Album: "<<song.album<<endl;
cout<<"Genre: "<<song.genre<<endl;
cout<<"Year: "<<song.year<<endl;
cout<<"Duration: "<<song.duration<<endl;
}
void Upload::printSongDetails(std::vector<Song>& songs) void Upload::printSongDetails(std::vector<Song>& songs)
{ {
for (auto& song: songs) for (auto& song: songs)
@@ -168,7 +222,8 @@ namespace Syncers
cout<<"Path: "<<song.songPath<<endl; cout<<"Path: "<<song.songPath<<endl;
} }
} }
void Upload::printJsonData(json obj)
void Upload::printJsonData(const json& obj)
{ {
cout<<endl<<endl<<"JSon data: "<<endl; cout<<endl<<endl<<"JSon data: "<<endl;
cout<<"id: "<<obj["id"]<<endl; cout<<"id: "<<obj["id"]<<endl;
@@ -180,8 +235,9 @@ namespace Syncers
cout<<"duration: "<<obj["duration"]<<endl; cout<<"duration: "<<obj["duration"]<<endl;
cout<<"song_data: "<<obj["song_data"]<<endl; cout<<"song_data: "<<obj["song_data"]<<endl;
cout<<endl<<endl;; cout<<endl<<endl;
} }
#pragma Testing #pragma endregion
#pragma Functions #pragma endregion
} }
+5
View File
@@ -4,12 +4,15 @@ using std::unique_ptr;
namespace UI namespace UI
{ {
#pragma region Constructors
AboutWindow::AboutWindow(QWidget* parent): QDialog(parent) AboutWindow::AboutWindow(QWidget* parent): QDialog(parent)
{ {
setupWindow(); setupWindow();
} }
#pragma endregion
#pragma region Functions
void AboutWindow::setupWindow() void AboutWindow::setupWindow()
{ {
windowWidth = 250; windowWidth = 250;
@@ -44,4 +47,6 @@ namespace UI
{ {
this->hide(); this->hide();
} }
#pragma endregion
} }
+6
View File
@@ -17,13 +17,17 @@ using Syncers::Upload;
namespace UI namespace UI
{ {
#pragma region Constructors
MainWindow::MainWindow() MainWindow::MainWindow()
{ {
setupMainWindow(); setupMainWindow();
aboutWindow = unique_ptr<AboutWindow>{new AboutWindow}; aboutWindow = unique_ptr<AboutWindow>{new AboutWindow};
} }
#pragma endregion
#pragma region Functions
void MainWindow::configureDownloadSection() void MainWindow::configureDownloadSection()
{ {
} }
@@ -171,4 +175,6 @@ namespace UI
uploadSongQt->setEnabled(true); uploadSongQt->setEnabled(true);
} }
#pragma endregion
} }
+4 -2
View File
@@ -7,6 +7,7 @@ using std::unique_ptr;
namespace Utilities namespace Utilities
{ {
Conversions::Conversions() Conversions::Conversions()
{ {
initializeValues(); initializeValues();
@@ -18,7 +19,8 @@ namespace Utilities
template <typename T> template <typename T>
void Conversions::printValue(T val) void Conversions::printValue(T val)
{ {
std::cout<<"going to print value"<<std::endl; std::cout<<"going to print value\n";
std::cout<<val<<std::endl; std::cout<<val<< "\n";
} }
} }