6
6
#include < openssl/bio.h>
7
7
#include < nlohmann/json.hpp>
8
8
9
+ #include < iostream>
10
+
9
11
using json = nlohmann::json;
10
12
11
13
std::string replace (const std::string_view& str, char replace, const std::string& with) noexcept {
@@ -22,6 +24,7 @@ template<typename T> T is_null(const nlohmann::json& j) noexcept {
22
24
23
25
using bio_callback = std::unique_ptr<BIO, decltype(&::BIO_free_all)>&;
24
26
27
+ /* TODO: handle connection state REGARDING sudden unhandled crashes or stay alives. ~@LeeEndl */
25
28
void request (std::function<void (bio_callback)> callback) {
26
29
std::unique_ptr<BIO, decltype (&::BIO_free_all)> bio{ BIO_new_ssl_connect (SSL_CTX_new (TLS_client_method ())), ::BIO_free_all };
27
30
BIO_ctrl (bio.get (), BIO_C_SET_CONNECT, 0L , const_cast <char *>(" api.jikan.moe:https" ));
@@ -96,28 +99,16 @@ class anime {
96
99
this ->synopsis = is_null<std::string>(j[" synopsis" ]);
97
100
this ->background = is_null<std::string>(j[" background" ]);
98
101
}
99
- constexpr ~anime () = default ;
102
+ /* comments made by @LeeEndl. contact via github for any problems */
103
+ constexpr anime () = default; // initializes (0/null) variables disregarding JSON. used for lite/lightweight data parenting (used in manga)
104
+ constexpr ~anime () = default ; // ^ same above but for deconstruct. nearly useless in this context but whatever
100
105
private:
101
106
};
102
107
103
- class manga {
108
+ class manga : public anime {
104
109
public:
105
- int mal_id{};
106
- std::vector<std::string> image{}; /* the front image on MAL of that manga. enum: image_size */
107
- std::string title{}; /* recommended title. as some manga only have japanese title. */
108
- std::string jp_title{}; /* Japanese title. */
109
110
int chapters{}; /* amount of chapters this manga contains. */
110
111
int volumes{}; /* amount of volumes this manga contains. */
111
- bool publishing{}; /* if the manga is still being published. */
112
- std::tm published{}; /* when the manga was published */
113
- std::tm next_publish{}; /* when the manga's next published chapter */
114
- double score{}; /* medium of overall score of this manga. e.g. 1.0 - 10.0 */
115
- int scored_by{}; /* number of people who scored this manga. */
116
- int rank{}; /* manga ranking. */
117
- int popularity{}; /* the overall popularity of this manga. */
118
- int favorites{}; /* total favorites. */
119
- std::string synopsis{}; /* about the manga. */
120
- std::string background{}; /* about the production. */
121
112
explicit manga (const json& j) noexcept {
122
113
this ->mal_id = is_null<int >(j[" mal_id" ]);
123
114
for (const char * const & size : { " image_url" , " small_image_url" , " large_image_url" })
@@ -126,13 +117,13 @@ class manga {
126
117
this ->jp_title = is_null<std::string>(j[" title_japanese" ]);
127
118
this ->chapters = is_null<int >(j[" chapters" ]);
128
119
this ->volumes = is_null<int >(j[" volumes" ]);
129
- this ->publishing = is_null<bool >(j[" publishing" ]);
130
- this ->published .tm_year = is_null<int >(j[" published" ][" prop" ][" from" ][" year" ]);
131
- this ->published .tm_mon = is_null<int >(j[" published" ][" prop" ][" from" ][" month" ]) + 1 ;
132
- this ->published .tm_mday = is_null<int >(j[" published" ][" prop" ][" from" ][" day" ]);
133
- this ->next_publish .tm_year = is_null<int >(j[" published" ][" prop" ][" to" ][" year" ]);
134
- this ->next_publish .tm_mon = is_null<int >(j[" published" ][" prop" ][" to" ][" month" ]) + 1 ;
135
- this ->next_publish .tm_mday = is_null<int >(j[" published" ][" prop" ][" to" ][" day" ]);
120
+ this ->airing = is_null<bool >(j[" publishing" ]);
121
+ this ->released .tm_year = is_null<int >(j[" published" ][" prop" ][" from" ][" year" ]);
122
+ this ->released .tm_mon = is_null<int >(j[" published" ][" prop" ][" from" ][" month" ]) + 1 ;
123
+ this ->released .tm_mday = is_null<int >(j[" published" ][" prop" ][" from" ][" day" ]);
124
+ this ->next_release .tm_year = is_null<int >(j[" published" ][" prop" ][" to" ][" year" ]);
125
+ this ->next_release .tm_mon = is_null<int >(j[" published" ][" prop" ][" to" ][" month" ]) + 1 ;
126
+ this ->next_release .tm_mday = is_null<int >(j[" published" ][" prop" ][" to" ][" day" ]);
136
127
this ->score = is_null<double >(j[" score" ]);
137
128
this ->scored_by = is_null<int >(j[" scored_by" ]);
138
129
this ->rank = is_null<int >(j[" rank" ]);
@@ -166,39 +157,41 @@ namespace mal {
166
157
void search (const std::string_view& name, const short & results, std::function<void (const T&)> callback) {
167
158
short i_results{};
168
159
for (short page = 1 ; page <= (results + 24 ) / 25 ; ++page) {
169
- std::unique_ptr<json> j = std::make_unique<json>();
170
160
request ([&](bio_callback bio) {
171
161
BIO_puts (bio.get (),
172
162
webpage (std::format (
173
163
" /v4/{0}?q=\" {1}\" &limit={2}&page={3}" ,
174
164
std::string (typeid (T).name ()).substr (sizeof (" class " ) - 1 , sizeof (typeid (T).name ())), replace (name, ' ' , " %20" ), 25 , page)).c_str ()
175
165
);
166
+ std::unique_ptr<std::string> all_data = std::make_unique<std::string>();
176
167
{
177
- std::unique_ptr<std::string> all_data = std::make_unique<std::string>();
178
- {
179
- std::unique_ptr<bool > once = std::make_unique<bool >(false );
180
- std::unique_ptr<char []> data = std::make_unique<char []>(INT_MAX);
181
- for (int r = BIO_read (bio.get (), data.get (), INT_MAX); r > 0 ; r = BIO_read (bio.get (), data.get (), INT_MAX)) {
182
- data[r] = static_cast <char >(0 );
183
- all_data->append (data.get ());
184
- if (not *once and all_data->find (" \r\n\r\n " ) not_eq -1 ) {
185
- all_data = std::make_unique<std::string>(all_data->substr (all_data->find (" \r\n\r\n " ) + 4 ));
186
- once.reset (new bool (true ));
187
- }
168
+ std::unique_ptr<bool > once = std::make_unique<bool >(false );
169
+ std::unique_ptr<char []> data = std::make_unique<char []>(16384 );
170
+ for (int r = BIO_read (bio.get (), data.get (), 16384 ); r > 0 ; r = BIO_read (bio.get (), data.get (), 16384 )) {
171
+ data[r] = static_cast <char >(0 );
172
+ all_data->append (data.get ());
173
+ if (not *once and all_data->find (" \r\n\r\n " ) not_eq -1 ) {
174
+ all_data = std::make_unique<std::string>(all_data->substr (all_data->find (" \r\n\r\n " ) + 4 ));
175
+ once.reset (new bool (true ));
188
176
}
189
- std::erase_if (*all_data, [](const char & c) { return not std::isprint (c); });
190
177
}
191
- all_data = std::make_unique<std::string>(all_data->substr (sizeof " \n\r\n " , all_data->size () - sizeof " \n\r\n 0" ));
192
- if (json::accept (*all_data))
193
- *j = json (json::parse (*all_data));
178
+ std::erase_if (*all_data, [](const char & c) { return not std::isprint (static_cast <int >(c)); });
194
179
}
195
- });
196
- if ((*j)[" data" ].is_null ()) break ;
197
- for (const json& data : (*j)[" data" ]) {
198
- i_results++;
199
- if (i_results > results) break ;
200
- callback (T (data));
180
+ all_data = std::make_unique<std::string>(all_data->substr (sizeof " \n\r\n " , all_data->size () - sizeof " \n\r\n 0" ));
181
+ try {
182
+ std::unique_ptr<json> j = std::make_unique<json>();
183
+ *j = json (json::parse (*all_data));
184
+ if ((*j)[" data" ].is_null ()) return nullptr ;
185
+ for (const json& data : (*j)[" data" ]) {
186
+ i_results++;
187
+ if (i_results > results) return nullptr ;
188
+ callback (T (data));
189
+ }
190
+ }
191
+ catch (json::exception & e) {
192
+ if (e.id == 101 ) std::cout << " [MAL.cpp] ah oh! seems there is an error that is acknowledged by the developer... this issue will be treated soon as possible!" << std::endl;
201
193
}
194
+ });
202
195
}
203
196
}
204
- }
197
+ }
0 commit comments