Compare commits
35 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da40d7df49 | ||
|
|
f045eb22b2 | ||
|
|
d6194ec8be | ||
|
|
3bbd2c2818 | ||
|
|
dc4c430231 | ||
|
|
a6848bb4d7 | ||
|
|
b1c035ae35 | ||
|
|
a7b47c564a | ||
|
|
7e0222d6f1 | ||
|
|
19164b8d9d | ||
|
|
a22c96e7a0 | ||
|
|
20cf8b1fc2 | ||
|
|
ba4dfec459 | ||
|
|
847aec7bdd | ||
|
|
4ca8b19adb | ||
|
|
6123ee039b | ||
|
|
ccf9722bb7 | ||
|
|
0fdf577612 | ||
|
|
c815e96f4c | ||
|
|
d69f5fcddf | ||
|
|
b368ecc43b | ||
|
|
a8dd448c95 | ||
|
|
e09b6658b2 | ||
|
|
28a7d9e691 | ||
|
|
12648e1a8f | ||
|
|
7efd7bb6b0 | ||
|
|
bd309d38c6 | ||
|
|
167e2323be | ||
|
|
3d8abc3f0c | ||
|
|
cdc1aa2e6b | ||
|
|
ea29fa79f0 | ||
|
|
45a1df4cbb | ||
|
|
45ce5da0ac | ||
|
|
602e9b62d8 | ||
|
|
879a7981cd |
54 changed files with 5457 additions and 10 deletions
1
api/.gitignore
vendored
Normal file
1
api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
generated-client/
|
||||
59
api/_build/my-cpp-templates/cpp-restsdk/README.mustache
Normal file
59
api/_build/my-cpp-templates/cpp-restsdk/README.mustache
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# C++ API client
|
||||
|
||||
{{#appDescriptionWithNewLines}}
|
||||
{{{.}}}
|
||||
{{/appDescriptionWithNewLines}}
|
||||
|
||||
## Overview
|
||||
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI spec](https://openapis.org) from a remote server, you can easily generate an API client.
|
||||
|
||||
- API version: {{appVersion}}
|
||||
- Package version: {{packageVersion}}
|
||||
{{^hideGenerationTimestamp}}
|
||||
- Build date: {{generatedDate}}
|
||||
{{/hideGenerationTimestamp}}
|
||||
- Generator version: {{generatorVersion}}
|
||||
- Build package: {{generatorClass}}
|
||||
{{#infoUrl}}
|
||||
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
|
||||
{{/infoUrl}}
|
||||
|
||||
- API namespace: {{{apiPackage}}}
|
||||
- Model namespace: {{{modelPackage}}}
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Install [cpprestsdk](https://github.com/Microsoft/cpprestsdk).
|
||||
|
||||
- Windows: `vcpkg install cpprestsdk cpprestsdk:x64-windows boost-uuid boost-uuid:x64-windows`
|
||||
- Mac: `brew install cpprestsdk`
|
||||
- Linux: `sudo apt-get install libcpprest-dev`
|
||||
|
||||
### Build
|
||||
|
||||
```sh
|
||||
cmake -DCPPREST_ROOT=/usr -DCMAKE_CXX_FLAGS="-I/usr/local/opt/openssl/include" -DCMAKE_MODULE_LINKER_FLAGS="-L/usr/local/opt/openssl/lib"
|
||||
make
|
||||
```
|
||||
|
||||
### Build on Windows with Visual Studio (VS2017)
|
||||
|
||||
- Right click on folder containing source code
|
||||
- Select 'Open in visual studio'
|
||||
- Once visual studio opens, CMake should show up in top menu bar.
|
||||
- Select CMake > Build All.
|
||||
|
||||
*Note: If the CMake menu item doesn't show up in Visual Studio, CMake
|
||||
for Visual Studio must be installed. In this case, open the 'Visual Studio
|
||||
Installer' application. Select 'modify' Visual Studio 2017. Make sure
|
||||
'Desktop Development with C++' is installed, and specifically that 'Visual
|
||||
C++ tools for CMake' is selected in the 'Installation Details' section.
|
||||
|
||||
Also be sure to review the CMakeLists.txt file. Edits are likely required.*
|
||||
|
||||
## Author
|
||||
|
||||
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
|
||||
{{/-last}}{{/apis}}{{/apiInfo}}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* AnyType.h
|
||||
*
|
||||
* This is the implementation of an any JSON type.
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_AnyType_H_
|
||||
#define {{modelHeaderGuardPrefix}}_AnyType_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/Object.h"
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/json.h>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} AnyType : public Object {
|
||||
public:
|
||||
AnyType();
|
||||
virtual ~AnyType();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// ModelBase overrides
|
||||
void validate() override;
|
||||
|
||||
web::json::value toJson() const override;
|
||||
bool fromJson(const web::json::value &json) override;
|
||||
|
||||
void toMultipart(std::shared_ptr<MultipartFormData> multipart,
|
||||
const utility::string_t &namePrefix) const override;
|
||||
bool fromMultiPart(std::shared_ptr<MultipartFormData> multipart,
|
||||
const utility::string_t &namePrefix) override;
|
||||
|
||||
private:
|
||||
web::json::value m_value;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_AnyType_H_ */
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/AnyType.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
AnyType::AnyType() { m_value = web::json::value::null(); }
|
||||
|
||||
AnyType::~AnyType() {}
|
||||
|
||||
void AnyType::validate() {}
|
||||
|
||||
web::json::value AnyType::toJson() const { return m_value; }
|
||||
|
||||
bool AnyType::fromJson(const web::json::value &val) {
|
||||
m_value = val;
|
||||
m_IsSet = true;
|
||||
return isSet();
|
||||
}
|
||||
|
||||
void AnyType::toMultipart(std::shared_ptr<MultipartFormData> multipart,
|
||||
const utility::string_t &prefix) const {
|
||||
if (m_value.is_object()) {
|
||||
return Object::toMultipart(multipart, prefix);
|
||||
}
|
||||
throw std::runtime_error("AnyType::toMultipart: unsupported type");
|
||||
}
|
||||
|
||||
bool AnyType::fromMultiPart(std::shared_ptr<MultipartFormData> multipart,
|
||||
const utility::string_t &prefix) {
|
||||
if (m_value.is_object()) {
|
||||
return Object::fromMultiPart(multipart, prefix);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
41
api/_build/my-cpp-templates/cpp-restsdk/api-gmock.mustache
Normal file
41
api/_build/my-cpp-templates/cpp-restsdk/api-gmock.mustache
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{{>licenseInfo}}
|
||||
{{#operations}}
|
||||
#ifndef {{apiHeaderGuardPrefix}}_{{classname}}GMock_H_
|
||||
#define {{apiHeaderGuardPrefix}}_{{classname}}GMock_H_
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "{{classname}}.h"
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
|
||||
class {{declspec}} {{classname}}Mock : public I{{classname}}
|
||||
{
|
||||
public:
|
||||
using Base = I{{classname}};
|
||||
|
||||
{{classname}}Mock() = default;
|
||||
explicit {{classname}}Mock( std::shared_ptr<ApiClient> apiClient ) { };
|
||||
~{{classname}}Mock() override = default;
|
||||
|
||||
{{#operation}}
|
||||
MOCK_METHOD{{allParams.size}}( {{operationId}}, pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> (
|
||||
{{#allParams}}
|
||||
{{^required}}boost::optional<{{/required}}{{#isFile}}std::shared_ptr<{{/isFile}}{{{dataType}}}{{#isFile}}>{{/isFile}}{{^required}}>{{/required}} {{paramName}}{{^-last}},{{/-last}}
|
||||
{{/allParams}}
|
||||
) );
|
||||
{{/operation}}
|
||||
};
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{apiHeaderGuardPrefix}}_{{classname}}GMock_H_ */
|
||||
|
||||
{{/operations}}
|
||||
86
api/_build/my-cpp-templates/cpp-restsdk/api-header.mustache
Normal file
86
api/_build/my-cpp-templates/cpp-restsdk/api-header.mustache
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
{{>licenseInfo}}
|
||||
{{#operations}}/*
|
||||
* {{classname}}.h
|
||||
*
|
||||
* {{description}}
|
||||
*/
|
||||
|
||||
#ifndef {{apiHeaderGuardPrefix}}_{{classname}}_H_
|
||||
#define {{apiHeaderGuardPrefix}}_{{classname}}_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include "{{packageName}}/ApiClient.h"
|
||||
{{^hasModelImport}}#include "{{packageName}}/ModelBase.h"{{/hasModelImport}}
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
#include <boost/optional.hpp>
|
||||
#include <map> // <-- добавлено для std::map
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
{{#gmockApis}}
|
||||
class {{declspec}} I{{classname}}
|
||||
{
|
||||
public:
|
||||
I{{classname}}() = default;
|
||||
virtual ~I{{classname}}() = default;
|
||||
|
||||
{{#operation}}
|
||||
virtual pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{operationId}}(
|
||||
{{#allParams}}
|
||||
{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}},{{/allParams}}
|
||||
const std::map<utility::string_t, utility::string_t>& customHeaders = {} // <-- добавлено
|
||||
) const = 0;
|
||||
{{/operation}}
|
||||
};{{/gmockApis}}
|
||||
|
||||
class {{declspec}} {{classname}} {{#gmockApis}} : public I{{classname}} {{/gmockApis}}
|
||||
{
|
||||
public:
|
||||
{{#gmockApis}}
|
||||
using Base = I{{classname}};
|
||||
{{/gmockApis}}
|
||||
|
||||
explicit {{classname}}( std::shared_ptr<const ApiClient> apiClient );
|
||||
|
||||
{{#gmockApis}}
|
||||
~{{classname}}() override;
|
||||
{{/gmockApis}}
|
||||
{{^gmockApis}}
|
||||
virtual ~{{classname}}();
|
||||
{{/gmockApis}}
|
||||
|
||||
{{#operation}}
|
||||
/// <summary>
|
||||
/// {{summary}}
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// {{notes}}
|
||||
/// </remarks>
|
||||
{{#allParams}}
|
||||
/// <param name="{{paramName}}">{{#lambda.multiline_comment_4}}{{description}}{{/lambda.multiline_comment_4}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
|
||||
{{/allParams}}
|
||||
/// <param name="customHeaders">Additional HTTP headers to send with the request (optional)</param>
|
||||
pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{operationId}}(
|
||||
{{#allParams}}
|
||||
{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}},{{/allParams}}
|
||||
const std::map<utility::string_t, utility::string_t>& customHeaders = {} // <-- добавлено
|
||||
) const{{#gmockApis}} override{{/gmockApis}};
|
||||
{{/operation}}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const ApiClient> m_ApiClient;
|
||||
};
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{apiHeaderGuardPrefix}}_{{classname}}_H_ */
|
||||
|
||||
{{/operations}}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
{{>licenseInfo}}
|
||||
{{#operations}}/*
|
||||
* {{classname}}.h
|
||||
*
|
||||
* {{description}}
|
||||
*/
|
||||
|
||||
#ifndef {{apiHeaderGuardPrefix}}_{{classname}}_H_
|
||||
#define {{apiHeaderGuardPrefix}}_{{classname}}_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include "{{packageName}}/ApiClient.h"
|
||||
{{^hasModelImport}}#include "{{packageName}}/ModelBase.h"{{/hasModelImport}}
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
{{#gmockApis}}
|
||||
class {{declspec}} I{{classname}}
|
||||
{
|
||||
public:
|
||||
I{{classname}}() = default;
|
||||
virtual ~I{{classname}}() = default;
|
||||
|
||||
{{#operation}}
|
||||
virtual pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{operationId}}(
|
||||
{{#allParams}}
|
||||
{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{^-last}},{{/-last}}
|
||||
{{/allParams}}
|
||||
) const = 0;
|
||||
{{/operation}}
|
||||
};{{/gmockApis}}
|
||||
|
||||
class {{declspec}} {{classname}} {{#gmockApis}} : public I{{classname}} {{/gmockApis}}
|
||||
{
|
||||
public:
|
||||
{{#gmockApis}}
|
||||
using Base = I{{classname}};
|
||||
{{/gmockApis}}
|
||||
|
||||
explicit {{classname}}( std::shared_ptr<const ApiClient> apiClient );
|
||||
|
||||
{{#gmockApis}}
|
||||
~{{classname}}() override;
|
||||
{{/gmockApis}}
|
||||
{{^gmockApis}}
|
||||
virtual ~{{classname}}();
|
||||
{{/gmockApis}}
|
||||
|
||||
{{#operation}}
|
||||
/// <summary>
|
||||
/// {{summary}}
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// {{notes}}
|
||||
/// </remarks>
|
||||
{{#allParams}}
|
||||
/// <param name="{{paramName}}">{{#lambda.multiline_comment_4}}{{description}}{{/lambda.multiline_comment_4}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
|
||||
{{/allParams}}
|
||||
pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{operationId}}(
|
||||
{{#allParams}}
|
||||
{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{^-last}},{{/-last}}
|
||||
{{/allParams}}
|
||||
) const{{#gmockApis}} override{{/gmockApis}};
|
||||
{{/operation}}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const ApiClient> m_ApiClient;
|
||||
};
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{apiHeaderGuardPrefix}}_{{classname}}_H_ */
|
||||
|
||||
{{/operations}}
|
||||
375
api/_build/my-cpp-templates/cpp-restsdk/api-source.mustache
Normal file
375
api/_build/my-cpp-templates/cpp-restsdk/api-source.mustache
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
{{>licenseInfo}}
|
||||
{{#operations}}
|
||||
|
||||
#include "{{packageName}}/api/{{classname}}.h"
|
||||
#include "{{packageName}}/IHttpBody.h"
|
||||
#include "{{packageName}}/JsonBody.h"
|
||||
#include "{{packageName}}/MultipartFormData.h"
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
{{classname}}::{{classname}}( std::shared_ptr<const ApiClient> apiClient )
|
||||
: m_ApiClient(apiClient)
|
||||
{
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}()
|
||||
{
|
||||
}
|
||||
|
||||
{{#operation}}
|
||||
pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{classname}}::{{operationId}}({{#allParams}}{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}, {{/allParams}}const std::map<utility::string_t, utility::string_t>& customHeaders) const // <-- изменено: все параметры с запятой, + customHeaders
|
||||
{
|
||||
{{#allParams}}{{#required}}{{^isPrimitiveType}}{{^isContainer}}
|
||||
// verify the required parameter '{{paramName}}' is set
|
||||
if ({{paramName}} == nullptr)
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"));
|
||||
}
|
||||
{{/isContainer}}{{/isPrimitiveType}}{{/required}}{{/allParams}}
|
||||
|
||||
std::shared_ptr<const ApiConfiguration> localVarApiConfiguration( m_ApiClient->getConfiguration() );
|
||||
utility::string_t localVarPath = utility::conversions::to_string_t("{{{path}}}");
|
||||
{{#pathParams}}
|
||||
boost::replace_all(localVarPath, utility::conversions::to_string_t("{") + utility::conversions::to_string_t("{{baseName}}") + utility::conversions::to_string_t("}"), web::uri::encode_uri(ApiClient::parameterToString({{{paramName}}})));
|
||||
{{/pathParams}}
|
||||
|
||||
std::map<utility::string_t, utility::string_t> localVarQueryParams;
|
||||
std::map<utility::string_t, utility::string_t> localVarHeaderParams( localVarApiConfiguration->getDefaultHeaders() ); // <-- уже содержит defaultHeaders
|
||||
std::map<utility::string_t, utility::string_t> localVarFormParams;
|
||||
std::map<utility::string_t, std::shared_ptr<HttpContent>> localVarFileParams;
|
||||
|
||||
std::unordered_set<utility::string_t> localVarResponseHttpContentTypes;
|
||||
{{#produces}}
|
||||
localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("{{{mediaType}}}") );
|
||||
{{/produces}}
|
||||
|
||||
utility::string_t localVarResponseHttpContentType;
|
||||
|
||||
// use JSON if possible
|
||||
if ( localVarResponseHttpContentTypes.size() == 0 )
|
||||
{
|
||||
{{#vendorExtensions.x-codegen-response.isString}}
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
{{^vendorExtensions.x-codegen-response.isString}}
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
}
|
||||
// JSON
|
||||
else if ( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
}
|
||||
// multipart formdata
|
||||
else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("multipart/form-data");
|
||||
}
|
||||
{{#vendorExtensions.x-codegen-response.isString}}
|
||||
// plain text
|
||||
else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("text/plain")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
{{#vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
else
|
||||
{
|
||||
//It's going to be binary, so just use the first one.
|
||||
localVarResponseHttpContentType = *localVarResponseHttpContentTypes.begin();
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
{{^vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
else
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("{{classname}}->{{operationId}} does not produce any supported media type"));
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
|
||||
localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType;
|
||||
|
||||
std::unordered_set<utility::string_t> localVarConsumeHttpContentTypes;
|
||||
{{#consumes}}
|
||||
localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("{{{mediaType}}}") );
|
||||
{{/consumes}}
|
||||
|
||||
{{#allParams}}
|
||||
{{^isBodyParam}}
|
||||
{{^isPathParam}}
|
||||
{{#required}}
|
||||
{{^isPrimitiveType}}
|
||||
{{^isContainer}}
|
||||
if ({{paramName}} != nullptr)
|
||||
{{/isContainer}}
|
||||
{{/isPrimitiveType}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{^isPrimitiveType}}
|
||||
{{^isContainer}}
|
||||
if ({{paramName}} && *{{paramName}} != nullptr)
|
||||
{{/isContainer}}
|
||||
{{/isPrimitiveType}}
|
||||
{{#isPrimitiveType}}
|
||||
{{#isFile}}
|
||||
if ({{paramName}} && *{{paramName}} != nullptr)
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
if ({{paramName}})
|
||||
{{/isFile}}
|
||||
{{/isPrimitiveType}}
|
||||
{{#isContainer}}
|
||||
if ({{paramName}})
|
||||
{{/isContainer}}
|
||||
{{/required}}
|
||||
{
|
||||
{{#isQueryParam}}
|
||||
localVarQueryParams[utility::conversions::to_string_t("{{baseName}}")] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isQueryParam}}
|
||||
{{#isHeaderParam}}
|
||||
localVarHeaderParams[utility::conversions::to_string_t("{{baseName}}")] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isHeaderParam}}
|
||||
{{#isFormParam}}
|
||||
{{#isFile}}
|
||||
localVarFileParams[ utility::conversions::to_string_t("{{baseName}}") ] = {{^required}}*{{/required}}{{paramName}};
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
localVarFormParams[ utility::conversions::to_string_t("{{baseName}}") ] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isFile}}
|
||||
{{/isFormParam}}
|
||||
}
|
||||
{{/isPathParam}}
|
||||
{{/isBodyParam}}
|
||||
{{/allParams}}
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
// Apply customHeaders AFTER all other headers (so they can override)
|
||||
for (const auto& header : customHeaders) {
|
||||
localVarHeaderParams[header.first] = header.second;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
std::shared_ptr<IHttpBody> localVarHttpBody;
|
||||
utility::string_t localVarRequestHttpContentType;
|
||||
|
||||
// use JSON if possible
|
||||
if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() )
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
{{#bodyParam}}
|
||||
web::json::value localVarJson;
|
||||
|
||||
{{#isPrimitiveType}}
|
||||
localVarJson = ModelBase::toJson({{paramName}}{{^required}}.get(){{/required}});
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
{{#isArray}}
|
||||
{
|
||||
std::vector<web::json::value> localVarJsonArray;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
{{#items.isPrimitiveType}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isPrimitiveType}}{{^items.isPrimitiveType}}{{#items.isString}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isString}}{{^items.isString}}{{#items.isDateTime}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isDateTime}}{{^items.isDateTime}}localVarJsonArray.push_back( localVarItem.get() ? localVarItem->toJson() : web::json::value::null() );
|
||||
{{/items.isDateTime}}{{/items.isString}}{{/items.isPrimitiveType}}
|
||||
}
|
||||
localVarJson = web::json::value::array(localVarJsonArray);
|
||||
}
|
||||
{{/isArray}}
|
||||
{{^isArray}}{{#required}}localVarJson = ModelBase::toJson({{paramName}});
|
||||
{{/required}}{{^required}}if ({{paramName}})
|
||||
localVarJson = ModelBase::toJson(*{{paramName}});{{/required}}
|
||||
{{/isArray}}
|
||||
{{/isPrimitiveType}}
|
||||
|
||||
localVarHttpBody = std::shared_ptr<IHttpBody>( new JsonBody( localVarJson ) );
|
||||
{{/bodyParam}}
|
||||
}
|
||||
// multipart formdata
|
||||
else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() )
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data");
|
||||
{{#bodyParam}}
|
||||
std::shared_ptr<MultipartFormData> localVarMultipart(new MultipartFormData);
|
||||
{{#isPrimitiveType}}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), {{paramName}}{{^required}}.get(){{/required}}));
|
||||
{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isArray}}
|
||||
{
|
||||
std::vector<web::json::value> localVarJsonArray;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), localVarJsonArray, utility::conversions::to_string_t("application/json")));
|
||||
}{{/isArray}}{{#isMap}}
|
||||
{
|
||||
std::map<utility::string_t, web::json::value> localVarJsonMap;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
web::json::value jval;
|
||||
localVarJsonMap.insert( std::pair<utility::string_t, web::json::value>(localVarItem.first, ModelBase::toJson(localVarItem.second) ));
|
||||
}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), localVarJsonMap, utility::conversions::to_string_t("application/json")));
|
||||
}{{/isMap}}
|
||||
{{^isArray}}{{^isMap}}{{#isString}}localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), {{paramName}}));
|
||||
{{/isString}}{{^isString}}if({{^required}}{{paramName}} && (*{{paramName}}){{/required}}{{#required}}{{paramName}}{{/required}}.get())
|
||||
{
|
||||
{{^required}}(*{{/required}}{{paramName}}{{^required}}){{/required}}->toMultipart(localVarMultipart, utility::conversions::to_string_t("{{paramName}}"));
|
||||
}
|
||||
{{/isString}}
|
||||
{{/isMap}}{{/isArray}}{{/isPrimitiveType}}
|
||||
|
||||
localVarHttpBody = localVarMultipart;
|
||||
localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary();
|
||||
{{/bodyParam}}
|
||||
}
|
||||
else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end())
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("application/x-www-form-urlencoded");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ApiException(415, utility::conversions::to_string_t("{{classname}}->{{operationId}} does not consume any supported media type"));
|
||||
}
|
||||
|
||||
{{#authMethods}}
|
||||
// authentication ({{name}}) required
|
||||
{{#isApiKey}}
|
||||
{{#isKeyInHeader}}
|
||||
{
|
||||
utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("{{keyParamName}}"));
|
||||
if ( localVarApiKey.size() > 0 )
|
||||
{
|
||||
localVarHeaderParams[utility::conversions::to_string_t("{{keyParamName}}")] = localVarApiKey;
|
||||
}
|
||||
}
|
||||
{{/isKeyInHeader}}
|
||||
{{#isKeyInQuery}}
|
||||
{
|
||||
utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("{{keyParamName}}"));
|
||||
if ( localVarApiKey.size() > 0 )
|
||||
{
|
||||
localVarQueryParams[utility::conversions::to_string_t("{{keyParamName}}")] = localVarApiKey;
|
||||
}
|
||||
}
|
||||
{{/isKeyInQuery}}
|
||||
{{/isApiKey}}
|
||||
{{#isBasicBasic}}
|
||||
// Basic authentication is added automatically as part of the http_client_config
|
||||
{{/isBasicBasic}}
|
||||
{{#isOAuth}}
|
||||
// oauth2 authentication is added automatically as part of the http_client_config
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
|
||||
return m_ApiClient->callApi(localVarPath, utility::conversions::to_string_t("{{httpMethod}}"), localVarQueryParams, localVarHttpBody, localVarHeaderParams, localVarFormParams, localVarFileParams, localVarRequestHttpContentType)
|
||||
.then([=, this](web::http::http_response localVarResponse)
|
||||
{
|
||||
if (m_ApiClient->getResponseHandler())
|
||||
{
|
||||
m_ApiClient->getResponseHandler()(localVarResponse.status_code(), localVarResponse.headers());
|
||||
}
|
||||
|
||||
// 1xx - informational : OK
|
||||
// 2xx - successful : OK
|
||||
// 3xx - redirection : OK
|
||||
// 4xx - client error : not OK
|
||||
// 5xx - client error : not OK
|
||||
if (localVarResponse.status_code() >= 400)
|
||||
{
|
||||
throw ApiException(localVarResponse.status_code()
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: ") + localVarResponse.reason_phrase()
|
||||
, std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
|
||||
}
|
||||
|
||||
// check response content type
|
||||
if(localVarResponse.headers().has(utility::conversions::to_string_t("Content-Type")))
|
||||
{
|
||||
utility::string_t localVarContentType = localVarResponse.headers()[utility::conversions::to_string_t("Content-Type")];
|
||||
if( localVarContentType.find(localVarResponseHttpContentType) == std::string::npos )
|
||||
{
|
||||
throw ApiException(500
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: unexpected response type: ") + localVarContentType
|
||||
, std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
|
||||
}
|
||||
}
|
||||
|
||||
{{#vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
return localVarResponse.extract_vector();
|
||||
})
|
||||
.then([=, this](std::vector<unsigned char> localVarResponse)
|
||||
{
|
||||
{{{returnType}}} localVarResult = std::make_shared<HttpContent>();
|
||||
std::shared_ptr<std::stringstream> stream = std::make_shared<std::stringstream>(std::string(localVarResponse.begin(), localVarResponse.end()));
|
||||
localVarResult->setData(stream);
|
||||
return localVarResult;
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
{{^vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
return localVarResponse.extract_string();
|
||||
})
|
||||
.then([=, this](utility::string_t localVarResponse)
|
||||
{
|
||||
{{^returnType}}
|
||||
return void();
|
||||
{{/returnType}}
|
||||
{{#returnType}}
|
||||
{{#returnContainer}}
|
||||
{{{returnType}}} localVarResult;
|
||||
{{/returnContainer}}
|
||||
{{^returnContainer}}
|
||||
{{{returnType}}} localVarResult({{{defaultResponse}}});
|
||||
{{/returnContainer}}
|
||||
|
||||
if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json"))
|
||||
{
|
||||
web::json::value localVarJson = web::json::value::parse(localVarResponse);
|
||||
{{#isArray}}
|
||||
for( auto& localVarItem : localVarJson.as_array() )
|
||||
{
|
||||
{{{vendorExtensions.x-codegen-response.items.datatype}}} localVarItemObj;
|
||||
ModelBase::fromJson(localVarItem, localVarItemObj);
|
||||
localVarResult.push_back(localVarItemObj);
|
||||
}{{/isArray}}{{#isMap}}
|
||||
for( auto& localVarItem : localVarJson.as_object() )
|
||||
{
|
||||
{{{vendorExtensions.x-codegen-response.items.datatype}}} localVarItemObj;
|
||||
ModelBase::fromJson(localVarItem.second, localVarItemObj);
|
||||
localVarResult[localVarItem.first] = localVarItemObj;
|
||||
}{{/isMap}}{{^isArray}}{{^isMap}}
|
||||
ModelBase::fromJson(localVarJson, localVarResult);{{/isMap}}{{/isArray}}
|
||||
}{{#vendorExtensions.x-codegen-response.isString}}
|
||||
else if(localVarResponseHttpContentType == utility::conversions::to_string_t("text/plain"))
|
||||
{
|
||||
localVarResult = localVarResponse;
|
||||
}{{/vendorExtensions.x-codegen-response.isString}}
|
||||
// else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data"))
|
||||
// {
|
||||
// TODO multipart response parsing
|
||||
// }
|
||||
else
|
||||
{
|
||||
throw ApiException(500
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: unsupported response type"));
|
||||
}
|
||||
|
||||
return localVarResult;
|
||||
{{/returnType}}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
});
|
||||
}
|
||||
{{/operation}}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
{{/operations}}
|
||||
368
api/_build/my-cpp-templates/cpp-restsdk/api-source.mustache_old
Normal file
368
api/_build/my-cpp-templates/cpp-restsdk/api-source.mustache_old
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
{{>licenseInfo}}
|
||||
{{#operations}}
|
||||
|
||||
#include "{{packageName}}/api/{{classname}}.h"
|
||||
#include "{{packageName}}/IHttpBody.h"
|
||||
#include "{{packageName}}/JsonBody.h"
|
||||
#include "{{packageName}}/MultipartFormData.h"
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
{{classname}}::{{classname}}( std::shared_ptr<const ApiClient> apiClient )
|
||||
: m_ApiClient(apiClient)
|
||||
{
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}()
|
||||
{
|
||||
}
|
||||
|
||||
{{#operation}}
|
||||
pplx::task<{{{returnType}}}{{^returnType}}void{{/returnType}}> {{classname}}::{{operationId}}({{#allParams}}{{^required}}boost::optional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) const
|
||||
{
|
||||
{{#allParams}}{{#required}}{{^isPrimitiveType}}{{^isContainer}}
|
||||
// verify the required parameter '{{paramName}}' is set
|
||||
if ({{paramName}} == nullptr)
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"));
|
||||
}
|
||||
{{/isContainer}}{{/isPrimitiveType}}{{/required}}{{/allParams}}
|
||||
|
||||
std::shared_ptr<const ApiConfiguration> localVarApiConfiguration( m_ApiClient->getConfiguration() );
|
||||
utility::string_t localVarPath = utility::conversions::to_string_t("{{{path}}}");
|
||||
{{#pathParams}}
|
||||
boost::replace_all(localVarPath, utility::conversions::to_string_t("{") + utility::conversions::to_string_t("{{baseName}}") + utility::conversions::to_string_t("}"), web::uri::encode_uri(ApiClient::parameterToString({{{paramName}}})));
|
||||
{{/pathParams}}
|
||||
|
||||
std::map<utility::string_t, utility::string_t> localVarQueryParams;
|
||||
std::map<utility::string_t, utility::string_t> localVarHeaderParams( localVarApiConfiguration->getDefaultHeaders() );
|
||||
std::map<utility::string_t, utility::string_t> localVarFormParams;
|
||||
std::map<utility::string_t, std::shared_ptr<HttpContent>> localVarFileParams;
|
||||
|
||||
std::unordered_set<utility::string_t> localVarResponseHttpContentTypes;
|
||||
{{#produces}}
|
||||
localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("{{{mediaType}}}") );
|
||||
{{/produces}}
|
||||
|
||||
utility::string_t localVarResponseHttpContentType;
|
||||
|
||||
// use JSON if possible
|
||||
if ( localVarResponseHttpContentTypes.size() == 0 )
|
||||
{
|
||||
{{#vendorExtensions.x-codegen-response.isString}}
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
{{^vendorExtensions.x-codegen-response.isString}}
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
}
|
||||
// JSON
|
||||
else if ( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
}
|
||||
// multipart formdata
|
||||
else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("multipart/form-data");
|
||||
}
|
||||
{{#vendorExtensions.x-codegen-response.isString}}
|
||||
// plain text
|
||||
else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("text/plain")) != localVarResponseHttpContentTypes.end() )
|
||||
{
|
||||
localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response.isString}}
|
||||
{{#vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
else
|
||||
{
|
||||
//It's going to be binary, so just use the first one.
|
||||
localVarResponseHttpContentType = *localVarResponseHttpContentTypes.begin();
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
{{^vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
else
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("{{classname}}->{{operationId}} does not produce any supported media type"));
|
||||
}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
|
||||
localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType;
|
||||
|
||||
std::unordered_set<utility::string_t> localVarConsumeHttpContentTypes;
|
||||
{{#consumes}}
|
||||
localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("{{{mediaType}}}") );
|
||||
{{/consumes}}
|
||||
|
||||
{{#allParams}}
|
||||
{{^isBodyParam}}
|
||||
{{^isPathParam}}
|
||||
{{#required}}
|
||||
{{^isPrimitiveType}}
|
||||
{{^isContainer}}
|
||||
if ({{paramName}} != nullptr)
|
||||
{{/isContainer}}
|
||||
{{/isPrimitiveType}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{^isPrimitiveType}}
|
||||
{{^isContainer}}
|
||||
if ({{paramName}} && *{{paramName}} != nullptr)
|
||||
{{/isContainer}}
|
||||
{{/isPrimitiveType}}
|
||||
{{#isPrimitiveType}}
|
||||
{{#isFile}}
|
||||
if ({{paramName}} && *{{paramName}} != nullptr)
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
if ({{paramName}})
|
||||
{{/isFile}}
|
||||
{{/isPrimitiveType}}
|
||||
{{#isContainer}}
|
||||
if ({{paramName}})
|
||||
{{/isContainer}}
|
||||
{{/required}}
|
||||
{
|
||||
{{#isQueryParam}}
|
||||
localVarQueryParams[utility::conversions::to_string_t("{{baseName}}")] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isQueryParam}}
|
||||
{{#isHeaderParam}}
|
||||
localVarHeaderParams[utility::conversions::to_string_t("{{baseName}}")] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isHeaderParam}}
|
||||
{{#isFormParam}}
|
||||
{{#isFile}}
|
||||
localVarFileParams[ utility::conversions::to_string_t("{{baseName}}") ] = {{^required}}*{{/required}}{{paramName}};
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
localVarFormParams[ utility::conversions::to_string_t("{{baseName}}") ] = ApiClient::parameterToString({{^required}}*{{/required}}{{paramName}});
|
||||
{{/isFile}}
|
||||
{{/isFormParam}}
|
||||
}
|
||||
{{/isPathParam}}
|
||||
{{/isBodyParam}}
|
||||
{{/allParams}}
|
||||
|
||||
std::shared_ptr<IHttpBody> localVarHttpBody;
|
||||
utility::string_t localVarRequestHttpContentType;
|
||||
|
||||
// use JSON if possible
|
||||
if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() )
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("application/json");
|
||||
{{#bodyParam}}
|
||||
web::json::value localVarJson;
|
||||
|
||||
{{#isPrimitiveType}}
|
||||
localVarJson = ModelBase::toJson({{paramName}}{{^required}}.get(){{/required}});
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
{{#isArray}}
|
||||
{
|
||||
std::vector<web::json::value> localVarJsonArray;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
{{#items.isPrimitiveType}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isPrimitiveType}}{{^items.isPrimitiveType}}{{#items.isString}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isString}}{{^items.isString}}{{#items.isDateTime}}localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
{{/items.isDateTime}}{{^items.isDateTime}}localVarJsonArray.push_back( localVarItem.get() ? localVarItem->toJson() : web::json::value::null() );
|
||||
{{/items.isDateTime}}{{/items.isString}}{{/items.isPrimitiveType}}
|
||||
}
|
||||
localVarJson = web::json::value::array(localVarJsonArray);
|
||||
}
|
||||
{{/isArray}}
|
||||
{{^isArray}}{{#required}}localVarJson = ModelBase::toJson({{paramName}});
|
||||
{{/required}}{{^required}}if ({{paramName}})
|
||||
localVarJson = ModelBase::toJson(*{{paramName}});{{/required}}
|
||||
{{/isArray}}
|
||||
{{/isPrimitiveType}}
|
||||
|
||||
localVarHttpBody = std::shared_ptr<IHttpBody>( new JsonBody( localVarJson ) );
|
||||
{{/bodyParam}}
|
||||
}
|
||||
// multipart formdata
|
||||
else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() )
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data");
|
||||
{{#bodyParam}}
|
||||
std::shared_ptr<MultipartFormData> localVarMultipart(new MultipartFormData);
|
||||
{{#isPrimitiveType}}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), {{paramName}}{{^required}}.get(){{/required}}));
|
||||
{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isArray}}
|
||||
{
|
||||
std::vector<web::json::value> localVarJsonArray;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
localVarJsonArray.push_back(ModelBase::toJson(localVarItem));
|
||||
}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), localVarJsonArray, utility::conversions::to_string_t("application/json")));
|
||||
}{{/isArray}}{{#isMap}}
|
||||
{
|
||||
std::map<utility::string_t, web::json::value> localVarJsonMap;
|
||||
for( auto& localVarItem : {{paramName}}{{^required}}.get(){{/required}} )
|
||||
{
|
||||
web::json::value jval;
|
||||
localVarJsonMap.insert( std::pair<utility::string_t, web::json::value>(localVarItem.first, ModelBase::toJson(localVarItem.second) ));
|
||||
}
|
||||
localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), localVarJsonMap, utility::conversions::to_string_t("application/json")));
|
||||
}{{/isMap}}
|
||||
{{^isArray}}{{^isMap}}{{#isString}}localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("{{paramName}}"), {{paramName}}));
|
||||
{{/isString}}{{^isString}}if({{^required}}{{paramName}} && (*{{paramName}}){{/required}}{{#required}}{{paramName}}{{/required}}.get())
|
||||
{
|
||||
{{^required}}(*{{/required}}{{paramName}}{{^required}}){{/required}}->toMultipart(localVarMultipart, utility::conversions::to_string_t("{{paramName}}"));
|
||||
}
|
||||
{{/isString}}
|
||||
{{/isMap}}{{/isArray}}{{/isPrimitiveType}}
|
||||
|
||||
localVarHttpBody = localVarMultipart;
|
||||
localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary();
|
||||
{{/bodyParam}}
|
||||
}
|
||||
else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end())
|
||||
{
|
||||
localVarRequestHttpContentType = utility::conversions::to_string_t("application/x-www-form-urlencoded");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ApiException(415, utility::conversions::to_string_t("{{classname}}->{{operationId}} does not consume any supported media type"));
|
||||
}
|
||||
|
||||
{{#authMethods}}
|
||||
// authentication ({{name}}) required
|
||||
{{#isApiKey}}
|
||||
{{#isKeyInHeader}}
|
||||
{
|
||||
utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("{{keyParamName}}"));
|
||||
if ( localVarApiKey.size() > 0 )
|
||||
{
|
||||
localVarHeaderParams[utility::conversions::to_string_t("{{keyParamName}}")] = localVarApiKey;
|
||||
}
|
||||
}
|
||||
{{/isKeyInHeader}}
|
||||
{{#isKeyInQuery}}
|
||||
{
|
||||
utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("{{keyParamName}}"));
|
||||
if ( localVarApiKey.size() > 0 )
|
||||
{
|
||||
localVarQueryParams[utility::conversions::to_string_t("{{keyParamName}}")] = localVarApiKey;
|
||||
}
|
||||
}
|
||||
{{/isKeyInQuery}}
|
||||
{{/isApiKey}}
|
||||
{{#isBasicBasic}}
|
||||
// Basic authentication is added automatically as part of the http_client_config
|
||||
{{/isBasicBasic}}
|
||||
{{#isOAuth}}
|
||||
// oauth2 authentication is added automatically as part of the http_client_config
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
|
||||
return m_ApiClient->callApi(localVarPath, utility::conversions::to_string_t("{{httpMethod}}"), localVarQueryParams, localVarHttpBody, localVarHeaderParams, localVarFormParams, localVarFileParams, localVarRequestHttpContentType)
|
||||
.then([=, this](web::http::http_response localVarResponse)
|
||||
{
|
||||
if (m_ApiClient->getResponseHandler())
|
||||
{
|
||||
m_ApiClient->getResponseHandler()(localVarResponse.status_code(), localVarResponse.headers());
|
||||
}
|
||||
|
||||
// 1xx - informational : OK
|
||||
// 2xx - successful : OK
|
||||
// 3xx - redirection : OK
|
||||
// 4xx - client error : not OK
|
||||
// 5xx - client error : not OK
|
||||
if (localVarResponse.status_code() >= 400)
|
||||
{
|
||||
throw ApiException(localVarResponse.status_code()
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: ") + localVarResponse.reason_phrase()
|
||||
, std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
|
||||
}
|
||||
|
||||
// check response content type
|
||||
if(localVarResponse.headers().has(utility::conversions::to_string_t("Content-Type")))
|
||||
{
|
||||
utility::string_t localVarContentType = localVarResponse.headers()[utility::conversions::to_string_t("Content-Type")];
|
||||
if( localVarContentType.find(localVarResponseHttpContentType) == std::string::npos )
|
||||
{
|
||||
throw ApiException(500
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: unexpected response type: ") + localVarContentType
|
||||
, std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
|
||||
}
|
||||
}
|
||||
|
||||
{{#vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
return localVarResponse.extract_vector();
|
||||
})
|
||||
.then([=, this](std::vector<unsigned char> localVarResponse)
|
||||
{
|
||||
{{{returnType}}} localVarResult = std::make_shared<HttpContent>();
|
||||
std::shared_ptr<std::stringstream> stream = std::make_shared<std::stringstream>(std::string(localVarResponse.begin(), localVarResponse.end()));
|
||||
localVarResult->setData(stream);
|
||||
return localVarResult;
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
{{^vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
return localVarResponse.extract_string();
|
||||
})
|
||||
.then([=, this](utility::string_t localVarResponse)
|
||||
{
|
||||
{{^returnType}}
|
||||
return void();
|
||||
{{/returnType}}
|
||||
{{#returnType}}
|
||||
{{#returnContainer}}
|
||||
{{{returnType}}} localVarResult;
|
||||
{{/returnContainer}}
|
||||
{{^returnContainer}}
|
||||
{{{returnType}}} localVarResult({{{defaultResponse}}});
|
||||
{{/returnContainer}}
|
||||
|
||||
if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json"))
|
||||
{
|
||||
web::json::value localVarJson = web::json::value::parse(localVarResponse);
|
||||
{{#isArray}}
|
||||
for( auto& localVarItem : localVarJson.as_array() )
|
||||
{
|
||||
{{{vendorExtensions.x-codegen-response.items.datatype}}} localVarItemObj;
|
||||
ModelBase::fromJson(localVarItem, localVarItemObj);
|
||||
localVarResult.push_back(localVarItemObj);
|
||||
}{{/isArray}}{{#isMap}}
|
||||
for( auto& localVarItem : localVarJson.as_object() )
|
||||
{
|
||||
{{{vendorExtensions.x-codegen-response.items.datatype}}} localVarItemObj;
|
||||
ModelBase::fromJson(localVarItem.second, localVarItemObj);
|
||||
localVarResult[localVarItem.first] = localVarItemObj;
|
||||
}{{/isMap}}{{^isArray}}{{^isMap}}
|
||||
ModelBase::fromJson(localVarJson, localVarResult);{{/isMap}}{{/isArray}}
|
||||
}{{#vendorExtensions.x-codegen-response.isString}}
|
||||
else if(localVarResponseHttpContentType == utility::conversions::to_string_t("text/plain"))
|
||||
{
|
||||
localVarResult = localVarResponse;
|
||||
}{{/vendorExtensions.x-codegen-response.isString}}
|
||||
// else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data"))
|
||||
// {
|
||||
// TODO multipart response parsing
|
||||
// }
|
||||
else
|
||||
{
|
||||
throw ApiException(500
|
||||
, utility::conversions::to_string_t("error calling {{operationId}}: unsupported response type"));
|
||||
}
|
||||
|
||||
return localVarResult;
|
||||
{{/returnType}}
|
||||
{{/vendorExtensions.x-codegen-response-ishttpcontent}}
|
||||
});
|
||||
}
|
||||
{{/operation}}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
{{/operations}}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* ApiClient.h
|
||||
*
|
||||
* This is an API client responsible for stating the HTTP calls
|
||||
*/
|
||||
|
||||
#ifndef {{apiHeaderGuardPrefix}}_ApiClient_H_
|
||||
#define {{apiHeaderGuardPrefix}}_ApiClient_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/ApiConfiguration.h"
|
||||
#include "{{packageName}}/ApiException.h"
|
||||
#include "{{packageName}}/IHttpBody.h"
|
||||
#include "{{packageName}}/HttpContent.h"
|
||||
{{^hasModelImport}}
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
{{/hasModelImport}}
|
||||
#if defined (_WIN32) || defined (_WIN64)
|
||||
#undef U
|
||||
#endif
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/http_client.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
class {{declspec}} ApiClient
|
||||
{
|
||||
public:
|
||||
ApiClient( std::shared_ptr<const ApiConfiguration> configuration = nullptr );
|
||||
virtual ~ApiClient();
|
||||
|
||||
typedef std::function<void(web::http::status_code, const web::http::http_headers&)> ResponseHandlerType;
|
||||
|
||||
const ResponseHandlerType& getResponseHandler() const;
|
||||
void setResponseHandler(const ResponseHandlerType& responseHandler);
|
||||
|
||||
std::shared_ptr<const ApiConfiguration> getConfiguration() const;
|
||||
void setConfiguration(std::shared_ptr<const ApiConfiguration> configuration);
|
||||
|
||||
static utility::string_t parameterToString(utility::string_t value);
|
||||
static utility::string_t parameterToString(int32_t value);
|
||||
static utility::string_t parameterToString(int64_t value);
|
||||
static utility::string_t parameterToString(float value);
|
||||
static utility::string_t parameterToString(double value);
|
||||
static utility::string_t parameterToString(const utility::datetime &value);
|
||||
static utility::string_t parameterToString(bool value);
|
||||
{{^hasModelImport}}
|
||||
static utility::string_t parameterToString(const ModelBase& value);
|
||||
{{/hasModelImport}}
|
||||
template<class T>
|
||||
static utility::string_t parameterToString(const std::vector<T>& value);
|
||||
template<class T>
|
||||
static utility::string_t parameterToString(const std::shared_ptr<T>& value);
|
||||
|
||||
pplx::task<web::http::http_response> callApi(
|
||||
const utility::string_t& path,
|
||||
const utility::string_t& method,
|
||||
const std::map<utility::string_t, utility::string_t>& queryParams,
|
||||
const std::shared_ptr<IHttpBody> postBody,
|
||||
const std::map<utility::string_t, utility::string_t>& headerParams,
|
||||
const std::map<utility::string_t, utility::string_t>& formParams,
|
||||
const std::map<utility::string_t, std::shared_ptr<HttpContent>>& fileParams,
|
||||
const utility::string_t& contentType
|
||||
) const;
|
||||
|
||||
protected:
|
||||
|
||||
ResponseHandlerType m_ResponseHandler;
|
||||
std::shared_ptr<const ApiConfiguration> m_Configuration;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
utility::string_t ApiClient::parameterToString(const std::vector<T>& value)
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
|
||||
for( size_t i = 0; i < value.size(); i++)
|
||||
{
|
||||
if( i > 0) ss << utility::conversions::to_string_t(", ");
|
||||
ss << ApiClient::parameterToString(value[i]);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
utility::string_t ApiClient::parameterToString(const std::shared_ptr<T>& value)
|
||||
{
|
||||
return parameterToString(*value.get());
|
||||
}
|
||||
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{apiHeaderGuardPrefix}}_ApiClient_H_ */
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/ApiClient.h"
|
||||
#include "{{packageName}}/MultipartFormData.h"
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
#include <iomanip>
|
||||
|
||||
template <typename T>
|
||||
utility::string_t toString(const T value)
|
||||
{
|
||||
utility::ostringstream_t out;
|
||||
out << std::setprecision(std::numeric_limits<T>::digits10) << std::fixed << value;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
using namespace {{modelNamespace}};
|
||||
|
||||
ApiClient::ApiClient(std::shared_ptr<const ApiConfiguration> configuration )
|
||||
: m_Configuration(configuration)
|
||||
{
|
||||
}
|
||||
ApiClient::~ApiClient()
|
||||
{
|
||||
}
|
||||
|
||||
const ApiClient::ResponseHandlerType& ApiClient::getResponseHandler() const {
|
||||
return m_ResponseHandler;
|
||||
}
|
||||
|
||||
void ApiClient::setResponseHandler(const ResponseHandlerType& responseHandler) {
|
||||
m_ResponseHandler = responseHandler;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ApiConfiguration> ApiClient::getConfiguration() const
|
||||
{
|
||||
return m_Configuration;
|
||||
}
|
||||
void ApiClient::setConfiguration(std::shared_ptr<const ApiConfiguration> configuration)
|
||||
{
|
||||
m_Configuration = configuration;
|
||||
}
|
||||
|
||||
|
||||
utility::string_t ApiClient::parameterToString(utility::string_t value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
utility::string_t ApiClient::parameterToString(int64_t value)
|
||||
{
|
||||
std::stringstream valueAsStringStream;
|
||||
valueAsStringStream << value;
|
||||
return utility::conversions::to_string_t(valueAsStringStream.str());
|
||||
}
|
||||
utility::string_t ApiClient::parameterToString(int32_t value)
|
||||
{
|
||||
std::stringstream valueAsStringStream;
|
||||
valueAsStringStream << value;
|
||||
return utility::conversions::to_string_t(valueAsStringStream.str());
|
||||
}
|
||||
|
||||
utility::string_t ApiClient::parameterToString(float value)
|
||||
{
|
||||
return utility::conversions::to_string_t(toString(value));
|
||||
}
|
||||
|
||||
utility::string_t ApiClient::parameterToString(double value)
|
||||
{
|
||||
return utility::conversions::to_string_t(toString(value));
|
||||
}
|
||||
|
||||
utility::string_t ApiClient::parameterToString(const utility::datetime &value)
|
||||
{
|
||||
return utility::conversions::to_string_t(value.to_string(utility::datetime::ISO_8601));
|
||||
}
|
||||
|
||||
{{^hasModelImport}}
|
||||
utility::string_t ApiClient::parameterToString(const ModelBase& value)
|
||||
{
|
||||
return value.toJson().serialize();
|
||||
}
|
||||
{{/hasModelImport}}
|
||||
|
||||
utility::string_t ApiClient::parameterToString(bool value)
|
||||
{
|
||||
std::stringstream valueAsStringStream;
|
||||
valueAsStringStream << std::boolalpha << value;
|
||||
return utility::conversions::to_string_t(valueAsStringStream.str());
|
||||
}
|
||||
|
||||
pplx::task<web::http::http_response> ApiClient::callApi(
|
||||
const utility::string_t& path,
|
||||
const utility::string_t& method,
|
||||
const std::map<utility::string_t, utility::string_t>& queryParams,
|
||||
const std::shared_ptr<IHttpBody> postBody,
|
||||
const std::map<utility::string_t, utility::string_t>& headerParams,
|
||||
const std::map<utility::string_t, utility::string_t>& formParams,
|
||||
const std::map<utility::string_t, std::shared_ptr<HttpContent>>& fileParams,
|
||||
const utility::string_t& contentType
|
||||
) const
|
||||
{
|
||||
if (postBody != nullptr && formParams.size() != 0)
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("Cannot have body and form params"));
|
||||
}
|
||||
|
||||
if (postBody != nullptr && fileParams.size() != 0)
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("Cannot have body and file params"));
|
||||
}
|
||||
|
||||
if (fileParams.size() > 0 && contentType != utility::conversions::to_string_t("multipart/form-data"))
|
||||
{
|
||||
throw ApiException(400, utility::conversions::to_string_t("Operations with file parameters must be called with multipart/form-data"));
|
||||
}
|
||||
|
||||
web::http::client::http_client client(m_Configuration->getBaseUrl(), m_Configuration->getHttpConfig());
|
||||
|
||||
web::http::http_request request;
|
||||
for (const auto& kvp : headerParams)
|
||||
{
|
||||
request.headers().add(kvp.first, kvp.second);
|
||||
}
|
||||
|
||||
if (fileParams.size() > 0)
|
||||
{
|
||||
MultipartFormData uploadData;
|
||||
for (const auto& kvp : formParams)
|
||||
{
|
||||
uploadData.add(ModelBase::toHttpContent(kvp.first, kvp.second));
|
||||
}
|
||||
for (const auto& kvp : fileParams)
|
||||
{
|
||||
uploadData.add(ModelBase::toHttpContent(kvp.first, kvp.second));
|
||||
}
|
||||
std::stringstream data;
|
||||
uploadData.writeTo(data);
|
||||
auto bodyString = data.str();
|
||||
const auto length = bodyString.size();
|
||||
request.set_body(concurrency::streams::bytestream::open_istream(std::move(bodyString)), length, utility::conversions::to_string_t("multipart/form-data; boundary=") + uploadData.getBoundary());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (postBody != nullptr)
|
||||
{
|
||||
std::stringstream data;
|
||||
postBody->writeTo(data);
|
||||
auto bodyString = data.str();
|
||||
const auto length = bodyString.size();
|
||||
request.set_body(concurrency::streams::bytestream::open_istream(std::move(bodyString)), length, contentType);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (contentType == utility::conversions::to_string_t("application/json"))
|
||||
{
|
||||
web::json::value body_data = web::json::value::object();
|
||||
for (auto& kvp : formParams)
|
||||
{
|
||||
body_data[kvp.first] = ModelBase::toJson(kvp.second);
|
||||
}
|
||||
if (!formParams.empty())
|
||||
{
|
||||
request.set_body(body_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
web::http::uri_builder formData;
|
||||
for (const auto& kvp : formParams)
|
||||
{
|
||||
formData.append_query(kvp.first, kvp.second);
|
||||
}
|
||||
if (!formParams.empty())
|
||||
{
|
||||
request.set_body(formData.query(), utility::conversions::to_string_t("application/x-www-form-urlencoded"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
web::http::uri_builder builder(path);
|
||||
for (const auto& kvp : queryParams)
|
||||
{
|
||||
builder.append_query(kvp.first, kvp.second);
|
||||
}
|
||||
request.set_request_uri(builder.to_uri());
|
||||
request.set_method(method);
|
||||
if ( !request.headers().has( web::http::header_names::user_agent ) )
|
||||
{
|
||||
request.headers().add( web::http::header_names::user_agent, m_Configuration->getUserAgent() );
|
||||
}
|
||||
|
||||
return client.request(request);
|
||||
}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* ApiConfiguration.h
|
||||
*
|
||||
* This class represents a single item of a multipart-formdata request.
|
||||
*/
|
||||
|
||||
#ifndef {{apiHeaderGuardPrefix}}_ApiConfiguration_H_
|
||||
#define {{apiHeaderGuardPrefix}}_ApiConfiguration_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/http_client.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} ApiConfiguration
|
||||
{
|
||||
public:
|
||||
ApiConfiguration();
|
||||
virtual ~ApiConfiguration();
|
||||
|
||||
const web::http::client::http_client_config& getHttpConfig() const;
|
||||
void setHttpConfig( web::http::client::http_client_config& value );
|
||||
|
||||
utility::string_t getBaseUrl() const;
|
||||
void setBaseUrl( const utility::string_t value );
|
||||
|
||||
utility::string_t getUserAgent() const;
|
||||
void setUserAgent( const utility::string_t value );
|
||||
|
||||
std::map<utility::string_t, utility::string_t>& getDefaultHeaders();
|
||||
const std::map<utility::string_t, utility::string_t>& getDefaultHeaders() const;
|
||||
|
||||
utility::string_t getApiKey( const utility::string_t& prefix) const;
|
||||
void setApiKey( const utility::string_t& prefix, const utility::string_t& apiKey );
|
||||
|
||||
protected:
|
||||
utility::string_t m_BaseUrl;
|
||||
std::map<utility::string_t, utility::string_t> m_DefaultHeaders;
|
||||
std::map<utility::string_t, utility::string_t> m_ApiKeys;
|
||||
web::http::client::http_client_config m_HttpConfig;
|
||||
utility::string_t m_UserAgent;
|
||||
};
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
#endif /* {{apiHeaderGuardPrefix}}_ApiConfiguration_H_ */
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/ApiConfiguration.h"
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
ApiConfiguration::ApiConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
ApiConfiguration::~ApiConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
const web::http::client::http_client_config& ApiConfiguration::getHttpConfig() const
|
||||
{
|
||||
return m_HttpConfig;
|
||||
}
|
||||
|
||||
void ApiConfiguration::setHttpConfig( web::http::client::http_client_config& value )
|
||||
{
|
||||
m_HttpConfig = value;
|
||||
}
|
||||
|
||||
utility::string_t ApiConfiguration::getBaseUrl() const
|
||||
{
|
||||
return m_BaseUrl;
|
||||
}
|
||||
|
||||
void ApiConfiguration::setBaseUrl( const utility::string_t value )
|
||||
{
|
||||
m_BaseUrl = value;
|
||||
}
|
||||
|
||||
utility::string_t ApiConfiguration::getUserAgent() const
|
||||
{
|
||||
return m_UserAgent;
|
||||
}
|
||||
|
||||
void ApiConfiguration::setUserAgent( const utility::string_t value )
|
||||
{
|
||||
m_UserAgent = value;
|
||||
}
|
||||
|
||||
std::map<utility::string_t, utility::string_t>& ApiConfiguration::getDefaultHeaders()
|
||||
{
|
||||
return m_DefaultHeaders;
|
||||
}
|
||||
|
||||
const std::map<utility::string_t, utility::string_t>& ApiConfiguration::getDefaultHeaders() const
|
||||
{
|
||||
return m_DefaultHeaders;
|
||||
}
|
||||
|
||||
utility::string_t ApiConfiguration::getApiKey( const utility::string_t& prefix) const
|
||||
{
|
||||
auto result = m_ApiKeys.find(prefix);
|
||||
if( result != m_ApiKeys.end() )
|
||||
{
|
||||
return result->second;
|
||||
}
|
||||
return utility::conversions::to_string_t("");
|
||||
}
|
||||
|
||||
void ApiConfiguration::setApiKey( const utility::string_t& prefix, const utility::string_t& apiKey )
|
||||
{
|
||||
m_ApiKeys[prefix] = apiKey;
|
||||
}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* ApiException.h
|
||||
*
|
||||
* This is the exception being thrown in case the api call was not successful
|
||||
*/
|
||||
|
||||
#ifndef {{apiHeaderGuardPrefix}}_ApiException_H_
|
||||
#define {{apiHeaderGuardPrefix}}_ApiException_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/http_msg.h>
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} ApiException
|
||||
: public web::http::http_exception
|
||||
{
|
||||
public:
|
||||
ApiException( int errorCode
|
||||
, const utility::string_t& message
|
||||
, std::shared_ptr<std::istream> content = nullptr );
|
||||
ApiException( int errorCode
|
||||
, const utility::string_t& message
|
||||
, std::map<utility::string_t, utility::string_t>& headers
|
||||
, std::shared_ptr<std::istream> content = nullptr );
|
||||
virtual ~ApiException();
|
||||
|
||||
std::map<utility::string_t, utility::string_t>& getHeaders();
|
||||
std::shared_ptr<std::istream> getContent() const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<std::istream> m_Content;
|
||||
std::map<utility::string_t, utility::string_t> m_Headers;
|
||||
};
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{apiHeaderGuardPrefix}}_ApiBase_H_ */
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/ApiException.h"
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
||||
ApiException::ApiException( int errorCode
|
||||
, const utility::string_t& message
|
||||
, std::shared_ptr<std::istream> content /*= nullptr*/ )
|
||||
: web::http::http_exception( errorCode, message )
|
||||
, m_Content(content)
|
||||
{
|
||||
}
|
||||
ApiException::ApiException( int errorCode
|
||||
, const utility::string_t& message
|
||||
, std::map<utility::string_t, utility::string_t>& headers
|
||||
, std::shared_ptr<std::istream> content /*= nullptr*/ )
|
||||
: web::http::http_exception( errorCode, message )
|
||||
, m_Content(content)
|
||||
, m_Headers(headers)
|
||||
{
|
||||
}
|
||||
|
||||
ApiException::~ApiException()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<std::istream> ApiException::getContent() const
|
||||
{
|
||||
return m_Content;
|
||||
}
|
||||
|
||||
std::map<utility::string_t, utility::string_t>& ApiException::getHeaders()
|
||||
{
|
||||
return m_Headers;
|
||||
}
|
||||
|
||||
{{#apiNamespaceDeclarations}}
|
||||
}
|
||||
{{/apiNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake)
|
||||
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
91
api/_build/my-cpp-templates/cpp-restsdk/cmake-lists.mustache
Normal file
91
api/_build/my-cpp-templates/cpp-restsdk/cmake-lists.mustache
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#
|
||||
# {{{appName}}}
|
||||
# {{{appDescription}}}
|
||||
#
|
||||
# The version of the OpenAPI document: 1.0.0
|
||||
#
|
||||
# https://openapi-generator.tech
|
||||
#
|
||||
# NOTE: Auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
||||
cmake_minimum_required (VERSION 3.10)
|
||||
|
||||
project({{{packageName}}} CXX)
|
||||
|
||||
# Force -fPIC even if the project is configured for building a static library.
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
if(DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION OR
|
||||
DEFINED CMAKE_CXX20_EXTENSION_COMPILE_OPTION)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
elseif(DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION OR
|
||||
DEFINED CMAKE_CXX17_EXTENSION_COMPILE_OPTION)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
elseif(DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION OR
|
||||
DEFINED CMAKE_CXX14_EXTENSION_COMPILE_OPTION)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
find_package(cpprestsdk REQUIRED)
|
||||
target_compile_definitions(cpprestsdk::cpprest INTERFACE _TURN_OFF_PLATFORM_STRING)
|
||||
find_package(Boost REQUIRED)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
file(GLOB_RECURSE HEADER_FILES "include/*.h")
|
||||
file(GLOB_RECURSE SOURCE_FILES "src/*.cpp")
|
||||
|
||||
add_library(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES})
|
||||
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
|
||||
-Wall -Wno-unused-variable -Wno-unused-lambda-capture>
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::headers cpprestsdk::cpprest)
|
||||
|
||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
)
|
||||
57
api/_build/my-cpp-templates/cpp-restsdk/git_push.sh.mustache
Normal file
57
api/_build/my-cpp-templates/cpp-restsdk/git_push.sh.mustache
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/sh
|
||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||
#
|
||||
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
|
||||
|
||||
git_user_id=$1
|
||||
git_repo_id=$2
|
||||
release_note=$3
|
||||
git_host=$4
|
||||
|
||||
if [ "$git_host" = "" ]; then
|
||||
git_host="{{{gitHost}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
|
||||
fi
|
||||
|
||||
if [ "$git_user_id" = "" ]; then
|
||||
git_user_id="{{{gitUserId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||
fi
|
||||
|
||||
if [ "$git_repo_id" = "" ]; then
|
||||
git_repo_id="{{{gitRepoId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||
fi
|
||||
|
||||
if [ "$release_note" = "" ]; then
|
||||
release_note="{{{releaseNote}}}"
|
||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||
fi
|
||||
|
||||
# Initialize the local directory as a Git repository
|
||||
git init
|
||||
|
||||
# Adds the files in the local repository and stages them for commit.
|
||||
git add .
|
||||
|
||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||
git commit -m "$release_note"
|
||||
|
||||
# Sets the new remote
|
||||
git_remote=$(git remote)
|
||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||
|
||||
if [ "$GIT_TOKEN" = "" ]; then
|
||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
||||
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
else
|
||||
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
git pull origin master
|
||||
|
||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
|
||||
git push origin master 2>&1 | grep -v 'To https'
|
||||
29
api/_build/my-cpp-templates/cpp-restsdk/gitignore.mustache
Normal file
29
api/_build/my-cpp-templates/cpp-restsdk/gitignore.mustache
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* HttpContent.h
|
||||
*
|
||||
* This class represents a single item of a multipart-formdata request.
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_HttpContent_H_
|
||||
#define {{modelHeaderGuardPrefix}}_HttpContent_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} HttpContent
|
||||
{
|
||||
public:
|
||||
HttpContent();
|
||||
virtual ~HttpContent();
|
||||
|
||||
virtual utility::string_t getContentDisposition() const;
|
||||
virtual void setContentDisposition( const utility::string_t& value );
|
||||
|
||||
virtual utility::string_t getName() const;
|
||||
virtual void setName( const utility::string_t& value );
|
||||
|
||||
virtual utility::string_t getFileName() const;
|
||||
virtual void setFileName( const utility::string_t& value );
|
||||
|
||||
virtual utility::string_t getContentType() const;
|
||||
virtual void setContentType( const utility::string_t& value );
|
||||
|
||||
virtual std::shared_ptr<std::istream> getData() const;
|
||||
virtual void setData( std::shared_ptr<std::istream> value );
|
||||
|
||||
virtual void writeTo( std::ostream& stream );
|
||||
|
||||
protected:
|
||||
// NOTE: no utility::string_t here because those strings can only contain ascii
|
||||
utility::string_t m_ContentDisposition;
|
||||
utility::string_t m_Name;
|
||||
utility::string_t m_FileName;
|
||||
utility::string_t m_ContentType;
|
||||
std::shared_ptr<std::istream> m_Data;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_HttpContent_H_ */
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/HttpContent.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
HttpContent::HttpContent()
|
||||
{
|
||||
}
|
||||
|
||||
HttpContent::~HttpContent()
|
||||
{
|
||||
}
|
||||
|
||||
utility::string_t HttpContent::getContentDisposition() const
|
||||
{
|
||||
return m_ContentDisposition;
|
||||
}
|
||||
|
||||
void HttpContent::setContentDisposition( const utility::string_t & value )
|
||||
{
|
||||
m_ContentDisposition = value;
|
||||
}
|
||||
|
||||
utility::string_t HttpContent::getName() const
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
void HttpContent::setName( const utility::string_t & value )
|
||||
{
|
||||
m_Name = value;
|
||||
}
|
||||
|
||||
utility::string_t HttpContent::getFileName() const
|
||||
{
|
||||
return m_FileName;
|
||||
}
|
||||
|
||||
void HttpContent::setFileName( const utility::string_t & value )
|
||||
{
|
||||
m_FileName = value;
|
||||
}
|
||||
|
||||
utility::string_t HttpContent::getContentType() const
|
||||
{
|
||||
return m_ContentType;
|
||||
}
|
||||
|
||||
void HttpContent::setContentType( const utility::string_t & value )
|
||||
{
|
||||
m_ContentType = value;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::istream> HttpContent::getData() const
|
||||
{
|
||||
return m_Data;
|
||||
}
|
||||
|
||||
void HttpContent::setData( std::shared_ptr<std::istream> value )
|
||||
{
|
||||
m_Data = value;
|
||||
}
|
||||
|
||||
void HttpContent::writeTo( std::ostream& stream )
|
||||
{
|
||||
m_Data->seekg( 0, m_Data->beg );
|
||||
stream << m_Data->rdbuf();
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* IHttpBody.h
|
||||
*
|
||||
* This is the interface for contents that can be sent to a remote HTTP server.
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_IHttpBody_H_
|
||||
#define {{modelHeaderGuardPrefix}}_IHttpBody_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include <iostream>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} IHttpBody
|
||||
{
|
||||
public:
|
||||
virtual ~IHttpBody() { }
|
||||
|
||||
virtual void writeTo( std::ostream& stream ) = 0;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_IHttpBody_H_ */
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* JsonBody.h
|
||||
*
|
||||
* This is a JSON http body which can be submitted via http
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_JsonBody_H_
|
||||
#define {{modelHeaderGuardPrefix}}_JsonBody_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/IHttpBody.h"
|
||||
|
||||
#include <cpprest/json.h>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} JsonBody
|
||||
: public IHttpBody
|
||||
{
|
||||
public:
|
||||
JsonBody( const web::json::value& value );
|
||||
virtual ~JsonBody();
|
||||
|
||||
void writeTo( std::ostream& target ) override;
|
||||
|
||||
protected:
|
||||
web::json::value m_Json;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_JsonBody_H_ */
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/JsonBody.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
JsonBody::JsonBody( const web::json::value& json)
|
||||
: m_Json(json)
|
||||
{
|
||||
}
|
||||
|
||||
JsonBody::~JsonBody()
|
||||
{
|
||||
}
|
||||
|
||||
void JsonBody::writeTo( std::ostream& target )
|
||||
{
|
||||
m_Json.serialize(target);
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
15
api/_build/my-cpp-templates/cpp-restsdk/licenseInfo.mustache
Normal file
15
api/_build/my-cpp-templates/cpp-restsdk/licenseInfo.mustache
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* {{{appName}}}
|
||||
* {{{appDescription}}}
|
||||
*
|
||||
{{#version}}
|
||||
* The version of the OpenAPI document: {{{.}}}
|
||||
{{/version}}
|
||||
{{#infoEmail}}
|
||||
* Contact: {{{.}}}
|
||||
{{/infoEmail}}
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI-Generator {{{generatorVersion}}}.
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
288
api/_build/my-cpp-templates/cpp-restsdk/model-header.mustache
Normal file
288
api/_build/my-cpp-templates/cpp-restsdk/model-header.mustache
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
{{>licenseInfo}}
|
||||
{{#models}}{{#model}}/*
|
||||
* {{classname}}.h
|
||||
*
|
||||
* {{description}}
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_{{classname}}_H_
|
||||
#define {{modelHeaderGuardPrefix}}_{{classname}}_H_
|
||||
|
||||
{{#hasEnums}}
|
||||
#include <stdexcept>
|
||||
{{/hasEnums}}
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
#include <variant>
|
||||
{{/-first}}
|
||||
{{/oneOf}}
|
||||
{{^parent}}
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
{{/parent}}
|
||||
|
||||
{{#imports}}{{{this}}}
|
||||
{{/imports}}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
{{#vendorExtensions.x-has-forward-declarations}}
|
||||
{{#vendorExtensions.x-forward-declarations}}{{.}}
|
||||
{{/vendorExtensions.x-forward-declarations}}
|
||||
{{/vendorExtensions.x-has-forward-declarations}}
|
||||
{{#oneOf}}{{#-first}}
|
||||
|
||||
class {{declspec}} {{classname}}
|
||||
{
|
||||
public:
|
||||
{{classname}}() = default;
|
||||
~{{classname}}() = default;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
void validate();
|
||||
|
||||
web::json::value toJson() const;
|
||||
|
||||
template<typename Target>
|
||||
bool fromJson(const web::json::value& json) {
|
||||
// convert json to Target type
|
||||
Target target;
|
||||
if (!target.fromJson(json)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_variantValue = target;
|
||||
return true;
|
||||
}
|
||||
|
||||
void toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) const;
|
||||
|
||||
template<typename Target>
|
||||
bool fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) {
|
||||
// convert multipart to Target type
|
||||
Target target;
|
||||
if (!target.fromMultiPart(multipart, namePrefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_variantValue = target;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// {{classname}} members
|
||||
|
||||
using VariantType = std::variant<{{#oneOf}}{{^-first}}, {{/-first}}{{{.}}}{{/oneOf}}>;
|
||||
|
||||
const VariantType& getVariant() const;
|
||||
void setVariant(VariantType value);
|
||||
|
||||
protected:
|
||||
VariantType m_variantValue;
|
||||
};
|
||||
|
||||
{{/-first}}{{/oneOf}}
|
||||
{{^oneOf}}
|
||||
{{#isEnum}}
|
||||
class {{declspec}} {{classname}}
|
||||
: public {{{parent}}}{{^parent}}ModelBase{{/parent}}
|
||||
{
|
||||
public:
|
||||
{{classname}}();
|
||||
{{classname}}(utility::string_t str);
|
||||
operator utility::string_t() const {
|
||||
return enumToStrMap.at(getValue());
|
||||
}
|
||||
|
||||
{{! operator std::string() const {
|
||||
return enumToStrMap.at(getValue());
|
||||
} }}
|
||||
|
||||
virtual ~{{classname}}();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// ModelBase overrides
|
||||
|
||||
void validate() override;
|
||||
|
||||
web::json::value toJson() const override;
|
||||
bool fromJson(const web::json::value& json) override;
|
||||
|
||||
void toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) const override;
|
||||
bool fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) override;
|
||||
|
||||
enum class e{{classname}}
|
||||
{
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{#enumDescription}}
|
||||
/// <summary>
|
||||
/// {{.}}
|
||||
/// </summary>
|
||||
{{/enumDescription}}
|
||||
{{{name}}}{{^last}},{{/last}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
};
|
||||
|
||||
e{{classname}} getValue() const;
|
||||
void setValue(e{{classname}} const value);
|
||||
|
||||
protected:
|
||||
e{{classname}} m_value;
|
||||
std::map<e{{classname}},utility::string_t> enumToStrMap = {
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{ e{{classname}}::{{{name}}}, _XPLATSTR("{{{name}}}") }{{^-last}},{{/-last}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
};
|
||||
std::map<utility::string_t,e{{classname}}> strToEnumMap = {
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{ _XPLATSTR("{{{name}}}"), e{{classname}}::{{{name}}} }{{^-last}},{{/-last}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
};
|
||||
|
||||
};
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
|
||||
{{#description}}
|
||||
/// <summary>
|
||||
/// {{description}}
|
||||
/// </summary>
|
||||
{{/description}}
|
||||
class {{declspec}} {{classname}}
|
||||
: public {{{parent}}}{{^parent}}ModelBase{{/parent}}
|
||||
{
|
||||
public:
|
||||
{{classname}}();
|
||||
virtual ~{{classname}}();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// ModelBase overrides
|
||||
|
||||
void validate() override;
|
||||
|
||||
web::json::value toJson() const override;
|
||||
bool fromJson(const web::json::value& json) override;
|
||||
|
||||
void toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) const override;
|
||||
bool fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) override;
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// {{classname}} members
|
||||
|
||||
{{! ENUM DEFINITIONS }}
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{#isEnum}}
|
||||
enum class {{#isContainer}}{{{enumName}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}
|
||||
{
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{{name}}}{{^last}},{{/last}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
};
|
||||
{{#description}}
|
||||
/// <summary>
|
||||
/// {{description}}
|
||||
/// </summary>
|
||||
{{/description}}
|
||||
{{/isEnum}}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{#isEnum}}
|
||||
{{#isContainer}}
|
||||
{{! ENUM CONVERSIONS }}
|
||||
{{{enumName}}} to{{{enumName}}}(const utility::string_t& value) const;
|
||||
const utility::string_t from{{{enumName}}}(const {{{enumName}}} value) const;
|
||||
{{#isArray}}
|
||||
{{{datatypeWithEnum}}} to{{{enumName}}}(const {{{dataType}}}& value) const;
|
||||
{{{dataType}}} from{{{enumName}}}(const {{{datatypeWithEnum}}}& value) const;
|
||||
{{/isArray}}{{/isContainer}}{{^isContainer}}
|
||||
{{{datatypeWithEnum}}} to{{{datatypeWithEnum}}}(const utility::string_t& value) const;
|
||||
const utility::string_t from{{{datatypeWithEnum}}}(const {{{datatypeWithEnum}}} value) const;
|
||||
{{/isContainer}}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
|
||||
{{! SETTER AND GETTERS }}
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{#description}}
|
||||
/// <summary>
|
||||
/// {{description}}
|
||||
/// </summary>
|
||||
{{/description}}
|
||||
{{#isContainer}}
|
||||
{{^isEnum}}
|
||||
{{{dataType}}} {{getter}}() const;
|
||||
{{/isEnum}}
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{^isEnum}}
|
||||
{{{dataType}}} {{getter}}() const;
|
||||
{{/isEnum}}
|
||||
{{/isContainer}}
|
||||
{{#isEnum}}
|
||||
{{^isMap}}
|
||||
{{{datatypeWithEnum}}} {{getter}}() const;
|
||||
{{/isMap}}
|
||||
{{#isMap}}
|
||||
{{{dataType}}} {{getter}}() const;
|
||||
{{/isMap}}
|
||||
{{/isEnum}}
|
||||
bool {{nameInCamelCase}}IsSet() const;
|
||||
void unset{{name}}();
|
||||
{{#isPrimitiveType}}
|
||||
void {{setter}}({{{dataType}}} value);
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
{{^isEnum}}
|
||||
void {{setter}}(const {{{dataType}}}& value);
|
||||
{{/isEnum}}
|
||||
{{/isPrimitiveType}}
|
||||
{{#isEnum}}
|
||||
void {{setter}}(const {{^isMap}}{{{datatypeWithEnum}}}{{/isMap}}{{#isMap}}{{{dataType}}}{{/isMap}} value);
|
||||
{{/isEnum}}
|
||||
{{/isInherited}}
|
||||
|
||||
{{/vars}}
|
||||
|
||||
protected:
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{^isEnum}}
|
||||
{{{dataType}}} m_{{name}};
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
{{^isMap}}{{{datatypeWithEnum}}}{{/isMap}}{{#isMap}}{{{dataType}}}{{/isMap}} m_{{name}};
|
||||
{{/isEnum}}
|
||||
bool m_{{name}}IsSet;
|
||||
{{/isInherited}}
|
||||
|
||||
{{/vars}}
|
||||
};
|
||||
|
||||
{{/isEnum}}
|
||||
{{/oneOf}}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_{{classname}}_H_ */
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
457
api/_build/my-cpp-templates/cpp-restsdk/model-source.mustache
Normal file
457
api/_build/my-cpp-templates/cpp-restsdk/model-source.mustache
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
{{>licenseInfo}}
|
||||
{{#models}}{{#model}}
|
||||
|
||||
#include "{{packageName}}/model/{{classFilename}}.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
|
||||
void {{classname}}::validate()
|
||||
{
|
||||
// TODO: implement validation
|
||||
}
|
||||
|
||||
const {{classname}}::VariantType& {{classname}}::getVariant() const
|
||||
{
|
||||
return m_variantValue;
|
||||
}
|
||||
|
||||
void {{classname}}::setVariant({{classname}}::VariantType value)
|
||||
{
|
||||
m_variantValue = value;
|
||||
}
|
||||
|
||||
web::json::value {{classname}}::toJson() const
|
||||
{
|
||||
web::json::value val = web::json::value::object();
|
||||
|
||||
std::visit([&](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
val = web::json::value::null();
|
||||
} else {
|
||||
val = arg.toJson();
|
||||
}
|
||||
}, m_variantValue);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void {{classname}}::toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix) const
|
||||
{
|
||||
std::visit([&](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (!std::is_same_v<T, std::monostate>) {
|
||||
arg.toMultipart(multipart, prefix);
|
||||
}
|
||||
}, m_variantValue);
|
||||
}
|
||||
|
||||
{{#oneOf}}
|
||||
template bool {{classname}}::fromJson<{{.}}>(const web::json::value& json);
|
||||
template bool {{classname}}::fromMultiPart<{{.}}>(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix);
|
||||
{{/oneOf}}
|
||||
|
||||
{{/-first}}
|
||||
{{/oneOf}}
|
||||
{{^oneOf}}
|
||||
{{#isEnum}}
|
||||
|
||||
namespace
|
||||
{
|
||||
using EnumUnderlyingType = {{#isNumeric}}int64_t{{/isNumeric}}{{^isNumeric}}utility::string_t{{/isNumeric}};
|
||||
|
||||
{{classname}}::e{{classname}} toEnum(const EnumUnderlyingType& val)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
{{#isNumeric}}
|
||||
switch (val)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{value}}:
|
||||
return {{classname}}::e{{classname}}::{{name}};
|
||||
{{#-last}}
|
||||
default:
|
||||
break;
|
||||
{{/-last}}
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/isNumeric}}
|
||||
{{^isNumeric}}
|
||||
{{#enumVars}}
|
||||
if (val == utility::conversions::to_string_t(_XPLATSTR("{{{value}}}")))
|
||||
return {{classname}}::e{{classname}}::{{name}};
|
||||
{{/enumVars}}
|
||||
{{/isNumeric}}
|
||||
{{/allowableValues}}
|
||||
return {};
|
||||
}
|
||||
|
||||
EnumUnderlyingType fromEnum({{classname}}::e{{classname}} e)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
switch (e)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{classname}}::e{{classname}}::{{name}}:
|
||||
return {{#isNumeric}}{{value}}{{/isNumeric}}{{^isNumeric}}_XPLATSTR("{{value}}"){{/isNumeric}};
|
||||
{{#-last}}
|
||||
default:
|
||||
break;
|
||||
{{/-last}}
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
{{classname}}::{{classname}}()
|
||||
{
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}()
|
||||
{
|
||||
}
|
||||
|
||||
void {{classname}}::validate()
|
||||
{
|
||||
// TODO: implement validation
|
||||
}
|
||||
|
||||
web::json::value {{classname}}::toJson() const
|
||||
{
|
||||
auto val = fromEnum(m_value);
|
||||
return web::json::value(val);
|
||||
}
|
||||
|
||||
bool {{classname}}::fromJson(const web::json::value& val)
|
||||
{
|
||||
m_value = toEnum({{#isNumeric}}val.as_number().to_int64(){{/isNumeric}}{{^isNumeric}}val.as_string(){{/isNumeric}});
|
||||
return true;
|
||||
}
|
||||
|
||||
void {{classname}}::toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix) const
|
||||
{
|
||||
utility::string_t namePrefix = prefix;
|
||||
if (!namePrefix.empty() && namePrefix.back() != _XPLATSTR('.'))
|
||||
{
|
||||
namePrefix.push_back(_XPLATSTR('.'));
|
||||
}
|
||||
|
||||
auto e = fromEnum(m_value);
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix, e));
|
||||
}
|
||||
|
||||
bool {{classname}}::fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix)
|
||||
{
|
||||
bool ok = true;
|
||||
utility::string_t namePrefix = prefix;
|
||||
if (!namePrefix.empty() && namePrefix.back() != _XPLATSTR('.'))
|
||||
{
|
||||
namePrefix.push_back(_XPLATSTR('.'));
|
||||
}
|
||||
{
|
||||
EnumUnderlyingType e;
|
||||
ok = ModelBase::fromHttpContent(multipart->getContent(namePrefix), e);
|
||||
if (ok)
|
||||
{
|
||||
auto v = toEnum(e);
|
||||
setValue(v);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
{{classname}}::e{{classname}} {{classname}}::getValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void {{classname}}::setValue({{classname}}::e{{classname}} const value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
{{classname}}::{{classname}}(utility::string_t str){
|
||||
setValue( strToEnumMap[str] );
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
|
||||
{{classname}}::{{classname}}()
|
||||
{
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{^isContainer}}
|
||||
{{^isEnum}}
|
||||
{{#isPrimitiveType}}
|
||||
m_{{name}} = {{{defaultValue}}};
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
{{#isString}}
|
||||
m_{{name}} = {{{defaultValue}}};
|
||||
{{/isString}}
|
||||
{{#isDateTime}}
|
||||
m_{{name}} = {{{defaultValue}}};
|
||||
{{/isDateTime}}
|
||||
{{/isPrimitiveType}}
|
||||
{{/isEnum}}
|
||||
{{/isContainer}}
|
||||
m_{{name}}IsSet = false;
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}()
|
||||
{
|
||||
}
|
||||
|
||||
void {{classname}}::validate()
|
||||
{
|
||||
// TODO: implement validation
|
||||
}
|
||||
|
||||
web::json::value {{classname}}::toJson() const
|
||||
{
|
||||
{{#parent}}
|
||||
web::json::value val = this->{{{.}}}::toJson();
|
||||
{{/parent}}
|
||||
{{^parent}}
|
||||
web::json::value val = web::json::value::object();
|
||||
{{/parent}}
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
if(m_{{name}}IsSet)
|
||||
{
|
||||
{{#isEnum}}{{#isContainer}}{{#isArray}}
|
||||
{{{dataType}}} refVal = from{{{enumName}}}(m_{{name}});
|
||||
{{/isArray}}{{#isMap}}
|
||||
val[utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))] = ModelBase::toJson(m_{{name}});
|
||||
{{/isMap}}{{/isContainer}}{{^isContainer}}
|
||||
utility::string_t refVal = from{{{datatypeWithEnum}}}(m_{{name}});
|
||||
{{/isContainer}}{{^isMap}}val[utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))] = ModelBase::toJson(refVal);
|
||||
{{/isMap}}{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
val[utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))] = ModelBase::toJson(m_{{name}});
|
||||
{{/isEnum}}
|
||||
}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool {{classname}}::fromJson(const web::json::value& val)
|
||||
{
|
||||
bool ok = true;
|
||||
{{#parent}}
|
||||
ok &= this->{{{.}}}::fromJson(val);
|
||||
{{/parent}}
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))))
|
||||
{
|
||||
const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("{{baseName}}")));
|
||||
if(!fieldValue.is_null())
|
||||
{
|
||||
{{{dataType}}} refVal_{{setter}};
|
||||
ok &= ModelBase::fromJson(fieldValue, refVal_{{setter}});
|
||||
{{^isEnum}}
|
||||
{{setter}}(refVal_{{setter}});
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}{{#isContainer}}{{#isArray}}
|
||||
{{setter}}(to{{{enumName}}}(refVal_{{setter}}));
|
||||
{{/isArray}}{{#isMap}}
|
||||
{{setter}}(refVal_{{setter}});
|
||||
{{/isMap}}{{/isContainer}}{{^isContainer}}
|
||||
{{setter}}(to{{{datatypeWithEnum}}}(refVal_{{setter}}));
|
||||
{{/isContainer}}{{/isEnum}}
|
||||
}
|
||||
}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void {{classname}}::toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix) const
|
||||
{
|
||||
utility::string_t namePrefix = prefix;
|
||||
if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR(".")))
|
||||
{
|
||||
namePrefix += utility::conversions::to_string_t(_XPLATSTR("."));
|
||||
}
|
||||
{{#vars}}
|
||||
if(m_{{name}}IsSet)
|
||||
{
|
||||
{{^isEnum}}
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("{{baseName}}")), m_{{name}}));
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
{{#isContainer}}
|
||||
{{#isArray}}
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("{{baseName}}")), from{{{enumName}}}(m_{{name}})));
|
||||
{{/isArray}}{{#isMap}}
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("{{baseName}}")), m_{{name}}));
|
||||
{{/isMap}}
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("{{baseName}}")), from{{{datatypeWithEnum}}}(m_{{name}})));
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
}
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
bool {{classname}}::fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix)
|
||||
{
|
||||
bool ok = true;
|
||||
utility::string_t namePrefix = prefix;
|
||||
if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR(".")))
|
||||
{
|
||||
namePrefix += utility::conversions::to_string_t(_XPLATSTR("."));
|
||||
}
|
||||
|
||||
{{#vars}}
|
||||
if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))))
|
||||
{
|
||||
{{{dataType}}} refVal_{{setter}};
|
||||
ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("{{baseName}}"))), refVal_{{setter}} );
|
||||
{{^isEnum}}
|
||||
{{setter}}(refVal_{{setter}});
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
{{#isContainer}}
|
||||
{{#isArray}}
|
||||
{{setter}}(to{{{enumName}}}(refVal_{{setter}}));
|
||||
{{/isArray}}
|
||||
{{#isMap}}
|
||||
{{setter}}(refVal_{{setter}});
|
||||
{{/isMap}}
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{setter}}(to{{{datatypeWithEnum}}}(refVal_{{setter}}));
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
}
|
||||
{{/vars}}
|
||||
return ok;
|
||||
}
|
||||
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{#isEnum}}
|
||||
{{#isContainer}}
|
||||
{{classname}}::{{{enumName}}} {{classname}}::to{{{enumName}}}(const utility::string_t& value) const
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{classname}}::{{{datatypeWithEnum}}} {{classname}}::to{{{datatypeWithEnum}}}(const {{dataType}}& value) const
|
||||
{{/isContainer}}
|
||||
{
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
if (value == utility::conversions::to_string_t("{{value}}")) {
|
||||
return {{#isContainer}}{{{enumName}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}::{{name}};
|
||||
}
|
||||
{{/enumVars}}{{/allowableValues}}
|
||||
throw std::invalid_argument("Invalid value for conversion to {{{datatypeWithEnum}}}");
|
||||
}
|
||||
|
||||
{{#isContainer}}
|
||||
const utility::string_t {{classname}}::from{{{enumName}}}(const {{{enumName}}} value) const
|
||||
{{/isContainer}}{{^isContainer}}
|
||||
const {{dataType}} {{classname}}::from{{{datatypeWithEnum}}}(const {{{datatypeWithEnum}}} value) const
|
||||
{{/isContainer}}
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
case {{#isContainer}}{{{enumName}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}::{{name}}: return utility::conversions::to_string_t("{{value}}");
|
||||
{{/enumVars}}{{/allowableValues}}
|
||||
}
|
||||
}
|
||||
|
||||
{{#isContainer}}
|
||||
{{#isArray}}
|
||||
{{{dataType}}} {{{classname}}}::from{{{enumName}}}(const {{{datatypeWithEnum}}}& value) const
|
||||
{
|
||||
{{{dataType}}} ret;
|
||||
for (auto it = value.begin(); it != value.end(); it++) {
|
||||
ret.push_back(from{{{enumName}}}(*it));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
{{{baseType}}}<{{classname}}::{{{enumName}}}> {{{classname}}}::to{{{enumName}}}(const {{{dataType}}}& value) const
|
||||
{
|
||||
{{{datatypeWithEnum}}} ret;
|
||||
for (auto it = value.begin(); it != value.end(); it++) {
|
||||
ret.push_back(to{{{enumName}}}(*it));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
{{/isArray}}
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
|
||||
{{#vars}}
|
||||
{{^isInherited}}
|
||||
{{#isContainer}}
|
||||
{{^isEnum}}
|
||||
{{{dataType}}} {{classname}}::{{getter}}() const
|
||||
{
|
||||
return m_{{name}};
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{^isEnum}}
|
||||
{{{dataType}}} {{classname}}::{{getter}}() const
|
||||
{
|
||||
return m_{{name}};
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/isContainer}}
|
||||
{{#isEnum}}
|
||||
{{^isMap}}{{#isArray}}{{{baseType}}}<{{/isArray}}{{{classname}}}::{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isMap}}{{#isMap}}{{{dataType}}}{{/isMap}} {{classname}}::{{getter}}() const
|
||||
{
|
||||
return m_{{name}};
|
||||
}
|
||||
{{/isEnum}}
|
||||
|
||||
{{#isPrimitiveType}}
|
||||
void {{classname}}::{{setter}}({{{dataType}}} value)
|
||||
{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isEnum}}
|
||||
void {{classname}}::{{setter}}(const {{{dataType}}}& value)
|
||||
{{/isEnum}}{{/isPrimitiveType}}{{#isEnum}}
|
||||
void {{classname}}::{{setter}}(const {{^isMap}}{{{datatypeWithEnum}}}{{/isMap}}{{#isMap}}{{{dataType}}}{{/isMap}} value)
|
||||
{{/isEnum}}
|
||||
{
|
||||
m_{{name}} = value;
|
||||
m_{{name}}IsSet = true;
|
||||
}
|
||||
|
||||
bool {{classname}}::{{nameInCamelCase}}IsSet() const
|
||||
{
|
||||
return m_{{name}}IsSet;
|
||||
}
|
||||
|
||||
void {{classname}}::unset{{name}}()
|
||||
{
|
||||
m_{{name}}IsSet = false;
|
||||
}
|
||||
{{/isInherited}}{{/vars}}
|
||||
{{/isEnum}}
|
||||
{{/oneOf}}
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
|
@ -0,0 +1,493 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* ModelBase.h
|
||||
*
|
||||
* This is the base class for all model classes
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_ModelBase_H_
|
||||
#define {{modelHeaderGuardPrefix}}_ModelBase_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
|
||||
#include "{{packageName}}/HttpContent.h"
|
||||
#include "{{packageName}}/MultipartFormData.h"
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/json.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} ModelBase
|
||||
{
|
||||
public:
|
||||
ModelBase();
|
||||
virtual ~ModelBase();
|
||||
|
||||
virtual void validate() = 0;
|
||||
|
||||
virtual web::json::value toJson() const = 0;
|
||||
virtual bool fromJson( const web::json::value& json ) = 0;
|
||||
|
||||
virtual void toMultipart( std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix ) const = 0;
|
||||
virtual bool fromMultiPart( std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix ) = 0;
|
||||
|
||||
virtual bool isSet() const;
|
||||
|
||||
static utility::string_t toString( const bool val );
|
||||
static utility::string_t toString( const float val );
|
||||
static utility::string_t toString( const double val );
|
||||
static utility::string_t toString( const int32_t val );
|
||||
static utility::string_t toString( const int64_t val );
|
||||
static utility::string_t toString( const utility::string_t &val );
|
||||
static utility::string_t toString( const utility::datetime &val );
|
||||
static utility::string_t toString( const web::json::value &val );
|
||||
static utility::string_t toString( const std::shared_ptr<HttpContent>& val );
|
||||
template <typename T>
|
||||
static utility::string_t toString( const std::shared_ptr<T>& val );
|
||||
template <typename T>
|
||||
static utility::string_t toString( const std::vector<T> & val );
|
||||
template <typename T>
|
||||
static utility::string_t toString( const std::set<T> & val );
|
||||
|
||||
static web::json::value toJson( bool val );
|
||||
static web::json::value toJson( float val );
|
||||
static web::json::value toJson( double val );
|
||||
static web::json::value toJson( int32_t val );
|
||||
static web::json::value toJson( int64_t val );
|
||||
static web::json::value toJson( const utility::string_t& val );
|
||||
static web::json::value toJson( const utility::datetime& val );
|
||||
static web::json::value toJson( const web::json::value& val );
|
||||
static web::json::value toJson( const std::shared_ptr<HttpContent>& val );
|
||||
template<typename T>
|
||||
static web::json::value toJson( const std::shared_ptr<T>& val );
|
||||
static web::json::value toJson( const std::shared_ptr<utility::datetime>& val );
|
||||
template<typename T>
|
||||
static web::json::value toJson( const std::vector<T>& val );
|
||||
template<typename T>
|
||||
static web::json::value toJson( const std::set<T>& val );
|
||||
template<typename T>
|
||||
static web::json::value toJson( const std::map<utility::string_t, T>& val );
|
||||
|
||||
static bool fromString( const utility::string_t& val, bool & );
|
||||
static bool fromString( const utility::string_t& val, float & );
|
||||
static bool fromString( const utility::string_t& val, double & );
|
||||
static bool fromString( const utility::string_t& val, int32_t & );
|
||||
static bool fromString( const utility::string_t& val, int64_t & );
|
||||
static bool fromString( const utility::string_t& val, utility::string_t & );
|
||||
static bool fromString( const utility::string_t& val, utility::datetime & );
|
||||
static bool fromString( const utility::string_t& val, web::json::value & );
|
||||
static bool fromString( const utility::string_t& val, std::shared_ptr<HttpContent> & );
|
||||
template<typename T>
|
||||
static bool fromString( const utility::string_t& val, std::shared_ptr<T>& );
|
||||
static bool fromString( const utility::string_t& val, std::shared_ptr<utility::datetime>& outVal );
|
||||
template<typename T>
|
||||
static bool fromString( const utility::string_t& val, std::vector<T> & );
|
||||
template<typename T>
|
||||
static bool fromString( const utility::string_t& val, std::set<T> & );
|
||||
template<typename T>
|
||||
static bool fromString( const utility::string_t& val, std::map<utility::string_t, T> & );
|
||||
|
||||
static bool fromJson( const web::json::value& val, bool & );
|
||||
static bool fromJson( const web::json::value& val, float & );
|
||||
static bool fromJson( const web::json::value& val, double & );
|
||||
static bool fromJson( const web::json::value& val, int32_t & );
|
||||
static bool fromJson( const web::json::value& val, int64_t & );
|
||||
static bool fromJson( const web::json::value& val, utility::string_t & );
|
||||
static bool fromJson( const web::json::value& val, utility::datetime & );
|
||||
static bool fromJson( const web::json::value& val, web::json::value & );
|
||||
static bool fromJson( const web::json::value& val, std::shared_ptr<HttpContent> & );
|
||||
template<typename T>
|
||||
static bool fromJson( const web::json::value& val, std::shared_ptr<T>& );
|
||||
static bool fromJson( const web::json::value& val, std::shared_ptr<utility::datetime> &outVal );
|
||||
template<typename T>
|
||||
static bool fromJson( const web::json::value& val, std::vector<T> & );
|
||||
template<typename T>
|
||||
static bool fromJson( const web::json::value& val, std::set<T> & );
|
||||
template<typename T>
|
||||
static bool fromJson( const web::json::value& val, std::map<utility::string_t, T> & );
|
||||
|
||||
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, bool value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, float value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, double value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, int32_t value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, int64_t value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const utility::string_t& value, const utility::string_t& contentType = utility::conversions::to_string_t(""));
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const utility::datetime& value, const utility::string_t& contentType = utility::conversions::to_string_t(""));
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const web::json::value& value, const utility::string_t& contentType = utility::conversions::to_string_t("application/json") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const std::shared_ptr<HttpContent>& );
|
||||
template <typename T>
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const std::shared_ptr<T>& , const utility::string_t& contentType = utility::conversions::to_string_t("application/json") );
|
||||
static std::shared_ptr<HttpContent> toHttpContent(const utility::string_t& name, const std::shared_ptr<utility::datetime>& value , const utility::string_t& contentType = utility::conversions::to_string_t("application/json") );
|
||||
template <typename T>
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const std::vector<T>& value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
template <typename T>
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const std::set<T>& value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
template <typename T>
|
||||
static std::shared_ptr<HttpContent> toHttpContent( const utility::string_t& name, const std::map<utility::string_t, T>& value, const utility::string_t& contentType = utility::conversions::to_string_t("") );
|
||||
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, bool & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, float & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, double & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, int64_t & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, int32_t & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, utility::string_t & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, utility::datetime & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, web::json::value & );
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, std::shared_ptr<HttpContent>& );
|
||||
template <typename T>
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, std::shared_ptr<T>& );
|
||||
template <typename T>
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, std::vector<T> & );
|
||||
template <typename T>
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, std::set<T> & );
|
||||
template <typename T>
|
||||
static bool fromHttpContent( std::shared_ptr<HttpContent> val, std::map<utility::string_t, T> & );
|
||||
|
||||
static utility::string_t toBase64( utility::string_t value );
|
||||
static utility::string_t toBase64( std::shared_ptr<std::istream> value );
|
||||
static std::shared_ptr<std::istream> fromBase64( const utility::string_t& encoded );
|
||||
protected:
|
||||
bool m_IsSet;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
utility::string_t ModelBase::toString( const std::shared_ptr<T>& val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
if( val != nullptr )
|
||||
{
|
||||
val->toJson().serialize(ss);
|
||||
}
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
|
||||
// std::vector to string
|
||||
template<typename T>
|
||||
utility::string_t ModelBase::toString( const std::vector<T> & val )
|
||||
{
|
||||
utility::string_t strArray;
|
||||
for ( const auto &item : val )
|
||||
{
|
||||
strArray.append( toString(item) + "," );
|
||||
}
|
||||
if (val.count() > 0)
|
||||
{
|
||||
strArray.pop_back();
|
||||
}
|
||||
return strArray;
|
||||
}
|
||||
|
||||
// std::set to string
|
||||
template<typename T>
|
||||
utility::string_t ModelBase::toString( const std::set<T> & val )
|
||||
{
|
||||
utility::string_t strArray;
|
||||
for ( const auto &item : val )
|
||||
{
|
||||
strArray.append( toString(item) + "," );
|
||||
}
|
||||
if (val.count() > 0)
|
||||
{
|
||||
strArray.pop_back();
|
||||
}
|
||||
return strArray;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
web::json::value ModelBase::toJson( const std::shared_ptr<T>& val )
|
||||
{
|
||||
web::json::value retVal;
|
||||
if(val != nullptr)
|
||||
{
|
||||
retVal = val->toJson();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// std::vector to json
|
||||
template<typename T>
|
||||
web::json::value ModelBase::toJson( const std::vector<T>& value )
|
||||
{
|
||||
std::vector<web::json::value> ret;
|
||||
for ( const auto& x : value )
|
||||
{
|
||||
ret.push_back( toJson(x) );
|
||||
}
|
||||
return web::json::value::array(ret);
|
||||
}
|
||||
|
||||
// std::set to json
|
||||
template<typename T>
|
||||
web::json::value ModelBase::toJson( const std::set<T>& value )
|
||||
{
|
||||
// There's no prototype web::json::value::array(...) taking a std::set parameter. Converting to std::vector to get an array.
|
||||
std::vector<web::json::value> ret;
|
||||
for ( const auto& x : value )
|
||||
{
|
||||
ret.push_back( toJson(x) );
|
||||
}
|
||||
return web::json::value::array(ret);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
web::json::value ModelBase::toJson( const std::map<utility::string_t, T>& val )
|
||||
{
|
||||
web::json::value obj;
|
||||
for ( const auto &itemkey : val )
|
||||
{
|
||||
obj[itemkey.first] = toJson( itemkey.second );
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromString( const utility::string_t& val, std::shared_ptr<T>& outVal )
|
||||
{
|
||||
bool ok = false;
|
||||
if(outVal == nullptr)
|
||||
{
|
||||
outVal = std::make_shared<T>();
|
||||
}
|
||||
if( outVal != nullptr )
|
||||
{
|
||||
ok = outVal->fromJson(web::json::value::parse(val));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromString(const utility::string_t& val, std::vector<T>& outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
web::json::value jsonValue = web::json::value::parse(val);
|
||||
if (jsonValue.is_array())
|
||||
{
|
||||
for (const web::json::value& jitem : jsonValue.as_array())
|
||||
{
|
||||
T item;
|
||||
ok &= fromJson(jitem, item);
|
||||
outVal.push_back(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T item;
|
||||
ok = fromJson(jsonValue, item);
|
||||
outVal.push_back(item);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromString(const utility::string_t& val, std::set<T>& outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
web::json::value jsonValue = web::json::value::parse(val);
|
||||
if (jsonValue.is_array())
|
||||
{
|
||||
for (const web::json::value& jitem : jsonValue.as_array())
|
||||
{
|
||||
T item;
|
||||
ok &= fromJson(jitem, item);
|
||||
outVal.insert(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T item;
|
||||
ok = fromJson(jsonValue, item);
|
||||
outVal.insert(item);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromString(const utility::string_t& val, std::map<utility::string_t, T>& outVal )
|
||||
{
|
||||
bool ok = false;
|
||||
web::json::value jsonValue = web::json::value::parse(val);
|
||||
if (jsonValue.is_array())
|
||||
{
|
||||
for (const web::json::value& jitem : jsonValue.as_array())
|
||||
{
|
||||
T item;
|
||||
ok &= fromJson(jitem, item);
|
||||
outVal.insert({ val, item });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T item;
|
||||
ok = fromJson(jsonValue, item);
|
||||
outVal.insert({ val, item });
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromJson( const web::json::value& val, std::shared_ptr<T> &outVal )
|
||||
{
|
||||
bool ok = false;
|
||||
if(outVal == nullptr)
|
||||
{
|
||||
outVal = std::make_shared<T>();
|
||||
}
|
||||
if( outVal != nullptr )
|
||||
{
|
||||
ok = outVal->fromJson(val);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromJson( const web::json::value& val, std::vector<T> &outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
if (val.is_array())
|
||||
{
|
||||
for (const web::json::value & jitem : val.as_array())
|
||||
{
|
||||
T item;
|
||||
ok &= fromJson(jitem, item);
|
||||
outVal.push_back(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromJson(const web::json::value& val, std::set<T>& outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
if (val.is_array())
|
||||
{
|
||||
for (const web::json::value& jitem : val.as_array())
|
||||
{
|
||||
T item;
|
||||
ok &= fromJson(jitem, item);
|
||||
outVal.insert(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T item;
|
||||
ok = fromJson(val, item);
|
||||
outVal.insert(item);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template<typename T>
|
||||
bool ModelBase::fromJson( const web::json::value& jval, std::map<utility::string_t, T> &outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
if ( jval.is_object() )
|
||||
{
|
||||
auto obj = jval.as_object();
|
||||
for( auto objItr = obj.begin() ; objItr != obj.end() ; objItr++ )
|
||||
{
|
||||
T itemVal;
|
||||
ok &= fromJson(objItr->second, itemVal);
|
||||
outVal.insert(std::pair<utility::string_t, T>(objItr->first, itemVal));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
template <typename T>
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent(const utility::string_t& name, const std::shared_ptr<T>& value , const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content = std::make_shared<HttpContent>();
|
||||
if (value != nullptr )
|
||||
{
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::make_shared<std::stringstream>( utility::conversions::to_utf8string(value->toJson().serialize()) ) );
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const std::vector<T>& value, const utility::string_t& contentType )
|
||||
{
|
||||
web::json::value json_array = ModelBase::toJson(value);
|
||||
std::shared_ptr<HttpContent> content = std::make_shared<HttpContent>();
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::make_shared<std::stringstream>( utility::conversions::to_utf8string(json_array.serialize()) ) );
|
||||
return content;
|
||||
}
|
||||
template <typename T>
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const std::set<T>& value, const utility::string_t& contentType )
|
||||
{
|
||||
web::json::value json_array = ModelBase::toJson(value);
|
||||
std::shared_ptr<HttpContent> content = std::make_shared<HttpContent>();
|
||||
content->setName(name);
|
||||
content->setContentDisposition(utility::conversions::to_string_t("form-data"));
|
||||
content->setContentType(contentType);
|
||||
content->setData( std::make_shared<std::stringstream>( utility::conversions::to_utf8string(json_array.serialize()) ) );
|
||||
return content;
|
||||
}
|
||||
template <typename T>
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const std::map<utility::string_t, T>& value, const utility::string_t& contentType )
|
||||
{
|
||||
web::json::value jobj = ModelBase::toJson(value);
|
||||
std::shared_ptr<HttpContent> content = std::make_shared<HttpContent>();
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::make_shared<std::stringstream>( utility::conversions::to_utf8string(jobj.serialize()) ) );
|
||||
return content;
|
||||
}
|
||||
template <typename T>
|
||||
bool ModelBase::fromHttpContent( std::shared_ptr<HttpContent> val, std::shared_ptr<T>& outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if(val == nullptr) return false;
|
||||
if( outVal == nullptr )
|
||||
{
|
||||
outVal = std::make_shared<T>();
|
||||
}
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
template <typename T>
|
||||
bool ModelBase::fromHttpContent( std::shared_ptr<HttpContent> val, std::vector<T> & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if (val == nullptr) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
template <typename T>
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, std::set<T>& outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if (val == nullptr) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
template <typename T>
|
||||
bool ModelBase::fromHttpContent( std::shared_ptr<HttpContent> val, std::map<utility::string_t, T> & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if (val == nullptr) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_ModelBase_H_ */
|
||||
|
|
@ -0,0 +1,653 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
ModelBase::ModelBase(): m_IsSet(false)
|
||||
{
|
||||
}
|
||||
ModelBase::~ModelBase()
|
||||
{
|
||||
}
|
||||
bool ModelBase::isSet() const
|
||||
{
|
||||
return m_IsSet;
|
||||
}
|
||||
utility::string_t ModelBase::toString( const bool val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString( const float val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString( const double val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString( const int32_t val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString( const int64_t val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString (const utility::string_t &val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
ss << val;
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
utility::string_t ModelBase::toString( const utility::datetime &val )
|
||||
{
|
||||
return val.to_string(utility::datetime::ISO_8601);
|
||||
}
|
||||
utility::string_t ModelBase::toString( const web::json::value &val )
|
||||
{
|
||||
return val.serialize();
|
||||
}
|
||||
utility::string_t ModelBase::toString( const std::shared_ptr<HttpContent>& val )
|
||||
{
|
||||
utility::stringstream_t ss;
|
||||
if( val != nullptr )
|
||||
{
|
||||
ss << val->getData();
|
||||
}
|
||||
return utility::string_t(ss.str());
|
||||
}
|
||||
web::json::value ModelBase::toJson(bool value)
|
||||
{
|
||||
return web::json::value::boolean(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( float value )
|
||||
{
|
||||
return web::json::value::number(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( double value )
|
||||
{
|
||||
return web::json::value::number(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( int32_t value )
|
||||
{
|
||||
return web::json::value::number(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( int64_t value )
|
||||
{
|
||||
return web::json::value::number(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( const utility::string_t& value )
|
||||
{
|
||||
return web::json::value::string(value);
|
||||
}
|
||||
web::json::value ModelBase::toJson( const utility::datetime& value )
|
||||
{
|
||||
return web::json::value::string(value.to_string(utility::datetime::ISO_8601));
|
||||
}
|
||||
web::json::value ModelBase::toJson( const web::json::value& value )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
web::json::value ModelBase::toJson( const std::shared_ptr<HttpContent>& content )
|
||||
{
|
||||
web::json::value value;
|
||||
if(content != nullptr)
|
||||
{
|
||||
value[utility::conversions::to_string_t("ContentDisposition")] = ModelBase::toJson(content->getContentDisposition());
|
||||
value[utility::conversions::to_string_t("ContentType")] = ModelBase::toJson(content->getContentType());
|
||||
value[utility::conversions::to_string_t("FileName")] = ModelBase::toJson(content->getFileName());
|
||||
value[utility::conversions::to_string_t("InputStream")] = web::json::value::string( ModelBase::toBase64(content->getData()) );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
web::json::value ModelBase::toJson( const std::shared_ptr<utility::datetime>& val )
|
||||
{
|
||||
web::json::value retVal;
|
||||
if(val != nullptr)
|
||||
{
|
||||
retVal = toJson(*val);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, bool &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, float &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
int64_t intVal = 0;
|
||||
success = ModelBase::fromString(val, intVal);
|
||||
if(success)
|
||||
{
|
||||
outVal = static_cast<float>(intVal);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, double &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
int64_t intVal = 0;
|
||||
success = ModelBase::fromString(val, intVal);
|
||||
if(success)
|
||||
{
|
||||
outVal = static_cast<double>(intVal);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, int32_t &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, int64_t &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, utility::string_t &outVal )
|
||||
{
|
||||
utility::stringstream_t ss(val);
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
ss >> outVal;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, utility::datetime &outVal )
|
||||
{
|
||||
bool success = true;
|
||||
auto dt = utility::datetime::from_string(val, utility::datetime::ISO_8601);
|
||||
if( dt.is_initialized() )
|
||||
{
|
||||
outVal = dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, web::json::value &outVal )
|
||||
{
|
||||
outVal = web::json::value::parse(val);
|
||||
return !outVal.is_null();
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, std::shared_ptr<HttpContent>& outVal )
|
||||
{
|
||||
bool ok = true;
|
||||
if(outVal == nullptr)
|
||||
{
|
||||
outVal = std::shared_ptr<HttpContent>(new HttpContent());
|
||||
}
|
||||
if(outVal != nullptr)
|
||||
{
|
||||
outVal->setData(std::shared_ptr<std::istream>(new std::stringstream(utility::conversions::to_utf8string(val))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool ModelBase::fromString( const utility::string_t& val, std::shared_ptr<utility::datetime>& outVal )
|
||||
{
|
||||
bool ok = false;
|
||||
if(outVal == nullptr)
|
||||
{
|
||||
outVal = std::shared_ptr<utility::datetime>(new utility::datetime());
|
||||
}
|
||||
if( outVal != nullptr )
|
||||
{
|
||||
ok = fromJson(web::json::value::parse(val), *outVal);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, bool & outVal )
|
||||
{
|
||||
outVal = !val.is_boolean() ? false : val.as_bool();
|
||||
return val.is_boolean();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, float & outVal )
|
||||
{
|
||||
outVal = (!val.is_double() && !val.is_integer()) ? std::numeric_limits<float>::quiet_NaN(): static_cast<float>(val.as_double());
|
||||
return val.is_double() || val.is_integer();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, double & outVal )
|
||||
{
|
||||
outVal = (!val.is_double() && !val.is_integer()) ? std::numeric_limits<double>::quiet_NaN(): val.as_double();
|
||||
return val.is_double() || val.is_integer();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, int32_t & outVal )
|
||||
{
|
||||
outVal = !val.is_integer() ? std::numeric_limits<int32_t>::quiet_NaN() : val.as_integer();
|
||||
return val.is_integer();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, int64_t & outVal )
|
||||
{
|
||||
outVal = !val.is_number() ? std::numeric_limits<int64_t>::quiet_NaN() : val.as_number().to_int64();
|
||||
return val.is_number();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, utility::string_t & outVal )
|
||||
{
|
||||
outVal = val.is_string() ? val.as_string() : utility::conversions::to_string_t("");
|
||||
return val.is_string();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, utility::datetime & outVal )
|
||||
{
|
||||
outVal = val.is_null() ? utility::datetime::from_string(utility::conversions::to_string_t("NULL"), utility::datetime::ISO_8601) : utility::datetime::from_string(val.as_string(), utility::datetime::ISO_8601);
|
||||
return outVal.is_initialized();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, web::json::value & outVal )
|
||||
{
|
||||
outVal = val;
|
||||
return !val.is_null();
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, std::shared_ptr<HttpContent>& content )
|
||||
{
|
||||
bool result = false;
|
||||
if( content != nullptr)
|
||||
{
|
||||
result = true;
|
||||
if(content == nullptr)
|
||||
{
|
||||
content = std::shared_ptr<HttpContent>(new HttpContent());
|
||||
}
|
||||
if(val.has_field(utility::conversions::to_string_t("ContentDisposition")))
|
||||
{
|
||||
utility::string_t value;
|
||||
result = result && ModelBase::fromJson(val.at(utility::conversions::to_string_t("ContentDisposition")), value);
|
||||
content->setContentDisposition( value );
|
||||
}
|
||||
if(val.has_field(utility::conversions::to_string_t("ContentType")))
|
||||
{
|
||||
utility::string_t value;
|
||||
result = result && ModelBase::fromJson(val.at(utility::conversions::to_string_t("ContentType")), value);
|
||||
content->setContentType( value );
|
||||
}
|
||||
if(val.has_field(utility::conversions::to_string_t("FileName")))
|
||||
{
|
||||
utility::string_t value;
|
||||
result = result && ModelBase::fromJson(val.at(utility::conversions::to_string_t("FileName")), value);
|
||||
content->setFileName( value );
|
||||
}
|
||||
if(val.has_field(utility::conversions::to_string_t("InputStream")))
|
||||
{
|
||||
utility::string_t value;
|
||||
result = result && ModelBase::fromJson(val.at(utility::conversions::to_string_t("InputStream")), value);
|
||||
content->setData( ModelBase::fromBase64( value ) );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool ModelBase::fromJson( const web::json::value& val, std::shared_ptr<utility::datetime> &outVal )
|
||||
{
|
||||
bool ok = false;
|
||||
if(outVal == nullptr)
|
||||
{
|
||||
outVal = std::shared_ptr<utility::datetime>(new utility::datetime());
|
||||
}
|
||||
if( outVal != nullptr )
|
||||
{
|
||||
ok = fromJson(val, *outVal);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, bool value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
std::stringstream* valueAsStringStream = new std::stringstream();
|
||||
(*valueAsStringStream) << value;
|
||||
content->setData( std::shared_ptr<std::istream>( valueAsStringStream ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, float value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
std::stringstream* valueAsStringStream = new std::stringstream();
|
||||
(*valueAsStringStream) << value;
|
||||
content->setData( std::shared_ptr<std::istream>( valueAsStringStream ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, double value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
std::stringstream* valueAsStringStream = new std::stringstream();
|
||||
(*valueAsStringStream) << value;
|
||||
content->setData( std::shared_ptr<std::istream>( valueAsStringStream ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, int32_t value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
std::stringstream* valueAsStringStream = new std::stringstream();
|
||||
(*valueAsStringStream) << value;
|
||||
content->setData( std::shared_ptr<std::istream>( valueAsStringStream ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, int64_t value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
std::stringstream* valueAsStringStream = new std::stringstream();
|
||||
(*valueAsStringStream) << value;
|
||||
content->setData( std::shared_ptr<std::istream>( valueAsStringStream) ) ;
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const utility::string_t& value, const utility::string_t& contentType)
|
||||
{
|
||||
std::shared_ptr<HttpContent> content(new HttpContent);
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::shared_ptr<std::istream>( new std::stringstream( utility::conversions::to_utf8string(value) ) ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const utility::datetime& value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::shared_ptr<std::istream>( new std::stringstream( utility::conversions::to_utf8string(value.to_string(utility::datetime::ISO_8601) ) ) ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const web::json::value& value, const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::shared_ptr<std::istream>( new std::stringstream( utility::conversions::to_utf8string(value.serialize()) ) ) );
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent( const utility::string_t& name, const std::shared_ptr<HttpContent>& value )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
if( value != nullptr )
|
||||
{
|
||||
content->setName( name );
|
||||
content->setContentDisposition( value->getContentDisposition() );
|
||||
content->setContentType( value->getContentType() );
|
||||
content->setData( value->getData() );
|
||||
content->setFileName( value->getFileName() );
|
||||
}
|
||||
return content;
|
||||
}
|
||||
std::shared_ptr<HttpContent> ModelBase::toHttpContent(const utility::string_t& name, const std::shared_ptr<utility::datetime>& value , const utility::string_t& contentType )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content( new HttpContent );
|
||||
if (value != nullptr )
|
||||
{
|
||||
content->setName( name );
|
||||
content->setContentDisposition( utility::conversions::to_string_t("form-data") );
|
||||
content->setContentType( contentType );
|
||||
content->setData( std::shared_ptr<std::istream>( new std::stringstream( utility::conversions::to_utf8string( toJson(*value).serialize() ) ) ) );
|
||||
}
|
||||
return content;
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, bool & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, float & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, double & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, int32_t & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, int64_t & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, utility::string_t & outVal )
|
||||
{
|
||||
if( val == nullptr ) return false;
|
||||
std::shared_ptr<std::istream> data = val->getData();
|
||||
data->seekg( 0, data->beg );
|
||||
|
||||
std::string str((std::istreambuf_iterator<char>(*data.get())),
|
||||
std::istreambuf_iterator<char>());
|
||||
outVal = utility::conversions::to_string_t(str);
|
||||
return true;
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, utility::datetime & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
outVal = utility::datetime::from_string(str, utility::datetime::ISO_8601);
|
||||
return true;
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, web::json::value & outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
bool ModelBase::fromHttpContent(std::shared_ptr<HttpContent> val, std::shared_ptr<HttpContent>& outVal )
|
||||
{
|
||||
utility::string_t str;
|
||||
if( val == nullptr ) return false;
|
||||
if( outVal == nullptr )
|
||||
{
|
||||
outVal = std::shared_ptr<HttpContent>(new HttpContent());
|
||||
}
|
||||
ModelBase::fromHttpContent(val, str);
|
||||
return fromString(str, outVal);
|
||||
}
|
||||
// base64 encoding/decoding based on : https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#C.2B.2B
|
||||
const static char Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const static char Base64PadChar = '=';
|
||||
utility::string_t ModelBase::toBase64( utility::string_t value )
|
||||
{
|
||||
std::shared_ptr<std::istream> source( new std::stringstream( utility::conversions::to_utf8string(value) ) );
|
||||
return ModelBase::toBase64(source);
|
||||
}
|
||||
utility::string_t ModelBase::toBase64( std::shared_ptr<std::istream> value )
|
||||
{
|
||||
value->seekg( 0, value->end );
|
||||
size_t length = value->tellg();
|
||||
value->seekg( 0, value->beg );
|
||||
utility::string_t base64;
|
||||
base64.reserve( ((length / 3) + (length % 3 > 0)) * 4 );
|
||||
char read[3] = { 0 };
|
||||
uint32_t temp;
|
||||
for ( size_t idx = 0; idx < length / 3; idx++ )
|
||||
{
|
||||
value->read( read, 3 );
|
||||
temp = (read[0]) << 16;
|
||||
temp += (read[1]) << 8;
|
||||
temp += (read[2]);
|
||||
base64.append( 1, Base64Chars[(temp & 0x00FC0000) >> 18] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x0003F000) >> 12] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x00000FC0) >> 6] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x0000003F)] );
|
||||
}
|
||||
switch ( length % 3 )
|
||||
{
|
||||
case 1:
|
||||
value->read( read, 1 );
|
||||
temp = read[0] << 16;
|
||||
base64.append( 1, Base64Chars[(temp & 0x00FC0000) >> 18] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x0003F000) >> 12] );
|
||||
base64.append( 2, Base64PadChar );
|
||||
break;
|
||||
case 2:
|
||||
value->read( read, 2 );
|
||||
temp = read[0] << 16;
|
||||
temp += read[1] << 8;
|
||||
base64.append( 1, Base64Chars[(temp & 0x00FC0000) >> 18] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x0003F000) >> 12] );
|
||||
base64.append( 1, Base64Chars[(temp & 0x00000FC0) >> 6] );
|
||||
base64.append( 1, Base64PadChar );
|
||||
break;
|
||||
}
|
||||
return base64;
|
||||
}
|
||||
std::shared_ptr<std::istream> ModelBase::fromBase64( const utility::string_t& encoded )
|
||||
{
|
||||
std::shared_ptr<std::stringstream> result(new std::stringstream);
|
||||
|
||||
char outBuf[3] = { 0 };
|
||||
uint32_t temp = 0;
|
||||
|
||||
utility::string_t::const_iterator cursor = encoded.begin();
|
||||
while ( cursor < encoded.end() )
|
||||
{
|
||||
for ( size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++ )
|
||||
{
|
||||
temp <<= 6;
|
||||
if ( *cursor >= 0x41 && *cursor <= 0x5A )
|
||||
{
|
||||
temp |= *cursor - 0x41;
|
||||
}
|
||||
else if ( *cursor >= 0x61 && *cursor <= 0x7A )
|
||||
{
|
||||
temp |= *cursor - 0x47;
|
||||
}
|
||||
else if ( *cursor >= 0x30 && *cursor <= 0x39 )
|
||||
{
|
||||
temp |= *cursor + 0x04;
|
||||
}
|
||||
else if ( *cursor == 0x2B )
|
||||
{
|
||||
temp |= 0x3E; //change to 0x2D for URL alphabet
|
||||
}
|
||||
else if ( *cursor == 0x2F )
|
||||
{
|
||||
temp |= 0x3F; //change to 0x5F for URL alphabet
|
||||
}
|
||||
else if ( *cursor == Base64PadChar ) //pad
|
||||
{
|
||||
switch ( encoded.end() - cursor )
|
||||
{
|
||||
case 1: //One pad character
|
||||
outBuf[0] = (temp >> 16) & 0x000000FF;
|
||||
outBuf[1] = (temp >> 8) & 0x000000FF;
|
||||
result->write( outBuf, 2 );
|
||||
return result;
|
||||
case 2: //Two pad characters
|
||||
outBuf[0] = (temp >> 10) & 0x000000FF;
|
||||
result->write( outBuf, 1 );
|
||||
return result;
|
||||
default:
|
||||
throw web::json::json_exception( utility::conversions::to_string_t( "Invalid Padding in Base 64!" ).c_str() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw web::json::json_exception( utility::conversions::to_string_t( "Non-Valid Character in Base 64!" ).c_str() );
|
||||
}
|
||||
++cursor;
|
||||
}
|
||||
|
||||
outBuf[0] = (temp >> 16) & 0x000000FF;
|
||||
outBuf[1] = (temp >> 8) & 0x000000FF;
|
||||
outBuf[2] = (temp) & 0x000000FF;
|
||||
result->write( outBuf, 3 );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* MultipartFormData.h
|
||||
*
|
||||
* This class represents a container for building application/x-multipart-formdata requests.
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_MultipartFormData_H_
|
||||
#define {{modelHeaderGuardPrefix}}_MultipartFormData_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/IHttpBody.h"
|
||||
#include "{{packageName}}/HttpContent.h"
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} MultipartFormData
|
||||
: public IHttpBody
|
||||
{
|
||||
public:
|
||||
MultipartFormData();
|
||||
MultipartFormData(const utility::string_t& boundary);
|
||||
virtual ~MultipartFormData();
|
||||
|
||||
virtual void add( std::shared_ptr<HttpContent> content );
|
||||
virtual utility::string_t getBoundary();
|
||||
virtual std::shared_ptr<HttpContent> getContent(const utility::string_t& name) const;
|
||||
virtual bool hasContent(const utility::string_t& name) const;
|
||||
virtual void writeTo( std::ostream& target );
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<HttpContent>> m_Contents;
|
||||
utility::string_t m_Boundary;
|
||||
std::map<utility::string_t, std::shared_ptr<HttpContent>> m_ContentLookup;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_MultipartFormData_H_ */
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/MultipartFormData.h"
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
MultipartFormData::MultipartFormData()
|
||||
{
|
||||
utility::stringstream_t uuidString;
|
||||
uuidString << boost::uuids::random_generator()();
|
||||
m_Boundary = uuidString.str();
|
||||
}
|
||||
|
||||
MultipartFormData::MultipartFormData(const utility::string_t& boundary)
|
||||
: m_Boundary(boundary)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MultipartFormData::~MultipartFormData()
|
||||
{
|
||||
}
|
||||
|
||||
utility::string_t MultipartFormData::getBoundary()
|
||||
{
|
||||
return m_Boundary;
|
||||
}
|
||||
|
||||
void MultipartFormData::add( std::shared_ptr<HttpContent> content )
|
||||
{
|
||||
m_Contents.push_back( content );
|
||||
m_ContentLookup[content->getName()] = content;
|
||||
}
|
||||
|
||||
bool MultipartFormData::hasContent(const utility::string_t& name) const
|
||||
{
|
||||
return m_ContentLookup.find(name) != m_ContentLookup.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpContent> MultipartFormData::getContent(const utility::string_t& name) const
|
||||
{
|
||||
auto result = m_ContentLookup.find(name);
|
||||
if(result == m_ContentLookup.end())
|
||||
{
|
||||
return std::shared_ptr<HttpContent>(nullptr);
|
||||
}
|
||||
return result->second;
|
||||
}
|
||||
|
||||
void MultipartFormData::writeTo( std::ostream& target )
|
||||
{
|
||||
for ( size_t i = 0; i < m_Contents.size(); i++ )
|
||||
{
|
||||
std::shared_ptr<HttpContent> content = m_Contents[i];
|
||||
|
||||
// boundary
|
||||
target << "\r\n" << "--" << utility::conversions::to_utf8string( m_Boundary ) << "\r\n";
|
||||
|
||||
// headers
|
||||
target << "Content-Disposition: " << utility::conversions::to_utf8string( content->getContentDisposition() );
|
||||
if ( content->getName().size() > 0 )
|
||||
{
|
||||
target << "; name=\"" << utility::conversions::to_utf8string( content->getName() ) << "\"";
|
||||
}
|
||||
if ( content->getFileName().size() > 0 )
|
||||
{
|
||||
target << "; filename=\"" << utility::conversions::to_utf8string( content->getFileName() ) << "\"";
|
||||
}
|
||||
target << "\r\n";
|
||||
|
||||
if ( content->getContentType().size() > 0 )
|
||||
{
|
||||
target << "Content-Type: " << utility::conversions::to_utf8string( content->getContentType() ) << "\r\n";
|
||||
}
|
||||
|
||||
target << "\r\n";
|
||||
|
||||
// body
|
||||
std::shared_ptr<std::istream> data = content->getData();
|
||||
|
||||
data->seekg( 0, data->end );
|
||||
std::vector<char> dataBytes( data->tellg() );
|
||||
|
||||
data->seekg( 0, data->beg );
|
||||
data->read( &dataBytes[0], dataBytes.size() );
|
||||
|
||||
std::copy( dataBytes.begin(), dataBytes.end(), std::ostreambuf_iterator<char>( target ) );
|
||||
}
|
||||
|
||||
target << "\r\n--" << utility::conversions::to_utf8string( m_Boundary ) << "--\r\n";
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
{{>licenseInfo}}
|
||||
/*
|
||||
* Object.h
|
||||
*
|
||||
* This is the implementation of a JSON object.
|
||||
*/
|
||||
|
||||
#ifndef {{modelHeaderGuardPrefix}}_Object_H_
|
||||
#define {{modelHeaderGuardPrefix}}_Object_H_
|
||||
|
||||
{{{defaultInclude}}}
|
||||
#include "{{packageName}}/ModelBase.h"
|
||||
|
||||
#include <cpprest/details/basic_types.h>
|
||||
#include <cpprest/json.h>
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
class {{declspec}} Object : public ModelBase
|
||||
{
|
||||
public:
|
||||
Object();
|
||||
virtual ~Object();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// ModelBase overrides
|
||||
void validate() override;
|
||||
|
||||
web::json::value toJson() const override;
|
||||
bool fromJson(const web::json::value& json) override;
|
||||
|
||||
void toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) const override;
|
||||
bool fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& namePrefix) override;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// Object manipulation
|
||||
web::json::value getValue(const utility::string_t& key) const;
|
||||
void setValue(const utility::string_t& key, const web::json::value& value);
|
||||
|
||||
private:
|
||||
web::json::value m_object;
|
||||
};
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
#endif /* {{modelHeaderGuardPrefix}}_Object_H_ */
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
{{>licenseInfo}}
|
||||
#include "{{packageName}}/Object.h"
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
||||
Object::Object()
|
||||
{
|
||||
m_object = web::json::value::object();
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
{
|
||||
}
|
||||
|
||||
void Object::validate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
web::json::value Object::toJson() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
bool Object::fromJson(const web::json::value& val)
|
||||
{
|
||||
if (val.is_object())
|
||||
{
|
||||
m_object = val;
|
||||
m_IsSet = true;
|
||||
}
|
||||
return isSet();
|
||||
}
|
||||
|
||||
void Object::toMultipart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix) const
|
||||
{
|
||||
utility::string_t namePrefix = prefix;
|
||||
if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t("."))
|
||||
{
|
||||
namePrefix += utility::conversions::to_string_t(".");
|
||||
}
|
||||
multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("object"), m_object));
|
||||
}
|
||||
|
||||
bool Object::fromMultiPart(std::shared_ptr<MultipartFormData> multipart, const utility::string_t& prefix)
|
||||
{
|
||||
utility::string_t namePrefix = prefix;
|
||||
if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t("."))
|
||||
{
|
||||
namePrefix += utility::conversions::to_string_t(".");
|
||||
}
|
||||
|
||||
if( ModelBase::fromHttpContent(multipart->getContent(namePrefix + utility::conversions::to_string_t("object")), m_object ) )
|
||||
{
|
||||
m_IsSet = true;
|
||||
}
|
||||
return isSet();
|
||||
}
|
||||
|
||||
web::json::value Object::getValue(const utility::string_t& key) const
|
||||
{
|
||||
return m_object.at(key);
|
||||
}
|
||||
|
||||
|
||||
void Object::setValue(const utility::string_t& key, const web::json::value& value)
|
||||
{
|
||||
if( !value.is_null() )
|
||||
{
|
||||
m_object[key] = value;
|
||||
m_IsSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
{{#modelNamespaceDeclarations}}
|
||||
}
|
||||
{{/modelNamespaceDeclarations}}
|
||||
|
|
@ -639,20 +639,13 @@ components:
|
|||
required:
|
||||
- id
|
||||
- name
|
||||
Tag:
|
||||
description: 'A localized tag: keys are language codes (ISO 639-1), values are tag names'
|
||||
type: object
|
||||
example:
|
||||
en: Shojo
|
||||
ru: Сёдзё
|
||||
ja: 少女
|
||||
additionalProperties:
|
||||
type: string
|
||||
Tags:
|
||||
description: Array of localized tags
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
- en: Shojo
|
||||
ru: Сёдзё
|
||||
|
|
|
|||
2
modules/bot/.gitignore
vendored
Normal file
2
modules/bot/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
generated-client/
|
||||
out/
|
||||
40
modules/bot/CMakeLists.txt
Normal file
40
modules/bot/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
cmake_minimum_required(VERSION 3.10.2)
|
||||
project(AnimeBot)
|
||||
|
||||
set(SOURCES "")
|
||||
file(GLOB_RECURSE SRC_FRONT "front/src/*.cpp")
|
||||
list(APPEND SOURCES ${SRC_FRONT})
|
||||
|
||||
file(GLOB_RECURSE SRC_BACK "back/src/*.cpp")
|
||||
list(APPEND SOURCES ${SRC_BACK})
|
||||
|
||||
file(GLOB_RECURSE SRC_API "generated-client/src/*.cpp")
|
||||
list(APPEND SOURCES ${SRC_API})
|
||||
|
||||
file(GLOB_RECURSE SRC_AUTH "generated-client-auth/src/*.cpp")
|
||||
list(APPEND SOURCES ${SRC_AUTH})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(Boost COMPONENTS system REQUIRED)
|
||||
find_package(CURL)
|
||||
find_library(CPPREST_LIB cpprest REQUIRED)
|
||||
include_directories(/usr/local/include ${OPENSSL_INCLUDE_DIR} ${Boost_INCLUDE_DIR})
|
||||
include_directories(front/include/)
|
||||
include_directories(back/include)
|
||||
include_directories(generated-client/include)
|
||||
include_directories(generated-client-auth/include)
|
||||
if (CURL_FOUND)
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
add_definitions(-DHAVE_CURL)
|
||||
endif()
|
||||
|
||||
add_executable(AnimeBot ${SOURCES})
|
||||
|
||||
target_link_libraries(AnimeBot /usr/local/lib/libTgBot.a ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ${CURL_LIBRARIES} ${CPPREST_LIB})
|
||||
1
modules/bot/README.md
Normal file
1
modules/bot/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
### Здесь будет часть, отвечающая за телеграм ботика
|
||||
35
modules/bot/back/include/AuthImpersonation.hpp
Normal file
35
modules/bot/back/include/AuthImpersonation.hpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// AuthImpersonationClient.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <cpprest/asyncrt_utils.h>
|
||||
#include "AuthClient/ApiClient.h"
|
||||
#include "AuthClient/ApiConfiguration.h"
|
||||
#include "AuthClient/api/AuthApi.h"
|
||||
#include "AuthClient/model/GetImpersonationToken_request.h"
|
||||
#include "AuthClient/model/GetImpersonationToken_200_response.h"
|
||||
|
||||
|
||||
namespace nyanimed {
|
||||
|
||||
class AuthImpersonationClient {
|
||||
public:
|
||||
AuthImpersonationClient();
|
||||
|
||||
// Потокобезопасный вызов — не модифицирует состояние
|
||||
pplx::task<std::shared_ptr<nyanimed::meow::auth::model::GetImpersonationToken_200_response>>
|
||||
getImpersonationToken(int64_t userId) const;
|
||||
|
||||
private:
|
||||
std::string m_baseUrl;
|
||||
std::string m_authToken;
|
||||
std::shared_ptr<nyanimed::meow::auth::api::ApiClient> m_apiClient;
|
||||
std::shared_ptr<nyanimed::meow::auth::api::AuthApi> m_authApi;
|
||||
};
|
||||
|
||||
} // namespace nyanimed
|
||||
39
modules/bot/back/include/BotToServer.hpp
Normal file
39
modules/bot/back/include/BotToServer.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include "CppRestOpenAPIClient/ApiClient.h"
|
||||
#include "CppRestOpenAPIClient/ApiConfiguration.h"
|
||||
#include "CppRestOpenAPIClient/api/DefaultApi.h"
|
||||
#include "CppRestOpenAPIClient/model/User.h"
|
||||
#include "CppRestOpenAPIClient/model/GetUserTitles_200_response.h"
|
||||
#include "CppRestOpenAPIClient/model/UserTitle.h"
|
||||
#include "CppRestOpenAPIClient/model/Title.h"
|
||||
#include "constants.hpp"
|
||||
#include "structs.hpp"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <cpprest/asyncrt_utils.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "AuthImpersonation.hpp"
|
||||
|
||||
using namespace org::openapitools::client::api;
|
||||
|
||||
class BotToServer {
|
||||
public:
|
||||
BotToServer();
|
||||
|
||||
// Асинхронный метод: получить список тайтлов пользователя
|
||||
pplx::task<std::vector<BotStructs::Title>> fetchUserTitlesAsync(const std::string& userId);
|
||||
pplx::task<BotStructs::Title> fetchTitleAsync(const std::string& userId, int64_t titleId);
|
||||
|
||||
private:
|
||||
std::shared_ptr<org::openapitools::client::api::ApiConfiguration> apiconfiguration;
|
||||
std::shared_ptr<org::openapitools::client::api::ApiClient> apiclient;
|
||||
std::shared_ptr<org::openapitools::client::api::DefaultApi> api;
|
||||
|
||||
nyanimed::AuthImpersonationClient authClient;
|
||||
|
||||
static BotStructs::Title mapTitleToBotTitle(
|
||||
const std::shared_ptr<org::openapitools::client::model::Title>& titleModel);
|
||||
};
|
||||
34
modules/bot/back/src/AuthImpersonation.cpp
Normal file
34
modules/bot/back/src/AuthImpersonation.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include "AuthImpersonation.hpp"
|
||||
|
||||
nyanimed::AuthImpersonationClient::AuthImpersonationClient() {
|
||||
const char* baseUrlEnv = std::getenv("NYANIMEDBAUTHURL");
|
||||
const char* tokenEnv = std::getenv("NYANIMEDBAUTHTOKEN");
|
||||
|
||||
if (!baseUrlEnv || std::string(baseUrlEnv).empty()) {
|
||||
throw std::runtime_error("Missing required environment variable: NYANIMEDBAUTHURL");
|
||||
}
|
||||
if (!tokenEnv || std::string(tokenEnv).empty()) {
|
||||
throw std::runtime_error("Missing required environment variable: NYANIMEDBAUTHTOKEN");
|
||||
}
|
||||
|
||||
m_baseUrl = baseUrlEnv;
|
||||
m_authToken = tokenEnv;
|
||||
|
||||
auto config = std::make_shared<nyanimed::meow::auth::api::ApiConfiguration>();
|
||||
config->setBaseUrl(utility::conversions::to_string_t(m_baseUrl));
|
||||
|
||||
m_apiClient = std::make_shared<nyanimed::meow::auth::api::ApiClient>(config);
|
||||
m_authApi = std::make_shared<nyanimed::meow::auth::api::AuthApi>(m_apiClient);
|
||||
}
|
||||
|
||||
pplx::task<std::shared_ptr<nyanimed::meow::auth::model::GetImpersonationToken_200_response>>
|
||||
nyanimed::AuthImpersonationClient::getImpersonationToken(int64_t userId) const {
|
||||
auto request = std::make_shared<nyanimed::meow::auth::model::GetImpersonationToken_request>();
|
||||
request->setUserId(userId);
|
||||
//request->setExternalId(externalId);
|
||||
|
||||
std::map<utility::string_t, utility::string_t> headers;
|
||||
headers[U("Authorization")] = U("Bearer ") + utility::conversions::to_string_t(m_authToken);
|
||||
|
||||
return m_authApi->getImpersonationToken(request, headers);
|
||||
}
|
||||
216
modules/bot/back/src/BotToServer.cpp
Normal file
216
modules/bot/back/src/BotToServer.cpp
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#include "BotToServer.hpp"
|
||||
|
||||
BotToServer::BotToServer() {
|
||||
apiconfiguration = std::make_shared<ApiConfiguration>();
|
||||
const char* envUrl = getenv("NYANIMEDBBASEURL");
|
||||
if (!envUrl) {
|
||||
std::runtime_error("Environment variable NYANIMEDBBASEURL is not set");
|
||||
}
|
||||
apiconfiguration->setBaseUrl(utility::conversions::to_string_t(envUrl));
|
||||
apiconfiguration->setUserAgent(utility::conversions::to_string_t("OpenAPI Client"));
|
||||
apiclient = std::make_shared<ApiClient>(apiconfiguration);
|
||||
api = std::make_shared<DefaultApi>(apiclient);
|
||||
}
|
||||
|
||||
// Вспомогательная функция: преобразует UserTitle → BotStructs::Title
|
||||
static BotStructs::Title mapUserTitleToBotTitle(
|
||||
const std::shared_ptr<org::openapitools::client::model::UserTitle>& userTitle
|
||||
) {
|
||||
if (!userTitle || !userTitle->titleIsSet()) {
|
||||
return BotStructs::Title{0, "Invalid", "", -1};
|
||||
}
|
||||
|
||||
auto apiTitle = userTitle->getTitle();
|
||||
if (!apiTitle) {
|
||||
return BotStructs::Title{0, "No Title", "", -1};
|
||||
}
|
||||
|
||||
int64_t id = apiTitle->getId();
|
||||
|
||||
std::string name = "Untitled";
|
||||
auto titleNames = apiTitle->getTitleNames();
|
||||
utility::string_t ru = U("ru");
|
||||
|
||||
if (titleNames.find(ru) != titleNames.end() && !titleNames.at(ru).empty()) {
|
||||
name = utility::conversions::to_utf8string(titleNames.at(ru).front());
|
||||
} else if (!titleNames.empty()) {
|
||||
const auto& firstLang = *titleNames.begin();
|
||||
if (!firstLang.second.empty()) {
|
||||
name = utility::conversions::to_utf8string(firstLang.second.front());
|
||||
}
|
||||
}
|
||||
|
||||
std::string description = ""; // описание пока не поддерживается в OpenAPI-модели
|
||||
return BotStructs::Title{id, name, description, -1};
|
||||
}
|
||||
|
||||
pplx::task<std::vector<BotStructs::Title>> BotToServer::fetchUserTitlesAsync(const std::string& userId) {
|
||||
// Шаг 1: Получаем impersonation-токен
|
||||
auto impersonationTask = authClient.getImpersonationToken(std::stoi(userId));
|
||||
|
||||
// Шаг 2: После получения токена — делаем запрос getUserTitles с этим токеном
|
||||
return impersonationTask.then([=](pplx::task<std::shared_ptr<nyanimed::meow::auth::model::GetImpersonationToken_200_response>> tokenTask) {
|
||||
try {
|
||||
auto tokenResponse = tokenTask.get();
|
||||
if (!tokenResponse) {
|
||||
throw std::runtime_error("Null response from getImpersonationToken");
|
||||
}
|
||||
|
||||
utility::string_t accessToken = utility::conversions::to_string_t(tokenResponse->getAccessToken());
|
||||
|
||||
// Формируем заголовки с токеном
|
||||
std::map<utility::string_t, utility::string_t> customHeaders;
|
||||
customHeaders[U("Cookie")] = U("access_token=") + accessToken;
|
||||
|
||||
// Подготавливаем параметры запроса
|
||||
utility::string_t userIdW = utility::conversions::to_string_t(userId);
|
||||
int32_t limit = static_cast<int32_t>(BotConstants::DISP_TITLES_NUM);
|
||||
|
||||
// Шаг 3: Выполняем getUserTitles с кастомными заголовками
|
||||
return api->getUserTitles(
|
||||
userIdW,
|
||||
boost::none, // cursor
|
||||
boost::none, // sort
|
||||
boost::none, // sortForward
|
||||
boost::none, // word
|
||||
boost::none, // status
|
||||
boost::none, // watchStatus
|
||||
boost::none, // rating
|
||||
boost::none, // myRate
|
||||
boost::none, // releaseYear
|
||||
boost::none, // releaseSeason
|
||||
limit,
|
||||
boost::none, // fields
|
||||
customHeaders
|
||||
);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error obtaining impersonation token: " << e.what() << std::endl;
|
||||
throw; // Пробрасываем, чтобы цепочка task.then завершилась с ошибкой
|
||||
}
|
||||
}).then([=](pplx::task<std::shared_ptr<org::openapitools::client::model::GetUserTitles_200_response>> responseTask) {
|
||||
try {
|
||||
auto response = responseTask.get();
|
||||
if (!response) {
|
||||
throw std::runtime_error("Null response from getUserTitles");
|
||||
}
|
||||
|
||||
const auto& userTitles = response->getData();
|
||||
std::vector<BotStructs::Title> result;
|
||||
result.reserve(userTitles.size());
|
||||
|
||||
for (size_t i = 0; i < userTitles.size(); ++i) {
|
||||
BotStructs::Title botTitle = mapUserTitleToBotTitle(userTitles[i]);
|
||||
botTitle.num = static_cast<int64_t>(i); // 0-based индекс
|
||||
result.push_back(botTitle);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (const web::http::http_exception& e) {
|
||||
std::cerr << "HTTP error in fetchUserTitlesAsync: " << e.what() << std::endl;
|
||||
throw;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error in fetchUserTitlesAsync: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pplx::task<BotStructs::Title> BotToServer::fetchTitleAsync(const std::string& userId, int64_t titleId) {
|
||||
auto impersonationTask = authClient.getImpersonationToken(std::stoi(userId));
|
||||
|
||||
// Шаг 2: После получения токена — делаем запрос getTitle с этим токеном
|
||||
return impersonationTask.then([=](pplx::task<std::shared_ptr<nyanimed::meow::auth::model::GetImpersonationToken_200_response>> tokenTask) {
|
||||
try {
|
||||
auto tokenResponse = tokenTask.get();
|
||||
if (!tokenResponse) {
|
||||
throw std::runtime_error("Null response from getImpersonationToken");
|
||||
}
|
||||
|
||||
utility::string_t accessToken = utility::conversions::to_string_t(tokenResponse->getAccessToken());
|
||||
|
||||
// Формируем заголовки с токеном
|
||||
std::map<utility::string_t, utility::string_t> customHeaders;
|
||||
customHeaders[U("Cookie")] = U("access_token=") + accessToken;
|
||||
|
||||
// Шаг 3: Выполняем запрос getTitle
|
||||
return api->getTitle(
|
||||
titleId,
|
||||
boost::none, // fields — оставляем по умолчанию (все поля)
|
||||
customHeaders
|
||||
);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error obtaining impersonation token in fetchTitleAsync: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
}).then([](pplx::task<std::shared_ptr<org::openapitools::client::model::Title>> responseTask) {
|
||||
try {
|
||||
auto response = responseTask.get();
|
||||
if (!response) {
|
||||
throw std::runtime_error("Null response from getTitle");
|
||||
}
|
||||
|
||||
// Преобразуем модель OpenAPI в внутреннюю структуру бота
|
||||
BotStructs::Title botTitle = mapTitleToBotTitle(response);
|
||||
return botTitle;
|
||||
|
||||
} catch (const web::http::http_exception& e) {
|
||||
std::cerr << "HTTP error in fetchTitleAsync: " << e.what() << std::endl;
|
||||
throw;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error in fetchTitleAsync: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BotStructs::Title BotToServer::mapTitleToBotTitle(
|
||||
const std::shared_ptr<org::openapitools::client::model::Title>& titleModel)
|
||||
{
|
||||
if (!titleModel) {
|
||||
throw std::invalid_argument("titleModel is null");
|
||||
}
|
||||
|
||||
BotStructs::Title botTitle;
|
||||
botTitle.id = titleModel->getId();
|
||||
botTitle.num = 0;
|
||||
botTitle.description = ""; // Описание недоступно в текущей модели
|
||||
|
||||
// Извлекаем название
|
||||
std::string titleName;
|
||||
const auto& titleNames = titleModel->getTitleNames();
|
||||
|
||||
// Попробуем ru → en → первый попавшийся
|
||||
std::vector<utility::string_t> preferredLangs = { U("ru"), U("en") };
|
||||
bool found = false;
|
||||
for (const auto& lang : preferredLangs) {
|
||||
auto it = titleNames.find(lang);
|
||||
if (it != titleNames.end() && !it->second.empty()) {
|
||||
titleName = utility::conversions::to_utf8string(it->second[0]);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && !titleNames.empty()) {
|
||||
// Берём первый язык и первое название
|
||||
const auto& firstLang = *titleNames.begin();
|
||||
if (!firstLang.second.empty()) {
|
||||
titleName = utility::conversions::to_utf8string(firstLang.second[0]);
|
||||
}
|
||||
}
|
||||
|
||||
botTitle.name = titleName;
|
||||
|
||||
// --- Изображение ---
|
||||
botTitle.imageUrl = "";
|
||||
if (titleModel->posterIsSet()) {
|
||||
auto poster = titleModel->getPoster();
|
||||
if (poster && poster->imagePathIsSet()) {
|
||||
botTitle.imageUrl = utility::conversions::to_utf8string(poster->getImagePath());
|
||||
}
|
||||
}
|
||||
|
||||
return botTitle;
|
||||
}
|
||||
2
modules/bot/front/.gitignore
vendored
Normal file
2
modules/bot/front/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
build/
|
||||
out/
|
||||
63
modules/bot/front/include/BotUserContext.hpp
Normal file
63
modules/bot/front/include/BotUserContext.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include "constants.hpp"
|
||||
|
||||
enum class UserState {
|
||||
MAIN_MENU, // Главное меню
|
||||
VIEWING_MY_TITLES, // Список моих тайтлов
|
||||
AWAITING_TITLE_NAME, // Жду название тайтла для поиска
|
||||
VIEWING_FOUND_TITLES, // Смотрю найденные тайтлы
|
||||
VIEWING_TITLE_PAGE, // Смотрю страничку тайтла
|
||||
AWAITING_REVIEW, // Жду ревью на тайтл
|
||||
VIEWING_REVIEW_LIST, // Смотрю список ревью на тайтл
|
||||
VIEWING_REVIEW, // Смотрю (конкретное) ревью на тайтл
|
||||
VIEWING_DESCRIPTION, // Смотрю описание тайтла
|
||||
ERROR, // Ошибка состояния
|
||||
};
|
||||
|
||||
struct NavigationStep {
|
||||
UserState state;
|
||||
int64_t payload; // ID тайтла, ревью и т.д.
|
||||
};
|
||||
|
||||
|
||||
struct UserContext {
|
||||
int64_t userId;
|
||||
std::vector<NavigationStep> history; // Текущее состояние пользователя + история предыдущих состояний
|
||||
};
|
||||
|
||||
class BotUserContext {
|
||||
private:
|
||||
mutable std::mutex mtx;
|
||||
std::unordered_map<int64_t, UserContext> userContexts;
|
||||
|
||||
public:
|
||||
// Получить копию контекста пользователя (или std::nullopt, если не найден)
|
||||
std::optional<UserContext> getContext(int64_t userId) const;
|
||||
|
||||
// Установить/обновить контекст пользователя
|
||||
void setContext(int64_t userId, const UserContext& context);
|
||||
|
||||
// Добавить шаг навигации к существующему контексту пользователя
|
||||
// Если пользователя нет — создаётся новый контекст
|
||||
void pushNavigationStep(int64_t userId, const NavigationStep& step);
|
||||
|
||||
// Заменить текущую историю (полезно, например, при сбросе состояния)
|
||||
void setNavigationHistory(int64_t userId, const std::vector<NavigationStep>& history);
|
||||
|
||||
// Получить текущий шаг (последний в истории) или std::nullopt, если нет истории
|
||||
std::optional<NavigationStep> getCurrentStep(int64_t userId) const;
|
||||
|
||||
// pop последнего состояния. true в случае удачи
|
||||
bool popStep(int64_t userId);
|
||||
|
||||
// Удалить контекст пользователя (например, при логауте)
|
||||
void removeContext(int64_t userId);
|
||||
|
||||
/// @brief Создает контекст начального меню для пользователя
|
||||
/// @param userId
|
||||
void createInitContext(int64_t userId);
|
||||
};
|
||||
17
modules/bot/front/include/KeyboardFactory.hpp
Normal file
17
modules/bot/front/include/KeyboardFactory.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <tgbot/tgbot.h>
|
||||
#include "structs.hpp"
|
||||
|
||||
class KeyboardFactory {
|
||||
public:
|
||||
/// Create keyboard for main menu
|
||||
static TgBot::InlineKeyboardMarkup::Ptr createMainMenu();
|
||||
|
||||
/// Create keyboard for My_Titles
|
||||
static TgBot::InlineKeyboardMarkup::Ptr createMyTitles(std::vector<BotStructs::Title> titles);
|
||||
|
||||
/// Create keyboard for sendError
|
||||
static TgBot::InlineKeyboardMarkup::Ptr createError(const std::string& errorCallback);
|
||||
|
||||
/// Create keyboard for Title page
|
||||
static TgBot::InlineKeyboardMarkup::Ptr createTitleMenu(int64_t title_id);
|
||||
};
|
||||
44
modules/bot/front/include/constants.hpp
Normal file
44
modules/bot/front/include/constants.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace BotConstants {
|
||||
const int64_t NULL_PAYLOAD = -1; // Default value для payload
|
||||
const int64_t DISP_TITLES_NUM = 6; // Количество тайтлов, отображаемых на страничке
|
||||
const int64_t DISP_REVIEW_NUM = 4; // Количество ревью, отображаемых на страничке
|
||||
|
||||
namespace Button {
|
||||
const std::string TO_MAIN_MENU = "Главное меню";
|
||||
const std::string FIND_ANIME = "Найти аниме";
|
||||
const std::string MY_TITLES = "Мои тайтлы";
|
||||
const std::string PREV = "<<Назад";
|
||||
const std::string NEXT = "Дальше>>";
|
||||
}
|
||||
namespace Callback {
|
||||
const std::string ACTION = "action:";
|
||||
const std::string FIND_ANIME = ACTION + "find_anime";
|
||||
const std::string ADD_REVIEW = ACTION + "add_review";
|
||||
const std::string ADD_STATUS = ACTION + "add_status";
|
||||
const std::string STATUS = "status:";
|
||||
const std::string WATCHING = STATUS + "watching";
|
||||
const std::string SEEN = STATUS + "seen";
|
||||
const std::string WANT = STATUS + "want";
|
||||
const std::string THROWN = STATUS + "thrown";
|
||||
const std::string NAVIGATION = "navigation:";
|
||||
const std::string MAIN_MENU = NAVIGATION + "main_menu";
|
||||
const std::string MY_TITLES = NAVIGATION + "my_titles";
|
||||
const std::string LIST_PREV = NAVIGATION + "prev"; // Пагинация
|
||||
const std::string LIST_NEXT = NAVIGATION + "next"; // Пагинация
|
||||
const std::string NAV_BACK = NAVIGATION + "back"; // Возврат по стеку состояний
|
||||
const std::string CHOICE = "choice:";
|
||||
const std::string ERROR = "error:";
|
||||
const std::string ERROR_NAVIGATION = ERROR + NAVIGATION;
|
||||
const std::string ERROR_AUTH = ERROR + "auth";
|
||||
}
|
||||
namespace Text {
|
||||
const std::string MAIN_MENU = "Вас приветствует nyanimedb бот:)\nЧего будем делать?";
|
||||
const std::string SAD_ERROR = "У нас что-то случилось:(\nМы обязательно скоро исправимся";
|
||||
const std::string AUTH_ERROR = "Проблемы с авторизацией, попробуйте авторизоваться повторно";
|
||||
const std::string SERVER_ERROR = "Не удалось загрузить данные. Попробуйте позже.";
|
||||
}
|
||||
}
|
||||
27
modules/bot/front/include/front.hpp
Normal file
27
modules/bot/front/include/front.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include <tgbot/tgbot.h>
|
||||
#include "handlers.hpp"
|
||||
|
||||
class AnimeBot {
|
||||
private:
|
||||
TgBot::Bot bot;
|
||||
BotHandlers handler;
|
||||
|
||||
public:
|
||||
/// Init Bot
|
||||
AnimeBot(const std::string& token);
|
||||
|
||||
/// Main menu
|
||||
void setupHandlers();
|
||||
|
||||
/// Get TgBot::Bot
|
||||
TgBot::Bot& getBot();
|
||||
|
||||
/// Function creates main menu and sends it to user with chatId
|
||||
void sendMainMenu(int64_t chatId);
|
||||
};
|
||||
112
modules/bot/front/include/handlers.hpp
Normal file
112
modules/bot/front/include/handlers.hpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#pragma once
|
||||
#include <tgbot/tgbot.h>
|
||||
#include <string>
|
||||
#include <structs.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cctype>
|
||||
#include "BotToServer.hpp"
|
||||
#include "BotUserContext.hpp"
|
||||
|
||||
/// @brief Структура возвращаемого значения класса BotHandlers для изменения текущего сообщения
|
||||
struct HandlerResult {
|
||||
std::string message;
|
||||
TgBot::InlineKeyboardMarkup::Ptr keyboard;
|
||||
};
|
||||
|
||||
class BotHandlers {
|
||||
public:
|
||||
BotHandlers(TgBot::Api api) : botApi(api) {;}
|
||||
|
||||
/// @brief Обработка callback'ов из кнопок интерфейса
|
||||
/// @param query запрос callback
|
||||
void handleCallback(TgBot::CallbackQuery::Ptr query);
|
||||
|
||||
/// @brief Обработка сообщений боту
|
||||
/// @details
|
||||
/// Функция для обработки сообщений, которые юзер отправляет
|
||||
/// боту. Необходима для обработки ревью и названий искомого
|
||||
/// аниме. Внутри себя проверяет текущий state пользователя
|
||||
/// в боте.
|
||||
/// @param message обрабатываемое сообщение
|
||||
void handleMessage(TgBot::Message::Ptr message);
|
||||
|
||||
void initUser(int64_t userId);
|
||||
private:
|
||||
TgBot::Api botApi;
|
||||
BotUserContext contextManager;
|
||||
BotToServer server_;
|
||||
|
||||
void handleNavigation(TgBot::CallbackQuery::Ptr query);
|
||||
|
||||
void handleError(TgBot::CallbackQuery::Ptr query);
|
||||
|
||||
void processCallbackImpl(TgBot::CallbackQuery::Ptr query);
|
||||
|
||||
/// @brief Получить очередную страницу тайтлов из списка пользователя
|
||||
/// @param userId Идентификатор пользователя
|
||||
/// @param payload Полезная нагрузка
|
||||
/// @return HandlerResult
|
||||
/// static HandlerResult returnMyTitles(int64_t userId, int64_t payload);
|
||||
|
||||
/// @brief Уменьшает значение нагрузки с учетом текущего состояния
|
||||
/// @param payload Изменяемое значение нагрузки
|
||||
/// @param curState Текущее состояние
|
||||
void reducePayload(int64_t& payload, const UserState curState);
|
||||
|
||||
/// @brief Увеличивает значение нагрузки с учетом текущего состояния
|
||||
/// @param payload Изменяемое значение нагрузки
|
||||
/// @param curState Текущее состояние
|
||||
void increasePayload(int64_t& payload, const UserState curState);
|
||||
|
||||
/// @brief Редактирует текущее сообщение в диалоге с пользователем
|
||||
/// @details Меняет текст сообщения и клавиатуру на те, что передаются
|
||||
/// в аргументе response. Информацию об id чата и изменяемого сообщения
|
||||
/// забирает из query, который возвращается с callback'ом после нажатия
|
||||
/// кнопки в интерфейсе
|
||||
/// @param query Callback запрос
|
||||
/// @param response Параметры ответа: клавиатура и текст
|
||||
void editMessage(int64_t chatId, int64_t messageId, HandlerResult response);
|
||||
|
||||
/// @brief Редактирует текущее сообщение в диалоге с пользователем
|
||||
/// @details Меняет текст сообщения и клавиатуру на те, что передаются
|
||||
/// в аргументе response, а также прикрепляет картинку
|
||||
/// @param chatId id чата
|
||||
/// @param messageId id меняемого сообщения
|
||||
/// @param imageUrl ссылка на вставляемую картинку (должна быть доступна в публичной сети)
|
||||
/// @param response Параметры ответа: клавиатура и текст
|
||||
void editMessageWithPhoto(
|
||||
int64_t chatId,
|
||||
int64_t messageId,
|
||||
const std::string& imageUrl,
|
||||
HandlerResult response);
|
||||
|
||||
/// @brief Отрисовка текущего экрана (соотв. контексту)
|
||||
/// @param ctx - текущий контекст
|
||||
void renderCurrent(TgBot::CallbackQuery::Ptr query);
|
||||
|
||||
/// @brief Логика переходов между контекстами (навигация на следующий шаг)
|
||||
/// @param query - запрос
|
||||
/// @param current - текущий шаг навигации
|
||||
/// @return следующий NavigationStep при успехе (std::nullopt в случае ошибки)
|
||||
std::optional<NavigationStep> computeNextStep(const TgBot::CallbackQuery::Ptr& query,
|
||||
const NavigationStep& current);
|
||||
|
||||
/// @brief Получить состояние страницы главного меню
|
||||
/// @return HandlerResult с параметрами главного меню
|
||||
HandlerResult showMainMenu();
|
||||
|
||||
/// @brief Посылает интерфейс обработки ошибки на callback запрос
|
||||
/// @param query запрос
|
||||
void sendError(int64_t chatId, int64_t messageId, const std::string& errText);
|
||||
|
||||
// Форматирование для отображения в сообщении
|
||||
std::string formatTitlesList(const std::vector<BotStructs::Title>& titles);
|
||||
|
||||
// Форматирование сообщения на страничке с тайтлом
|
||||
std::string formatTitle(const BotStructs::Title& title);
|
||||
|
||||
// Парсинг id тайтла из callback'а
|
||||
int64_t parseId(const std::string& data);
|
||||
};
|
||||
11
modules/bot/front/include/structs.hpp
Normal file
11
modules/bot/front/include/structs.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace BotStructs {
|
||||
struct Title {
|
||||
int64_t id;
|
||||
std::string name;
|
||||
std::string description;
|
||||
int64_t num;
|
||||
std::string imageUrl;
|
||||
};
|
||||
}
|
||||
58
modules/bot/front/src/BotUserContext.cpp
Normal file
58
modules/bot/front/src/BotUserContext.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include "BotUserContext.hpp"
|
||||
|
||||
std::optional<UserContext> BotUserContext::getContext(int64_t userId) const {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto it = userContexts.find(userId);
|
||||
if (it != userContexts.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void BotUserContext::setContext(int64_t userId, const UserContext& context) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
userContexts[userId] = context;
|
||||
}
|
||||
|
||||
void BotUserContext::pushNavigationStep(int64_t userId, const NavigationStep& step) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto& ctx = userContexts[userId];
|
||||
ctx.userId = userId;
|
||||
ctx.history.push_back(step);
|
||||
}
|
||||
|
||||
void BotUserContext::setNavigationHistory(int64_t userId, const std::vector<NavigationStep>& history) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto& ctx = userContexts[userId];
|
||||
ctx.userId = userId;
|
||||
ctx.history = history;
|
||||
}
|
||||
|
||||
std::optional<NavigationStep> BotUserContext::getCurrentStep(int64_t userId) const {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto it = userContexts.find(userId);
|
||||
if (it != userContexts.end() && !it->second.history.empty()) {
|
||||
return it->second.history.back();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void BotUserContext::removeContext(int64_t userId) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
userContexts.erase(userId);
|
||||
}
|
||||
|
||||
bool BotUserContext::popStep(int64_t userId) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto it = userContexts.find(userId);
|
||||
if (it != userContexts.end() && (it->second.history.size() > 1)) {
|
||||
it->second.history.pop_back();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BotUserContext::createInitContext(int64_t userId) {
|
||||
NavigationStep initStep = {UserState::MAIN_MENU, BotConstants::NULL_PAYLOAD};
|
||||
setContext(userId, {userId, {initStep}});
|
||||
}
|
||||
83
modules/bot/front/src/KeyboardFactory.cpp
Normal file
83
modules/bot/front/src/KeyboardFactory.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include "KeyboardFactory.hpp"
|
||||
#include "constants.hpp"
|
||||
|
||||
TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createMainMenu() {
|
||||
auto keyboard = std::make_shared<TgBot::InlineKeyboardMarkup>();
|
||||
TgBot::InlineKeyboardButton::Ptr button1(new TgBot::InlineKeyboardButton);
|
||||
button1->text = BotConstants::Button::FIND_ANIME;
|
||||
button1->callbackData = BotConstants::Callback::FIND_ANIME;
|
||||
TgBot::InlineKeyboardButton::Ptr button2(new TgBot::InlineKeyboardButton);
|
||||
button2->text = BotConstants::Button::MY_TITLES;
|
||||
button2->callbackData = BotConstants::Callback::MY_TITLES;
|
||||
|
||||
keyboard->inlineKeyboard = {{button1, button2}};
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
// TODO: Переписать с учетом констант на количество отображаемых тайтлов и нового callback'a
|
||||
TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createMyTitles(std::vector<BotStructs::Title> titles) {
|
||||
auto keyboard = std::make_shared<TgBot::InlineKeyboardMarkup>();
|
||||
std::vector<TgBot::InlineKeyboardButton::Ptr> row;
|
||||
std::vector<std::vector<TgBot::InlineKeyboardButton::Ptr>> layout;
|
||||
|
||||
int counter = 0;
|
||||
for(BotStructs::Title& title : titles) {
|
||||
if(counter >= BotConstants::DISP_TITLES_NUM) {
|
||||
break;
|
||||
}
|
||||
auto button = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button->text = std::to_string(title.num + 1) + " " + title.name;
|
||||
button->callbackData = BotConstants::Callback::CHOICE + std::to_string(title.num);
|
||||
row.push_back(button);
|
||||
counter++;
|
||||
if(counter % 2 == 0) {
|
||||
layout.push_back(row);
|
||||
row.clear();
|
||||
}
|
||||
}
|
||||
if (!row.empty()) {
|
||||
layout.push_back(row);
|
||||
row.clear();
|
||||
}
|
||||
|
||||
// TODO: Додумать логику, когда пришло 6 записей в конце
|
||||
if(counter % 2 == 1) {
|
||||
auto button = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button->text = BotConstants::Button::PREV;
|
||||
if(titles[0].num == 0) {
|
||||
button->callbackData = BotConstants::Callback::NAV_BACK;
|
||||
}
|
||||
else {
|
||||
button->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
}
|
||||
layout.back().push_back(button);
|
||||
}
|
||||
else {
|
||||
auto button_prev = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button_prev->text = BotConstants::Button::PREV;
|
||||
if(titles[0].num == 0) {
|
||||
button_prev->callbackData = BotConstants::Callback::NAV_BACK;
|
||||
}
|
||||
else {
|
||||
button_prev->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
}
|
||||
auto button_next = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button_next->text = BotConstants::Button::NEXT;
|
||||
button_next->callbackData = BotConstants::Callback::LIST_NEXT + ':' + std::to_string(titles[5].num);
|
||||
layout.push_back({button_prev, button_next});
|
||||
}
|
||||
|
||||
keyboard->inlineKeyboard = layout;
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createError(const std::string& errorCallback) {
|
||||
auto keyboard = std::make_shared<TgBot::InlineKeyboardMarkup>();
|
||||
TgBot::InlineKeyboardButton::Ptr button(new TgBot::InlineKeyboardButton);
|
||||
button->text = BotConstants::Button::TO_MAIN_MENU;
|
||||
button->callbackData = errorCallback;
|
||||
|
||||
keyboard->inlineKeyboard = {{button}};
|
||||
return keyboard;
|
||||
}
|
||||
35
modules/bot/front/src/front.cpp
Normal file
35
modules/bot/front/src/front.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include "front.hpp"
|
||||
#include "KeyboardFactory.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "handlers.hpp"
|
||||
|
||||
AnimeBot::AnimeBot(const std::string& token)
|
||||
: bot(token)
|
||||
, handler(bot.getApi()) {
|
||||
setupHandlers();
|
||||
}
|
||||
|
||||
void AnimeBot::setupHandlers() {
|
||||
bot.getEvents().onCommand("start", [this](TgBot::Message::Ptr message) {
|
||||
sendMainMenu(message->chat->id);
|
||||
//TODO: производить инициализацию контекста только после авторизации
|
||||
handler.initUser(message->from->id);
|
||||
});
|
||||
|
||||
bot.getEvents().onCallbackQuery([this](TgBot::CallbackQuery::Ptr query) {
|
||||
handler.handleCallback(query);
|
||||
});
|
||||
|
||||
bot.getEvents().onAnyMessage([this](TgBot::Message::Ptr message) {
|
||||
handler.handleMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
void AnimeBot::sendMainMenu(int64_t chatId) {
|
||||
auto keyboard = KeyboardFactory::createMainMenu();
|
||||
bot.getApi().sendMessage(chatId, BotConstants::Text::MAIN_MENU, nullptr, nullptr, keyboard);
|
||||
}
|
||||
|
||||
TgBot::Bot& AnimeBot::getBot() {
|
||||
return bot;
|
||||
}
|
||||
219
modules/bot/front/src/handleNavigation.cpp
Normal file
219
modules/bot/front/src/handleNavigation.cpp
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#include "handlers.hpp"
|
||||
#include "KeyboardFactory.hpp"
|
||||
#include "structs.hpp"
|
||||
#include "constants.hpp"
|
||||
|
||||
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
||||
//const auto& current = ctx.history.back(); // текущий экран
|
||||
const std::string& data = query->data;
|
||||
int64_t userId = query->from->id;
|
||||
int64_t chatId = query->message->chat->id;
|
||||
int64_t messageId = query->message->messageId;
|
||||
|
||||
// Пагинация (в списках)
|
||||
/* Временно отключаем, все равно не функционирует :)
|
||||
if ((data == BotConstants::Callback::LIST_PREV || data == BotConstants::Callback::LIST_NEXT)
|
||||
&& (current.state == UserState::VIEWING_MY_TITLES || current.state == UserState::VIEWING_REVIEW_LIST ||
|
||||
current.state == UserState::VIEWING_FOUND_TITLES)) {
|
||||
|
||||
int64_t newPayload = current.payload;
|
||||
if (data == BotConstants::Callback::LIST_PREV && newPayload > 0) {
|
||||
reducePayload(newPayload, current.state);
|
||||
} else if (data == BotConstants::Callback::LIST_NEXT) {
|
||||
increasePayload(newPayload, current.state);
|
||||
} else {
|
||||
if (data == BotConstants::Callback::LIST_PREV) {
|
||||
std::cout << "Error: navigation:prev callback for 1st page" << std::endl;
|
||||
return;
|
||||
}
|
||||
// TODO: log
|
||||
std::cout << "Error: navigation:prev unknown error" << std::endl;
|
||||
}
|
||||
|
||||
ctx.history.back().payload = newPayload;
|
||||
|
||||
renderCurrent(query, ctx);
|
||||
return;
|
||||
}*/
|
||||
|
||||
// Обработка back по интерфейсу
|
||||
if (data == BotConstants::Callback::NAV_BACK) {
|
||||
if (!contextManager.popStep(userId)) {
|
||||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
renderCurrent(query);
|
||||
return;
|
||||
}
|
||||
|
||||
// Переходы вперёд (push)
|
||||
std::optional<NavigationStep> currentStep = contextManager.getCurrentStep(userId);
|
||||
if(!currentStep.has_value()) {
|
||||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
auto newStepOpt = computeNextStep(query, currentStep.value());
|
||||
if (!newStepOpt.has_value()) {
|
||||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
contextManager.pushNavigationStep(userId, newStepOpt.value());
|
||||
renderCurrent(query);
|
||||
}
|
||||
|
||||
void BotHandlers::renderCurrent(TgBot::CallbackQuery::Ptr query) {
|
||||
int64_t userId = query->from->id;
|
||||
int64_t chatId = query->message->chat->id;
|
||||
int64_t messageId = query->message->messageId;
|
||||
|
||||
auto step = contextManager.getCurrentStep(userId);
|
||||
if(!step.has_value()) {;
|
||||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (step.value().state) {
|
||||
case UserState::MAIN_MENU:
|
||||
editMessage(chatId, messageId, showMainMenu());
|
||||
return;
|
||||
case UserState::VIEWING_MY_TITLES:
|
||||
server_.fetchUserTitlesAsync(std::to_string(22)) // ALARM: тестовое значение вместо userId
|
||||
.then([this, chatId, messageId](pplx::task<std::vector<BotStructs::Title>> t) {
|
||||
try {
|
||||
auto titles = t.get();
|
||||
|
||||
std::string message = formatTitlesList(titles);
|
||||
auto keyboard = KeyboardFactory::createMyTitles(titles);
|
||||
|
||||
editMessage(chatId, messageId, {message, keyboard});
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
sendError(chatId, messageId, BotConstants::Text::SERVER_ERROR);
|
||||
// Логирование ошибки (например, в cerr)
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
case UserState::VIEWING_TITLE_PAGE:
|
||||
server_.fetchTitleAsync(std::to_string(22), step.value().payload)
|
||||
.then([this, chatId, messageId](pplx::task<BotStructs::Title> t) {
|
||||
try {
|
||||
auto title = t.get();
|
||||
|
||||
std::string message = formatTitle(title);
|
||||
auto keyboard = KeyboardFactory::createTitleMenu(title.id);
|
||||
|
||||
std::string imageUrl = "https://i.pinimg.com/736x/30/2b/49/302b49176e5a74ef43871a462df47e1f.jpg";
|
||||
|
||||
editMessageWithPhoto(chatId, messageId, imageUrl, {message, keyboard});
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
sendError(chatId, messageId, BotConstants::Text::SERVER_ERROR);
|
||||
// Логирование ошибки (например, в cerr)
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
/*
|
||||
case UserState::VIEWING_REVIEW:
|
||||
return returnReview(step.payload); // payload = reviewId
|
||||
case UserState::AWAITING_REVIEW:
|
||||
return HandlerResult{"Пришлите текст отзыва:", nullptr};
|
||||
// ...
|
||||
*/
|
||||
default:
|
||||
return editMessage(chatId, messageId, HandlerResult{BotConstants::Text::SAD_ERROR, nullptr});
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<NavigationStep> BotHandlers::computeNextStep(
|
||||
const TgBot::CallbackQuery::Ptr& query,
|
||||
const NavigationStep& current
|
||||
) {
|
||||
const std::string& data = query->data;
|
||||
|
||||
switch (current.state) {
|
||||
case UserState::MAIN_MENU:
|
||||
if (data == BotConstants::Callback::MY_TITLES) {
|
||||
return NavigationStep{UserState::VIEWING_MY_TITLES, 0};
|
||||
}
|
||||
break;
|
||||
|
||||
case UserState::VIEWING_MY_TITLES:
|
||||
if (data.starts_with(BotConstants::Callback::CHOICE)) {
|
||||
int64_t titleId = parseId(data);
|
||||
return NavigationStep{UserState::VIEWING_TITLE_PAGE, titleId};
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case UserState::VIEWING_TITLE_PAGE:
|
||||
if (data == BotConstants::Callback::ACTION_ADD_REVIEW) {
|
||||
return NavigationStep{UserState::AWAITING_REVIEW, current.payload};
|
||||
}
|
||||
if (data.starts_with("review_")) {
|
||||
int64_t reviewId = parseId(data);
|
||||
return NavigationStep{UserState::VIEWING_REVIEW, reviewId};
|
||||
}
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string BotHandlers::formatTitlesList(const std::vector<BotStructs::Title>& titles) {
|
||||
if (titles.empty()) {
|
||||
return "У вас пока нет тайтлов.";
|
||||
}
|
||||
|
||||
std::string msg;
|
||||
for (size_t i = 0; i < titles.size(); ++i) {
|
||||
// num — 0-based, но в сообщении показываем 1-based
|
||||
msg += std::to_string(i + 1) + ". " + titles[i].name + "\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
std::string BotHandlers::formatTitle(const BotStructs::Title& title) {
|
||||
std::string msg;
|
||||
msg += title.name + "\n";
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
int64_t BotHandlers::parseId(const std::string& data) {
|
||||
const std::string prefix = "choice:";
|
||||
if (data.substr(0, prefix.size()) != prefix) {
|
||||
throw std::invalid_argument("Data does not start with 'choice:'");
|
||||
}
|
||||
|
||||
std::string idPart = data.substr(prefix.size());
|
||||
|
||||
// Проверяем, что остаток состоит только из цифр (и, возможно, знака '-')
|
||||
if (idPart.empty()) {
|
||||
throw std::invalid_argument("ID part is empty");
|
||||
}
|
||||
|
||||
size_t startPos = 0;
|
||||
if (idPart[0] == '-') {
|
||||
if (idPart.size() == 1) {
|
||||
throw std::invalid_argument("Invalid negative ID");
|
||||
}
|
||||
startPos = 1;
|
||||
}
|
||||
|
||||
for (size_t i = startPos; i < idPart.size(); ++i) {
|
||||
if (!std::isdigit(static_cast<unsigned char>(idPart[i]))) {
|
||||
throw std::invalid_argument("ID contains non-digit characters");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return std::stoll(idPart);
|
||||
} catch (const std::out_of_range&) {
|
||||
throw std::out_of_range("ID is out of range for int64_t");
|
||||
}
|
||||
}
|
||||
187
modules/bot/front/src/handlers.cpp
Normal file
187
modules/bot/front/src/handlers.cpp
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#include "handlers.hpp"
|
||||
#include "KeyboardFactory.hpp"
|
||||
#include "structs.hpp"
|
||||
#include "constants.hpp"
|
||||
|
||||
void BotHandlers::handleCallback(TgBot::CallbackQuery::Ptr query) {
|
||||
if (!query) {
|
||||
// TODO: log
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: Тут mutex на многопоточке
|
||||
botApi.answerCallbackQuery(query->id);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "answerCallbackQuery error";
|
||||
//TODO: обработка ошибки
|
||||
}
|
||||
|
||||
processCallbackImpl(query);
|
||||
}
|
||||
|
||||
/* deprecated. will be deleted soon.
|
||||
HandlerResult BotHandlers::returnMyTitles(int64_t userId, int64_t payload) {
|
||||
// Здесь должен происходить запрос на сервер
|
||||
std::vector<BotStructs::Title> titles = {{123, "Школа мертвяков", "", 1}, {321, "KissXsis", "", 2}};
|
||||
|
||||
struct HandlerResult result;
|
||||
result.keyboard = KeyboardFactory::createMyTitles(titles);
|
||||
result.message = "1. Школа мертвяков\n2. KissXsis\n";
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
void BotHandlers::handleMessage(TgBot::Message::Ptr message) {
|
||||
//TODO: просмотр состояния пользователя
|
||||
return;
|
||||
}
|
||||
|
||||
void BotHandlers::processCallbackImpl(TgBot::CallbackQuery::Ptr query) {
|
||||
const std::string& data = query->data;
|
||||
int64_t userId = query->from->id;
|
||||
int64_t chatId = query->message->chat->id;
|
||||
int64_t messageId = query->message->messageId;
|
||||
|
||||
std::optional<UserContext> ctx = contextManager.getContext(userId);
|
||||
if (!ctx.has_value()) {
|
||||
// TODO: log
|
||||
sendError(chatId, messageId, BotConstants::Text::AUTH_ERROR);
|
||||
std::cout << "Error: Не нашел пользователя " << userId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.starts_with(BotConstants::Callback::NAVIGATION)) {
|
||||
handleNavigation(query);
|
||||
}
|
||||
else if (data.starts_with(BotConstants::Callback::CHOICE)) {
|
||||
handleNavigation(query);
|
||||
}
|
||||
else if (data.starts_with(BotConstants::Callback::ERROR)) {
|
||||
handleError(query);
|
||||
}
|
||||
else {
|
||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void BotHandlers::reducePayload(int64_t& payload, const UserState curState) {
|
||||
if (curState == UserState::VIEWING_MY_TITLES ||
|
||||
curState == UserState::VIEWING_FOUND_TITLES) {
|
||||
payload -= BotConstants::DISP_TITLES_NUM;
|
||||
} else if (curState == UserState::VIEWING_REVIEW_LIST) {
|
||||
payload -= BotConstants::DISP_REVIEW_NUM;
|
||||
} else {
|
||||
// TODO: log
|
||||
payload = BotConstants::NULL_PAYLOAD;
|
||||
std::cerr << "Error: reducePayload" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void BotHandlers::increasePayload(int64_t& payload, const UserState curState) {
|
||||
if (curState == UserState::VIEWING_MY_TITLES ||
|
||||
curState == UserState::VIEWING_FOUND_TITLES) {
|
||||
payload += BotConstants::DISP_TITLES_NUM;
|
||||
} else if (curState == UserState::VIEWING_REVIEW_LIST) {
|
||||
payload += BotConstants::DISP_REVIEW_NUM;
|
||||
} else {
|
||||
// TODO: log
|
||||
payload = BotConstants::NULL_PAYLOAD;
|
||||
std::cerr << "Error: increasePayload" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void BotHandlers::editMessage(int64_t chatId, int64_t messageId, HandlerResult response) {
|
||||
// botApi.editMessageText быстрее. Реализовать его, где возможно
|
||||
try {
|
||||
botApi.deleteMessage(chatId, messageId);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Warning: Failed to delete message " << messageId
|
||||
<< " in chat " << chatId << ": " << e.what() << std::endl;
|
||||
// Продолжаем отправку нового сообщения даже при ошибке удаления
|
||||
}
|
||||
|
||||
// 2. Отправляем новое сообщение с правильным порядком параметров
|
||||
botApi.sendMessage(
|
||||
chatId, // chatId
|
||||
response.message, // text
|
||||
nullptr, // linkPreviewOptions (nullptr = default)
|
||||
nullptr, // replyParameters (не отвечаем на сообщение)
|
||||
response.keyboard, // replyMarkup — клавиатура
|
||||
"HTML", // parseMode — поддержка <b>, <i> и т.д.
|
||||
false // disableNotification
|
||||
// остальные параметры по умолчанию
|
||||
);
|
||||
}
|
||||
|
||||
void BotHandlers::editMessageWithPhoto(
|
||||
int64_t chatId,
|
||||
int64_t messageId,
|
||||
const std::string& imageUrl,
|
||||
HandlerResult response)
|
||||
{
|
||||
// 1. Удаляем старое сообщение
|
||||
try {
|
||||
botApi.deleteMessage(chatId, messageId);
|
||||
} catch (const std::exception& e) {
|
||||
// Игнорируем ошибку, если сообщение уже удалено или недоступно
|
||||
std::cerr << "Warning: Failed to delete message: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
std::string safeCaption = response.message;
|
||||
if (safeCaption.length() > 1024) {
|
||||
safeCaption = safeCaption.substr(0, 1021) + "...";
|
||||
}
|
||||
|
||||
// Отправка фото по URL
|
||||
botApi.sendPhoto(
|
||||
chatId,
|
||||
imageUrl,
|
||||
safeCaption,
|
||||
nullptr,
|
||||
response.keyboard,
|
||||
"HTML"
|
||||
);
|
||||
}
|
||||
|
||||
HandlerResult BotHandlers::showMainMenu() {
|
||||
auto keyboard = KeyboardFactory::createMainMenu();
|
||||
|
||||
return HandlerResult{BotConstants::Text::MAIN_MENU, keyboard};
|
||||
}
|
||||
|
||||
void BotHandlers::sendError(int64_t chatId, int64_t messageId, const std::string& errText) {
|
||||
//TODO: посылать сообщение с кнопкой возврата в главное меню
|
||||
TgBot::InlineKeyboardMarkup::Ptr keyboard;
|
||||
if (errText == BotConstants::Text::SAD_ERROR) {
|
||||
keyboard = KeyboardFactory::createError(BotConstants::Callback::ERROR_NAVIGATION);
|
||||
}
|
||||
else if (errText == BotConstants::Text::AUTH_ERROR) {
|
||||
keyboard = nullptr; //KeyboardFactory::createError(BotConstants::Callback::ERROR_AUTH);
|
||||
}
|
||||
|
||||
editMessage(chatId, messageId, {errText, keyboard});
|
||||
}
|
||||
|
||||
void BotHandlers::handleError(TgBot::CallbackQuery::Ptr query) {
|
||||
const std::string& data = query->data;
|
||||
int64_t userId = query->from->id;
|
||||
int64_t chatId = query->message->chat->id;
|
||||
int64_t messageId = query->message->messageId;
|
||||
|
||||
if(data == BotConstants::Callback::ERROR_NAVIGATION) {
|
||||
contextManager.removeContext(userId);
|
||||
contextManager.createInitContext(userId);
|
||||
auto result = showMainMenu();
|
||||
editMessage(chatId, messageId, result);
|
||||
}
|
||||
else if(data == BotConstants::Callback::ERROR_AUTH) {
|
||||
// TODO: продумать логику
|
||||
HandlerResult result = {BotConstants::Text::AUTH_ERROR, nullptr};
|
||||
editMessage(chatId, messageId, result);
|
||||
}
|
||||
}
|
||||
|
||||
void BotHandlers::initUser(int64_t userId) {
|
||||
contextManager.createInitContext(userId);
|
||||
}
|
||||
15
modules/bot/front/src/main.cpp
Normal file
15
modules/bot/front/src/main.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include <front.hpp>
|
||||
|
||||
int main() {
|
||||
AnimeBot bot(getenv("TOKEN"));
|
||||
TgBot::TgLongPoll longPoll(bot.getBot());
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
longPoll.start();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue