8#include <nlohmann/json.hpp>
16#include <unordered_set>
22namespace TgBot::ApiRequest {
24TGBOT_API void appendField(std::vector<HttpFormField>& fields, std::string_view name, std::string_view value);
25TGBOT_API void appendField(std::vector<HttpFormField>& fields, std::string_view name,
26 const std::shared_ptr<InputFile>& value);
29requires(!std::is_convertible_v<const T&, std::string_view>)
30void appendField(std::vector<HttpFormField>& fields, std::string_view name,
const T& value) {
31 if constexpr (std::is_arithmetic_v<T>) {
32 fields.push_back({ std::string(name), std::to_string(value) });
34 fields.push_back({ std::string(name), Json::encode(value).dump() });
39void appendField(std::vector<HttpFormField>& fields, std::string_view name,
const std::optional<T>& value) {
41 appendField(fields, name, *value);
46void appendField(std::vector<HttpFormField>& fields, std::string_view name,
const std::shared_ptr<T>& value) {
48 fields.push_back({ std::string(name), Json::encode(value).dump() });
52template<
typename... T>
53void appendField(std::vector<HttpFormField>& fields, std::string_view name,
const std::variant<T...>& value) {
55 [&](
const auto& item) {
56 appendField(fields, name, item);
62requires std::is_arithmetic_v<T>
63void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name, T value) {
65 appendField(fields, name, value);
69TGBOT_API void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name, std::string_view value);
70TGBOT_API void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
const std::string& value);
72TGBOT_API void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
73 const nlohmann::json& value);
74TGBOT_API void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
75 const std::vector<InputFileAttachment>& value);
78void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
const std::shared_ptr<T>& value) {
80 appendField(fields, name, value);
85void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
const std::vector<T>& value) {
87 appendField(fields, name, value);
91template<
typename... T>
92void appendOptionalField(std::vector<HttpFormField>& fields, std::string_view name,
const std::variant<T...>& value) {
94 [&](
const auto& item) {
95 appendOptionalField(fields, name, item);
106template<
bool Required,
typename T>
108 static constexpr bool isRequired = Required;
110 std::string_view name;
121struct ParameterWithDefault {
122 static constexpr bool isRequired =
false;
124 std::string_view name;
130Parameter<true, T> required(std::string_view name,
const T& value) {
131 return { name, value };
135Parameter<false, T> optional(std::string_view name,
const T& value) {
136 return { name, value };
140ParameterWithDefault<T> optional(std::string_view name,
const T& value, T defaultValue) {
141 return { name, value, std::move(defaultValue) };
144template<
typename... Parameters>
145std::vector<HttpFormField> makeFields(
const Parameters&... parameters) {
146 std::vector<HttpFormField> result;
147 result.reserve(
sizeof...(Parameters));
150 if constexpr (Parameters::isRequired) {
151 appendField(result, parameters.name, parameters.value);
152 }
else if constexpr (
requires { parameters.defaultValue; }) {
153 if (parameters.value != parameters.defaultValue) {
154 appendField(result, parameters.name, parameters.value);
157 appendOptionalField(result, parameters.name, parameters.value);
162 std::unordered_set<std::string_view> names;
163 for (
const auto& field : result) {
164 if (!names.emplace(field.name).second) {
165 throw std::invalid_argument(
"Duplicate multipart field name: " + field.name);
174namespace TgBot::ApiResponse {
177T decode(
const nlohmann::json& json) {
179 Json::decode(json, result);
185std::shared_ptr<T> decodeObjectOrTrue(
const nlohmann::json& json) {
186 auto result = decode<std::variant<std::shared_ptr<T>,
bool>>(json);
187 if (
auto object = std::get_if<std::shared_ptr<T>>(&result)) {