From fb35fa5ed25717807d536130f351ed536566ed0b Mon Sep 17 00:00:00 2001 From: Slavasil Date: Fri, 15 Nov 2024 22:48:24 +0300 Subject: [PATCH] create VKClient with get_posts() method to get wall posts --- .gitmodules | 3 ++ CMakeLists.txt | 5 ++-- json | 1 + vk.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ vk.h | 38 ++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 2 deletions(-) create mode 160000 json create mode 100644 vk.cpp create mode 100644 vk.h diff --git a/.gitmodules b/.gitmodules index b2802bf..879ec8c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "curl"] path = curl url = git@github.com:curl/curl.git +[submodule "json"] + path = json + url = git@github.com:nlohmann/json.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d316cb..1da57fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,11 @@ cmake_minimum_required(VERSION 3.5) project(mmcs-quotes-bridge LANGUAGES CXX) add_subdirectory(curl) +add_subdirectory(json) add_subdirectory(libuv) add_subdirectory(spdlog) add_subdirectory(td) -add_executable(${PROJECT_NAME} main.cpp http.cpp) +add_executable(${PROJECT_NAME} main.cpp http.cpp vk.cpp) -target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl uv spdlog::spdlog Td::TdStatic $<$:ws2_32>) +target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl nlohmann_json::nlohmann_json uv spdlog::spdlog Td::TdStatic $<$:ws2_32>) diff --git a/json b/json new file mode 160000 index 0000000..fde9a86 --- /dev/null +++ b/json @@ -0,0 +1 @@ +Subproject commit fde9a86c5ad9c671662c0e9802b621f2de3cf60a diff --git a/vk.cpp b/vk.cpp new file mode 100644 index 0000000..5a8a776 --- /dev/null +++ b/vk.cpp @@ -0,0 +1,78 @@ +#include "vk.h" +#include "curl/curl.h" +#include "http.h" +#include "spdlog/sinks/stdout_color_sinks.h" +#include +#include + +using namespace vk; +using namespace nlohmann; + +const char *API_BASE_URL = "https://api.vk.com/method/"; +const char *API_VERSION = "5.199"; +const char *LOGGER_TAG = "vk"; + +VKClient::VKClient(uv_loop_t *eventLoop) : m_httpClient(eventLoop) { + m_logger = spdlog::get(LOGGER_TAG); + if (!m_logger) { + m_logger = spdlog::stdout_color_mt(LOGGER_TAG); + m_logger->set_level(spdlog::level::debug); + } +}; + +VKClient::VKClient(uv_loop_t *eventLoop, std::string serviceKey) : VKClient(eventLoop) { + set_service_api_key(serviceKey); +} + +void VKClient::set_service_api_key(std::string key) { + m_serviceApiKey = {key}; +} + +void VKClient::get_posts(std::variant wall, int offset, int count, std::function, int)> callback) { + if (!m_serviceApiKey) { + m_logger->error("get_posts called without authorization"); + return; + } + std::string url(API_BASE_URL); + url += "wall.get?access_token="; + url += *m_serviceApiKey; + url += "&v="; + url += API_VERSION; + url += "&offset="; + url += std::to_string(offset); + url += "&count="; + url += std::to_string(count); + if (wall.index() == 0) { + url += "&owner_id="; + url += std::to_string(std::get(wall)); + } else { + url += "&domain="; + url += std::get(wall); + } + m_logger->debug("using URL: {}", url); + + m_httpClient.send_request("GET", url, {}, [this, callback](std::unique_ptr resp, CURLcode r){ + if (r == 0) { + auto parsedResponse = json::parse(resp->body); + + if (parsedResponse.contains("error")) { + auto err = parsedResponse["error"]; + m_logger->error("get_posts error {} {}", (int)err["error_code"], (std::string)err["error_msg"]); + callback({}, -1); + return; + } + + auto responsePayload = parsedResponse["response"]; + int count = responsePayload["count"]; + std::vector posts; + for (auto post : responsePayload["items"]) { + posts.emplace_back(post["id"], post["date"], post["edited"], post["from_id"], post["type"], post["text"]); + } + + callback({{count, std::move(posts)}}, 0); + } else { + m_logger->error("get_posts network error"); + callback({}, r); + } + }); +} \ No newline at end of file diff --git a/vk.h b/vk.h new file mode 100644 index 0000000..e4d41f2 --- /dev/null +++ b/vk.h @@ -0,0 +1,38 @@ +#pragma once +#include "http.h" +#include "spdlog/logger.h" +#include "uv.h" +#include +#include +#include +#include + +namespace vk { + using namespace http; + + struct Post { + Post(long id, long date, long editDate, long fromId, std::string postType, std::string text); + + long id, date, editDate, fromId; + std::string postType, text; + }; + + struct WallChunk { + int count; + std::vector posts; + }; + + class VKClient { + public: + VKClient(uv_loop_t *eventLoop); + VKClient(VKClient&) = delete; + VKClient(uv_loop_t *eventLoop, std::string serviceKey); + + void set_service_api_key(std::string key); + void get_posts(std::variant wall, int offset, int count, std::function, int)> callback); + private: + HttpClient m_httpClient; + std::optional m_serviceApiKey; + std::shared_ptr m_logger; + }; +} \ No newline at end of file