Compare commits
2 Commits
9ddafb8240
...
1135f9df05
Author | SHA1 | Date | |
---|---|---|---|
1135f9df05 | |||
be61d8dabc |
@ -26,7 +26,6 @@ make
|
||||
- Decode escaping from server
|
||||
- Use a config file
|
||||
- Add newline escape to server
|
||||
- Add myliststats cmd as --stats arg
|
||||
- Add support for compression
|
||||
- Implement session saving between different invocations, and session destroying
|
||||
- Automatically remove found anime from wishlist
|
||||
|
104
src/api.c
104
src/api.c
@ -484,27 +484,34 @@ static enum error api_ratelimit()
|
||||
|
||||
/*
|
||||
* Returns the written byte count
|
||||
* Or -1 on error, and -2 if errno was EINTR
|
||||
* Or negative errno value on error
|
||||
*/
|
||||
static ssize_t api_send(char *buffer, size_t data_len, size_t buf_size)
|
||||
{
|
||||
pthread_mutex_lock(&api_work_mx);
|
||||
|
||||
ssize_t read_len;
|
||||
int en;
|
||||
|
||||
if (api_ratelimit() == ERR_SHOULD_EXIT)
|
||||
return -2;
|
||||
if (api_ratelimit() == ERR_SHOULD_EXIT) {
|
||||
read_len = -2;
|
||||
goto end;
|
||||
}
|
||||
uio_debug("{Api}: Sending: %.*s", (int)data_len, buffer);
|
||||
if (api_encryption)
|
||||
data_len = api_encrypt(buffer, data_len);
|
||||
|
||||
en = net_send(buffer, data_len);
|
||||
if (en < 0)
|
||||
return en;
|
||||
if (en < 0) {
|
||||
read_len = en;
|
||||
goto end;
|
||||
}
|
||||
|
||||
read_len = net_read(buffer, buf_size);
|
||||
if (read_len < 0) {
|
||||
uio_error("!!! BAD PLACE EINTR !!! report pls");
|
||||
return read_len; /* This could lead so some problems if we also want to
|
||||
if (read_len == -EINTR)
|
||||
uio_error("!!! BAD PLACE EINTR !!! report pls");
|
||||
goto end; /* This could lead so some problems if we also want to
|
||||
log out. If we hit this, the msg got sent, but we
|
||||
couldn't read the response. That means, in the
|
||||
logout call, this msg's data will be read
|
||||
@ -516,6 +523,8 @@ static ssize_t api_send(char *buffer, size_t data_len, size_t buf_size)
|
||||
read_len = api_decrypt(buffer, read_len);
|
||||
uio_debug("{Api}: Reading: %.*s", (int)read_len, buffer);
|
||||
|
||||
end:
|
||||
pthread_mutex_unlock(&api_work_mx);
|
||||
return read_len;
|
||||
}
|
||||
|
||||
@ -686,7 +695,6 @@ static enum error api_cmd_base_pref(char buffer[API_BUFSIZE], int send_len,
|
||||
enum error err = NOERR;
|
||||
int retry_count = 0;
|
||||
|
||||
pthread_mutex_lock(&api_work_mx);
|
||||
api_g_retry_count = 0;
|
||||
|
||||
while (retry_count < API_MAX_TRYAGAIN &&
|
||||
@ -701,7 +709,7 @@ static enum error api_cmd_base_pref(char buffer[API_BUFSIZE], int send_len,
|
||||
res_len = api_send(buffer, send_len, API_BUFSIZE);
|
||||
|
||||
if (res_len < 0) {
|
||||
if (res_len == -2 && should_exit)
|
||||
if (res_len == -EINTR && should_exit)
|
||||
err = ERR_SHOULD_EXIT;
|
||||
else
|
||||
err = ERR_API_COMMFAIL;
|
||||
@ -742,10 +750,24 @@ static enum error api_cmd_base_pref(char buffer[API_BUFSIZE], int send_len,
|
||||
}
|
||||
|
||||
if (err == ERR_API_NOLOGIN || err == ERR_API_INV_SESSION) {
|
||||
if (api_authed == false) {
|
||||
/* If this happens and we are not logged in, don't retry */
|
||||
err = ERR_API_COMMFAIL;
|
||||
break;
|
||||
}
|
||||
api_g_retry_count++;
|
||||
if (api_g_retry_count < API_MAX_TRYAGAIN) {
|
||||
uio_debug("Let's try loggin in agane");
|
||||
struct timespec ts;
|
||||
MS_TO_TIMESPEC_L(ts, 30000);
|
||||
|
||||
uio_debug("Let's try loggin in agane after waiting some");
|
||||
api_authed = false; /* We got logged out probably */
|
||||
if (nanosleep(&ts, NULL) == -1) {
|
||||
if (errno == EINTR && should_exit) {
|
||||
err = ERR_SHOULD_EXIT;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
err = api_auth(); /* -> will call this function */
|
||||
if (api_g_retry_count < API_MAX_TRYAGAIN) {
|
||||
memcpy(buffer, l_buff, send_len);
|
||||
@ -764,7 +786,6 @@ static enum error api_cmd_base_pref(char buffer[API_BUFSIZE], int send_len,
|
||||
}
|
||||
|
||||
end:
|
||||
pthread_mutex_unlock(&api_work_mx);
|
||||
return err;
|
||||
}
|
||||
static enum error api_cmd_base(char buffer[API_BUFSIZE], struct api_result *res,
|
||||
@ -1022,4 +1043,65 @@ enum error api_cmd_mylistmod(uint64_t lid, struct api_mylistadd_opts *opts,
|
||||
return err;
|
||||
}
|
||||
|
||||
static enum error api_cmd_myliststats_resp_parse(const char *buffer, struct api_myliststats_result *stats)
|
||||
{
|
||||
/* all int
|
||||
*
|
||||
* {animes}|{eps}|{files}|{size of files}|{added animes}|{added eps}|
|
||||
* {added files}|{added groups}|{leech %}|{glory %}|{viewed % of db}|
|
||||
* {mylist % of db}|{viewed % of mylist}|{number of viewed eps}|
|
||||
* {votes}|{reviews}|{viewed length in minutes}
|
||||
*/
|
||||
|
||||
bool glr;
|
||||
char *line;
|
||||
size_t line_len;
|
||||
int fc;
|
||||
|
||||
glr = api_get_line(buffer, 2, &line, &line_len);
|
||||
if (!glr)
|
||||
return ERR_API_RESP_INVALID;
|
||||
fc = api_field_parse(line,
|
||||
"%lu", &stats->animes,
|
||||
"%lu", &stats->eps,
|
||||
"%lu", &stats->files,
|
||||
"%lu", &stats->size_of_files,
|
||||
"%lu", &stats->added_animes,
|
||||
"%lu", &stats->added_eps,
|
||||
"%lu", &stats->added_files,
|
||||
"%lu", &stats->added_groups,
|
||||
"%lu", &stats->leech_prcnt,
|
||||
"%lu", &stats->glory_prcnt,
|
||||
"%lu", &stats->viewed_prcnt_of_db,
|
||||
"%lu", &stats->mylist_prcnt_of_db,
|
||||
"%lu", &stats->viewed_prcnt_of_mylist,
|
||||
"%lu", &stats->num_of_viewed_eps,
|
||||
"%lu", &stats->votes,
|
||||
"%lu", &stats->reviews,
|
||||
"%lu", &stats->viewed_minutes,
|
||||
NULL);
|
||||
if (fc != 17) {
|
||||
uio_error("Scanf only parsed %d", fc);
|
||||
return ERR_API_RESP_INVALID;
|
||||
}
|
||||
|
||||
return NOERR;
|
||||
}
|
||||
|
||||
enum error api_cmd_myliststats(struct api_result *res)
|
||||
{
|
||||
char buffer[API_BUFSIZE];
|
||||
enum error err = NOERR;
|
||||
|
||||
err = api_cmd_base(buffer, res, "MYLISTSTATS s=%s", api_session);
|
||||
//err = api_cmd_base(buffer, res, "MYLISTSTATS");
|
||||
if (err != NOERR)
|
||||
return err;
|
||||
|
||||
if (res->code == APICODE_MYLIST_STATS)
|
||||
return api_cmd_myliststats_resp_parse(buffer, &res->myliststats);
|
||||
else
|
||||
return ERR_API_RESP_INVALID;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
12
src/api.h
12
src/api.h
@ -2,6 +2,7 @@
|
||||
#define _API_H
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
@ -243,6 +244,15 @@ struct api_mylistadd_result {
|
||||
struct api_mylistmod_result {
|
||||
uint32_t n_edits;
|
||||
};
|
||||
/* The largest struct probably lul 136 bytes */
|
||||
struct api_myliststats_result {
|
||||
uint64_t animes, eps, files, size_of_files;
|
||||
uint64_t added_animes, added_eps, added_files;
|
||||
uint64_t added_groups, leech_prcnt, glory_prcnt;
|
||||
uint64_t viewed_prcnt_of_db, mylist_prcnt_of_db;
|
||||
uint64_t viewed_prcnt_of_mylist, num_of_viewed_eps;
|
||||
uint64_t votes, reviews, viewed_minutes;
|
||||
};
|
||||
|
||||
#define e(n) struct api_##n##_result n
|
||||
struct api_result {
|
||||
@ -255,6 +265,7 @@ struct api_result {
|
||||
e(mylistadd);
|
||||
e(encrypt);
|
||||
e(mylistmod);
|
||||
e(myliststats);
|
||||
};
|
||||
};
|
||||
#undef e
|
||||
@ -269,5 +280,6 @@ enum error api_cmd_mylistadd(int64_t size, const uint8_t *hash,
|
||||
struct api_mylistadd_opts *opts, struct api_result *res);
|
||||
enum error api_cmd_mylistmod(uint64_t lid, struct api_mylistadd_opts *opts,
|
||||
struct api_result *res);
|
||||
enum error api_cmd_myliststats(struct api_result *res);
|
||||
|
||||
#endif /* _API_H */
|
||||
|
@ -23,8 +23,10 @@ static const struct cmd_entry ents[] = {
|
||||
{ .arg_name = "server-version", .fn = cmd_server_version, .need_api = true },
|
||||
{ .arg_name = "uptime", .fn = cmd_server_uptime, .need_auth = true },
|
||||
{ .arg_name = "ed2k", .fn = cmd_ed2k, },
|
||||
|
||||
{ .arg_name = "add", .fn = cmd_add, .argcheck = cmd_add_argcheck, .need_auth = true, .need_cache = true, },
|
||||
{ .arg_name = "modify", .fn = cmd_modify, .argcheck = cmd_modify_argcheck, .need_auth = true, .need_cache = true, },
|
||||
{ .arg_name = "stats", .fn = cmd_stats, .need_auth = true, .need_cache = false, },
|
||||
};
|
||||
static const int32_t ents_len = sizeof(ents)/sizeof(*ents);
|
||||
|
||||
|
@ -42,4 +42,9 @@ enum error cmd_prog_version(void *);
|
||||
enum error cmd_modify(void *data);
|
||||
enum error cmd_modify_argcheck();
|
||||
|
||||
/*
|
||||
* Request the mylist stats
|
||||
*/
|
||||
enum error cmd_stats(void *data);
|
||||
|
||||
#endif /* _CMD_H */
|
||||
|
40
src/cmd_stats.c
Normal file
40
src/cmd_stats.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "error.h"
|
||||
#include "api.h"
|
||||
#include "util.h"
|
||||
#include "uio.h"
|
||||
|
||||
enum error cmd_stats(void *data)
|
||||
{
|
||||
enum error err = NOERR;
|
||||
struct api_result res;
|
||||
struct api_myliststats_result *stats = &res.myliststats;
|
||||
|
||||
err = api_cmd_myliststats(&res);
|
||||
if (err != NOERR) {
|
||||
uio_error("Failed to request stats from API server");
|
||||
return err;
|
||||
}
|
||||
|
||||
printf("Mylist status:\n"
|
||||
"Anime: %lu\n"
|
||||
"Episodes: %lu\n"
|
||||
"Files: %lu\n"
|
||||
"Size of files: %lu\n"
|
||||
"Added groups: %lu\n"
|
||||
"leech%%: %lu\n"
|
||||
"Glory%%: %lu\n"
|
||||
"Viewed%%/DB: %lu\n"
|
||||
"Mylist%%/DB: %lu\n"
|
||||
"Viewed%%/Mylist: %lu\n"
|
||||
"Viewed eps: %lu\n"
|
||||
"Votes: %lu\n"
|
||||
"Reviews: %lu\n"
|
||||
"Viewed minutes: %lu\n",
|
||||
stats->animes, stats->eps, stats->files, stats->size_of_files, stats->added_groups,
|
||||
stats->leech_prcnt, stats->glory_prcnt, stats->viewed_prcnt_of_db,
|
||||
stats->mylist_prcnt_of_db, stats->viewed_prcnt_of_mylist, stats->num_of_viewed_eps,
|
||||
stats->votes, stats->reviews, stats->viewed_minutes);
|
||||
return NOERR;
|
||||
}
|
@ -171,6 +171,12 @@ static struct conf_entry options[] = {
|
||||
.subopts_count = sizeof(modify_add_subopts) / sizeof(modify_add_subopts[0]),
|
||||
},
|
||||
|
||||
{ .l_name = "stats", .s_name = UCHAR_MAX + 10,
|
||||
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
|
||||
.type = OTYPE_SUBCOMMAND, .handle_order = 1,
|
||||
.h_desc = "Get the mylist status",
|
||||
},
|
||||
|
||||
/*{ .l_name = "stats", .s_name = UCHAR_MAX + 5,
|
||||
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
|
||||
.type = OTYPE_B, .handle_order = 1, .value_is_set = true },*/
|
||||
|
@ -265,9 +265,7 @@ ssize_t net_read(void* out_data, size_t read_size)
|
||||
int en = errno;
|
||||
|
||||
uio_error("{net} Read failed: %s", strerror(errno));
|
||||
if (en == EINTR)
|
||||
return -2;
|
||||
return -1;
|
||||
return -en;
|
||||
}
|
||||
if (read == read_size)
|
||||
uio_warning("{net} Data may have been discarded!");
|
||||
|
@ -12,9 +12,8 @@ enum error net_init();
|
||||
|
||||
/*
|
||||
* Send and read data to and from the api
|
||||
* Returns the number of bytes sent/read or -1 on error
|
||||
* If the error is EINTR, it returns -2
|
||||
*/
|
||||
* Returns the number of bytes sent/read or
|
||||
* a negative value which is the errno */
|
||||
ssize_t net_send(const void *msg, size_t msg_len);
|
||||
ssize_t net_read(void *out_data, size_t read_size);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user