diff --git a/.gitmodules b/.gitmodules index e85d8af..2f4664b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "bindings/lib/anitomy"] path = bindings/lib/anitomy url = https://github.com/erengy/anitomy +[submodule "bindings/lib/libtorrent"] + path = bindings/lib/libtorrent + url = https://github.com/arvidn/libtorrent diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index 2b96516..a903f1c 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -3,7 +3,8 @@ cmake_minimum_required(VERSION 3.12.0 FATAL_ERROR) # Name of the project (will be the name of the plugin) project(kawabinds) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_BUILD_TYPE Release) # Essential include files to build a node addon, # you should add this line in every CMake.js based project. @@ -15,17 +16,21 @@ file( SOURCE_FILES "src/*.cc" "src/*.h" "src/torrent/*.cc" "src/torrent/*.h" + "src/name_parser/*.cc" "src/name_parser/*.h" + + "lib/anitomy/anitomy/*.cpp" "lib/anitomy/anitomy/*.h" ) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) -set(ANITOMY_INCLUDE_DIR "lib/anitomy") -target_include_directories(${PROJECT_NAME} PRIVATE ${ANITOMY_INCLUDE_DIR}) +target_include_directories(${PROJECT_NAME} PRIVATE "lib/anitomy") ## Libtorrent # Checking Version -find_package(LibtorrentRasterbar 1.2 REQUIRED) - # Getting installed version of libtorrent +find_package(LibtorrentRasterbar 1.2 REQUIRED) +# set(LIBTORRENT_DIR "lib/libtorrent") +# add_subdirectory(${LIBTORRENT_DIR}) + find_path(LIBTORRENT_INCLUDE_PATH libtorrent) find_library(LIBTORRENT_LIB torrent-rasterbar) @@ -34,9 +39,9 @@ target_link_libraries(${PROJECT_NAME} ${LIBTORRENT_LIB}) # Include N-API wrappers execute_process(COMMAND node -p "require('node-addon-api').include" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE NODE_ADDON_API_DIR - ) + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE NODE_ADDON_API_DIR +) string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR}) diff --git a/bindings/example.js b/bindings/example.js index 8bf109c..d5a93f4 100644 --- a/bindings/example.js +++ b/bindings/example.js @@ -1,46 +1,3 @@ const addon = require('./build/Release/kawabinds') -let intervalId -console.log(addon) -const client = new addon.torrent.Client() - -console.log( - client.addTorrent( - '/Users/kylart/Downloads/blabla', - 'magnet:?xt=urn:btih:600f816632f326168b3160fabbdf282ef8e23ab8&dn=%5BHorribleSubs%5D%20Azur%20Lane%20-%2002%20%5B720p%5D.mkv&tr=http%3A%2F%2Fnyaa.tracker.wf%3A7777%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce' - ) -) - -setTimeout(() => { - console.log('pausing') - client.destroy() - console.log('destroyed') - const paused = client.pauseTorrent(client.hasTorrents() && client.getTorrents()[0].id) - - console.log(paused) - - if (paused) { - console.log('paused gg') - // clearInterval(intervalId) - } -}, 2000) - -// setTimeout(() => { -// console.log('removing') -// const resumed = client.removeTorrent(client.hasTorrents() && client.getTorrents()[0].id) - -// if (resumed) { -// console.log('resumed gg') -// // clearInterval(intervalId) -// } -// }, 5000) - -intervalId = setInterval(() => { - const torrents = client.getTorrents() - - console.log('got info') - // console.log(torrents) - // console.log(client.getClientInfo()) - - if (client.hasTorrents() && torrents[0].done) clearInterval(intervalId) -}, 1000) +console.log(addon.parseName('[Ouroboros]_Fullmetal_Alchemist_Brotherhood_-_01.mkv')) diff --git a/bindings/lib/libtorrent b/bindings/lib/libtorrent new file mode 160000 index 0000000..b266298 --- /dev/null +++ b/bindings/lib/libtorrent @@ -0,0 +1 @@ +Subproject commit b26629885bf07679b71455289b1b7bd276b1b67d diff --git a/bindings/src/addon.cc b/bindings/src/addon.cc index 2478d0e..d6ffcc2 100644 --- a/bindings/src/addon.cc +++ b/bindings/src/addon.cc @@ -1,11 +1,11 @@ #include #include "torrent/bind.h" - -#include +#include "name_parser/bind.h" Napi::Object Init(Napi::Env env, Napi::Object exports) { Torrent::SetUp(env, exports); + NameParser::SetUp(env, exports); return exports; } diff --git a/bindings/src/name_parser/bind.cc b/bindings/src/name_parser/bind.cc new file mode 100644 index 0000000..9c19395 --- /dev/null +++ b/bindings/src/name_parser/bind.cc @@ -0,0 +1,9 @@ +#include "bind.h" + +namespace NameParser { + +void SetUp (Napi::Env env, Napi::Object exports) { + exports.Set("parseName", Napi::Function::New(env, Parser::parse)); +} + +} // namespace NameParser \ No newline at end of file diff --git a/bindings/src/name_parser/bind.h b/bindings/src/name_parser/bind.h new file mode 100644 index 0000000..15778d5 --- /dev/null +++ b/bindings/src/name_parser/bind.h @@ -0,0 +1,9 @@ +#include + +#include "parse.h" + +namespace NameParser { + +void SetUp (Napi::Env env, Napi::Object exports); + +} // namespace NameParser \ No newline at end of file diff --git a/bindings/src/name_parser/parse.cc b/bindings/src/name_parser/parse.cc new file mode 100644 index 0000000..8303afa --- /dev/null +++ b/bindings/src/name_parser/parse.cc @@ -0,0 +1,22 @@ +#include "parse.h" + +namespace Parser { + +Napi::Value parse (const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + if (info.Length() < 1) { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + Napi::String name = info[0].As(); + + Wrapper::Wrapper anitomy_wrapper; + anitomy_wrapper.SetInput(name, env); + anitomy_wrapper.Parse(); + + return anitomy_wrapper.ParsedResult(env); +} + +} // namespace Parser \ No newline at end of file diff --git a/bindings/src/name_parser/parse.h b/bindings/src/name_parser/parse.h new file mode 100644 index 0000000..a095d18 --- /dev/null +++ b/bindings/src/name_parser/parse.h @@ -0,0 +1,15 @@ +#include + +#include + +#include +#include +#include + +#include "wrapper.h" + +namespace Parser { + +Napi::Value parse (const Napi::CallbackInfo& info); + +} // namespace Parser diff --git a/bindings/src/name_parser/wrapper.cc b/bindings/src/name_parser/wrapper.cc new file mode 100644 index 0000000..1472e9c --- /dev/null +++ b/bindings/src/name_parser/wrapper.cc @@ -0,0 +1,109 @@ +#include "wrapper.h" + +namespace Wrapper { + +void Wrapper::SetInput(Napi::String value, Napi::Env env) { + this->input_ = ToWideString(value, env); +} + +void Wrapper::Parse() { + this->anitomy_.Parse(this->input_); + this->parsed_ = this->anitomy_.elements(); +} + +anitomy::Elements Wrapper::Parsed() { return this->parsed_; } + +Napi::Value Wrapper::ParsedResult(Napi::Env env) { + Napi::Object result = Napi::Object::New(env); + + return BuildObject(this->parsed_, env); +} + +// From https://stackoverflow.com/a/39018368/10611946 +std::wstring Wrapper::ToWideString(Napi::String input, Napi::Env env) { + std::wstring result; + std::string _input = input.Utf8Value(); + + try + { + std::wstring_convert> converter; + return converter.from_bytes(_input); + } + catch(std::range_error& e) + { + size_t length = _input.length(); + std::wstring result; + result.reserve(length); + for(size_t i = 0; i < length; i++) + { + result.push_back(_input[i] & 0xFF); + } + return result; + } +} + +std::string Wrapper::ToStr(anitomy::string_t str) { + std::wstring ws_value(str.c_str()); + return std::string(ws_value.begin(), ws_value.end()); +} + +void Wrapper::SetEntry(Napi::Object &object, Napi::Env env, const char *entry, anitomy::Elements &elements, anitomy::ElementCategory pos) { + Napi::String entry_name = Napi::String::New(env, entry); + + switch (elements.count(pos)) { + case 0: + break; + case 1: + object.Set(entry_name.Utf8Value(), ToStr(elements.get(pos)).c_str()); + break; + default: + object.Set(entry_name, CategoryArray(elements, pos, env)); + } +} + +Napi::Array Wrapper::CategoryArray(anitomy::Elements &elements, anitomy::ElementCategory pos, Napi::Env env) { + std::vector category_elements = elements.get_all(pos); + Napi::Array output = Napi::Array::New(env); + unsigned int index = 0; + + for (anitomy::string_t value : category_elements) { + output.Set(index, Napi::String::New(env, ToStr(value).c_str())); + index++; + } + + return output; +} + +Napi::Object Wrapper::BuildObject(anitomy::Elements &elements, Napi::Env env) { + Napi::Object result = Napi::Object::New(env); + + SetEntry(result, env, "anime_season", elements, anitomy::kElementAnimeSeason); + SetEntry(result, env, "season_prefix", elements, anitomy::kElementAnimeSeasonPrefix); + SetEntry(result, env, "anime_title", elements, anitomy::kElementAnimeTitle); + SetEntry(result, env, "anime_type", elements, anitomy::kElementAnimeType); + SetEntry(result, env, "anime_year", elements, anitomy::kElementAnimeYear); + SetEntry(result, env, "audio_term", elements, anitomy::kElementAudioTerm); + SetEntry(result, env, "device_compatibility", elements, anitomy::kElementDeviceCompatibility); + SetEntry(result, env, "episode_number", elements, anitomy::kElementEpisodeNumber); + SetEntry(result, env, "episode_number_alt", elements, anitomy::kElementEpisodeNumberAlt); + SetEntry(result, env, "episode_prefix", elements, anitomy::kElementEpisodePrefix); + SetEntry(result, env, "episode_title", elements, anitomy::kElementEpisodeTitle); + SetEntry(result, env, "file_checksum", elements, anitomy::kElementFileChecksum); + SetEntry(result, env, "file_extension", elements, anitomy::kElementFileExtension); + SetEntry(result, env, "file_name", elements, anitomy::kElementFileName); + SetEntry(result, env, "language", elements, anitomy::kElementLanguage); + SetEntry(result, env, "other", elements, anitomy::kElementOther); + SetEntry(result, env, "release_group", elements, anitomy::kElementReleaseGroup); + SetEntry(result, env, "release_information", elements, anitomy::kElementReleaseInformation); + SetEntry(result, env, "release_version", elements, anitomy::kElementReleaseVersion); + SetEntry(result, env, "source", elements, anitomy::kElementSource); + SetEntry(result, env, "subtitles", elements, anitomy::kElementSubtitles); + SetEntry(result, env, "video_resolution", elements, anitomy::kElementVideoResolution); + SetEntry(result, env, "video_term", elements, anitomy::kElementVideoTerm); + SetEntry(result, env, "volume_number", elements, anitomy::kElementVolumeNumber); + SetEntry(result, env, "volume_prefix", elements, anitomy::kElementVolumePrefix); + SetEntry(result, env, "unknown", elements, anitomy::kElementUnknown); + + return result; +} +} // namespace Wrapper diff --git a/bindings/src/name_parser/wrapper.h b/bindings/src/name_parser/wrapper.h new file mode 100644 index 0000000..ea47593 --- /dev/null +++ b/bindings/src/name_parser/wrapper.h @@ -0,0 +1,33 @@ +#include + +#include +#include +#include +#include + +#include + +namespace Wrapper { + +class Wrapper { +public: + void SetInput(Napi::String value, Napi::Env env); + void Parse(); + + anitomy::Elements Parsed(); + Napi::Value ParsedResult(Napi::Env env); + +private: + anitomy::Anitomy anitomy_; + std::wstring input_; + + anitomy::Elements parsed_; + + std::wstring ToWideString(Napi::String str, Napi::Env env); + std::string ToStr(anitomy::string_t str); + + Napi::Object BuildObject(anitomy::Elements &elements, Napi::Env env); + void SetEntry(Napi::Object &object, Napi::Env env, const char *entry, anitomy::Elements &elements, anitomy::ElementCategory pos); + Napi::Array CategoryArray(anitomy::Elements &elements, anitomy::ElementCategory pos, Napi::Env env); +}; +} // namespace Wrapper \ No newline at end of file