From d306f261bd775d7b6e2463b96c3daf49ca364cbe Mon Sep 17 00:00:00 2001 From: shell Date: Thu, 18 Jun 2026 00:20:39 +0800 Subject: [PATCH] initial commit --- .gitignore | 2 + CMakeLists.txt | 76 +++++++++++++++++++++ include/seafile/auth_token.hpp | 16 +++++ include/seafile/exception.hpp | 18 +++++ include/seafile/seafile_api.hpp | 115 ++++++++++++++++++++++++++++++++ include/seafile/server_info.hpp | 32 +++++++++ src/main.cpp | 15 +++++ vcpkg.json | 28 ++++++++ 8 files changed, 302 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 include/seafile/auth_token.hpp create mode 100644 include/seafile/exception.hpp create mode 100644 include/seafile/seafile_api.hpp create mode 100644 include/seafile/server_info.hpp create mode 100644 src/main.cpp create mode 100644 vcpkg.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e24b65 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +cmake-build-debug diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0160439 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,76 @@ +cmake_minimum_required(VERSION 4.2) +project(seadisk C CXX) + +set(CMAKE_CXX_STANDARD 20) + +find_package(tl-expected CONFIG REQUIRED) +find_package(nlohmann_json CONFIG REQUIRED) +find_package(date CONFIG REQUIRED) +find_package(cpr CONFIG REQUIRED) +find_package(argparse CONFIG REQUIRED) +find_package(ada CONFIG REQUIRED) + +cmake_host_system_information( + RESULT WINFSP_DIR + QUERY WINDOWS_REGISTRY + "HKLM\\SOFTWARE\\WinFsp" + VALUE "InstallDir" +) + +message(STATUS "WinFsp=${WINFSP_DIR}") + +set(WINFSP_INCLUDE_DIR "${WINFSP_DIR}/inc") + +message(STATUS "${CMAKE_SYSTEM_PROCESSOR}") +if (CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|x86_64") + set(WINFSP_PLATFORM x64) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64") + set(WINFSP_PLATFORM a64) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "X86|i386|i686") + set(WINFSP_PLATFORM x86) +endif () + +set(WINFSP_LIB "winfsp-${WINFSP_PLATFORM}.lib") + +message(STATUS "WinFSP lib: ${WINFSP_LIB}") + +add_executable(seadisk src/main.cpp + include/seafile/seafile_api.hpp + include/seafile/exception.hpp + include/seafile/server_info.hpp + include/seafile/auth_token.hpp +) + +target_compile_definitions(seadisk PRIVATE + UNICODE + _UNICODE +) + +target_include_directories(seadisk PRIVATE + "${WINFSP_INCLUDE_DIR}" + include +) + +target_link_directories(seadisk PRIVATE + "${WINFSP_DIR}/lib" +) + +target_link_libraries(seadisk PRIVATE + ${WINFSP_LIB} + delayimp + tl::expected + nlohmann_json::nlohmann_json + date::date + date::date-tz + cpr::cpr + argparse::argparse + ada::ada +) + +target_link_options(seadisk PRIVATE + "/DELAYLOAD:winfsp-${WINFSP_PLATFORM}.dll" +) + +target_compile_options(seadisk PRIVATE + /Zc:preprocessor +) \ No newline at end of file diff --git a/include/seafile/auth_token.hpp b/include/seafile/auth_token.hpp new file mode 100644 index 0000000..a756efe --- /dev/null +++ b/include/seafile/auth_token.hpp @@ -0,0 +1,16 @@ +// +// Created by Shell on 2026/6/18. +// + +#ifndef SEADISK_AUTH_TOKEN_HPP +#define SEADISK_AUTH_TOKEN_HPP + +namespace seafile { + struct AuthToken final { + std::string token; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(AuthToken, token); + }; +} + +#endif //SEADISK_AUTH_TOKEN_HPP diff --git a/include/seafile/exception.hpp b/include/seafile/exception.hpp new file mode 100644 index 0000000..6e97abf --- /dev/null +++ b/include/seafile/exception.hpp @@ -0,0 +1,18 @@ +// +// Created by Shell on 2026/6/17. +// + +#ifndef SEADISK_EXCEPTION_HPP +#define SEADISK_EXCEPTION_HPP +#include + +namespace seafile { + class SeafileException : public std::runtime_error { + public: + explicit SeafileException(const std::string &msg) + : std::runtime_error(msg) { + } + }; +} + +#endif //SEADISK_EXCEPTION_HPP diff --git a/include/seafile/seafile_api.hpp b/include/seafile/seafile_api.hpp new file mode 100644 index 0000000..699cc44 --- /dev/null +++ b/include/seafile/seafile_api.hpp @@ -0,0 +1,115 @@ +// +// Created by Shell on 2026/6/17. +// + +#ifndef SEADISK_SEAFILE_API_HPP +#define SEADISK_SEAFILE_API_HPP +#include +#include +#include + +#include "exception.hpp" +#include +#include +#include + +#include "auth_token.hpp" +#include "server_info.hpp" + +namespace seafile { + class SeaFileApi final { + //base url of the seafile api server + std::string base_url; + + /** + * make a url string from given path + * @param path url path + * @return the whole url string + */ + std::string makeUrl(const std::string &path) { + auto url = ada::parse(this->base_url); + url->set_pathname(path); + return std::string(url->get_href()); + } + + template + tl::expected + parseResponse(const cpr::Response &response) { + if (response.error) { + return tl::make_unexpected( + SeafileException( + response.error.message)); + } + + if (response.status_code != 200) { + return tl::make_unexpected( + SeafileException( + std::format("Http Error: {}", + response.status_code))); + } + + try { + return nlohmann::json::parse(response.text) + .get(); + } catch (const std::exception &e) { + return tl::make_unexpected( + SeafileException(e.what())); + } + } + + /** + * post body and fetch result + * @tparam T return type + * @param path target url path + * @param body post body data + * @return T if success else SeafileException + */ + template + tl::expected post(const std::string &path, const nlohmann::json &body) { + const auto url = makeUrl(path); + auto response = cpr::Post( + cpr::Url{url}, + cpr::Header{ + {"accept", "application/json"}, + {"content-type", "application/json"} + }, cpr::Body{body.dump()}); + return parseResponse(response); + } + + public: + /** + * primary constructor + * @param base_url base url of seafile server + */ + explicit SeaFileApi(std::string base_url) : base_url(std::move(base_url)) { + } + + /** + * + * @param username username + * @param password password + * @return token when success else SeafileException + */ + tl::expected + authToken(const std::string &username, const std::string &password) { + const nlohmann::json body = { + {"username", username}, + {"password", password} + }; + return this->post("/api2/auth-token/", body); + } + + tl::expected + serverInfo() { + auto response = cpr::Get( + cpr::Url{makeUrl("/api2/server-info/")}, + cpr::Header{ + {"accept", "application/json"} + }); + + return parseResponse(response); + } + }; +} + +#endif //SEADISK_SEAFILE_API_HPP diff --git a/include/seafile/server_info.hpp b/include/seafile/server_info.hpp new file mode 100644 index 0000000..162cdcd --- /dev/null +++ b/include/seafile/server_info.hpp @@ -0,0 +1,32 @@ +// +// Created by Shell on 2026/6/17. +// + +#ifndef SEADISK_SERVER_INFO_HPP +#define SEADISK_SERVER_INFO_HPP +#include +#include + +namespace seafile { + /** + * seafile server info + */ + struct ServerInfo final { + /** + * server version + */ + std::string version; + /** + * encrypted library version + */ + int encrypted_library_version = 0; + /** + * supported features + */ + std::vector features; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(ServerInfo, version, encrypted_library_version, features); + }; +} + +#endif //SEADISK_SERVER_INFO_HPP diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..44df8c9 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,15 @@ +#include "seafile/seafile_api.hpp" +#include + +int main(int argc,char** argv) { + seafile::SeaFileApi api("https://pan.hanwangsoft.com/"); + if (const auto token = api.authToken("asypost@yeah.net","Shell0805@china"); token.has_value()) { + std::cout<().token<().version<=" : "3.2" + }, { + "name" : "nlohmann-json", + "version>=" : "3.12.0#2" + }, { + "name" : "cpr", + "features" : [ "ssl" ], + "version>=" : "1.14.2" + }, { + "name" : "date", + "version>=" : "3.0.4" + }, { + "name" : "icu", + "version>=" : "78.2" + }, { + "name" : "ada-url", + "version>=" : "3.4.4" + }, { + "name" : "tl-expected", + "version>=" : "1.3.1" + } ] +} \ No newline at end of file