Add 'myliststats' command
This commit is contained in:
parent
9ddafb8240
commit
be61d8dabc
104
src/api.c
104
src/api.c
@ -484,27 +484,34 @@ static enum error api_ratelimit()
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the written byte count
|
* 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)
|
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;
|
ssize_t read_len;
|
||||||
int en;
|
int en;
|
||||||
|
|
||||||
if (api_ratelimit() == ERR_SHOULD_EXIT)
|
if (api_ratelimit() == ERR_SHOULD_EXIT) {
|
||||||
return -2;
|
read_len = -2;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
uio_debug("{Api}: Sending: %.*s", (int)data_len, buffer);
|
uio_debug("{Api}: Sending: %.*s", (int)data_len, buffer);
|
||||||
if (api_encryption)
|
if (api_encryption)
|
||||||
data_len = api_encrypt(buffer, data_len);
|
data_len = api_encrypt(buffer, data_len);
|
||||||
|
|
||||||
en = net_send(buffer, data_len);
|
en = net_send(buffer, data_len);
|
||||||
if (en < 0)
|
if (en < 0) {
|
||||||
return en;
|
read_len = en;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
read_len = net_read(buffer, buf_size);
|
read_len = net_read(buffer, buf_size);
|
||||||
if (read_len < 0) {
|
if (read_len < 0) {
|
||||||
uio_error("!!! BAD PLACE EINTR !!! report pls");
|
if (read_len == -EINTR)
|
||||||
return read_len; /* This could lead so some problems if we also want to
|
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
|
log out. If we hit this, the msg got sent, but we
|
||||||
couldn't read the response. That means, in the
|
couldn't read the response. That means, in the
|
||||||
logout call, this msg's data will be read
|
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);
|
read_len = api_decrypt(buffer, read_len);
|
||||||
uio_debug("{Api}: Reading: %.*s", (int)read_len, buffer);
|
uio_debug("{Api}: Reading: %.*s", (int)read_len, buffer);
|
||||||
|
|
||||||
|
end:
|
||||||
|
pthread_mutex_unlock(&api_work_mx);
|
||||||
return read_len;
|
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;
|
enum error err = NOERR;
|
||||||
int retry_count = 0;
|
int retry_count = 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&api_work_mx);
|
|
||||||
api_g_retry_count = 0;
|
api_g_retry_count = 0;
|
||||||
|
|
||||||
while (retry_count < API_MAX_TRYAGAIN &&
|
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);
|
res_len = api_send(buffer, send_len, API_BUFSIZE);
|
||||||
|
|
||||||
if (res_len < 0) {
|
if (res_len < 0) {
|
||||||
if (res_len == -2 && should_exit)
|
if (res_len == -EINTR && should_exit)
|
||||||
err = ERR_SHOULD_EXIT;
|
err = ERR_SHOULD_EXIT;
|
||||||
else
|
else
|
||||||
err = ERR_API_COMMFAIL;
|
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 (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++;
|
api_g_retry_count++;
|
||||||
if (api_g_retry_count < API_MAX_TRYAGAIN) {
|
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 */
|
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 */
|
err = api_auth(); /* -> will call this function */
|
||||||
if (api_g_retry_count < API_MAX_TRYAGAIN) {
|
if (api_g_retry_count < API_MAX_TRYAGAIN) {
|
||||||
memcpy(buffer, l_buff, send_len);
|
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:
|
end:
|
||||||
pthread_mutex_unlock(&api_work_mx);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
static enum error api_cmd_base(char buffer[API_BUFSIZE], struct api_result *res,
|
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;
|
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
|
#pragma GCC diagnostic pop
|
||||||
|
12
src/api.h
12
src/api.h
@ -2,6 +2,7 @@
|
|||||||
#define _API_H
|
#define _API_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
@ -243,6 +244,15 @@ struct api_mylistadd_result {
|
|||||||
struct api_mylistmod_result {
|
struct api_mylistmod_result {
|
||||||
uint32_t n_edits;
|
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
|
#define e(n) struct api_##n##_result n
|
||||||
struct api_result {
|
struct api_result {
|
||||||
@ -255,6 +265,7 @@ struct api_result {
|
|||||||
e(mylistadd);
|
e(mylistadd);
|
||||||
e(encrypt);
|
e(encrypt);
|
||||||
e(mylistmod);
|
e(mylistmod);
|
||||||
|
e(myliststats);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#undef e
|
#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);
|
struct api_mylistadd_opts *opts, struct api_result *res);
|
||||||
enum error api_cmd_mylistmod(uint64_t lid, struct api_mylistadd_opts *opts,
|
enum error api_cmd_mylistmod(uint64_t lid, struct api_mylistadd_opts *opts,
|
||||||
struct api_result *res);
|
struct api_result *res);
|
||||||
|
enum error api_cmd_myliststats(struct api_result *res);
|
||||||
|
|
||||||
#endif /* _API_H */
|
#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 = "server-version", .fn = cmd_server_version, .need_api = true },
|
||||||
{ .arg_name = "uptime", .fn = cmd_server_uptime, .need_auth = true },
|
{ .arg_name = "uptime", .fn = cmd_server_uptime, .need_auth = true },
|
||||||
{ .arg_name = "ed2k", .fn = cmd_ed2k, },
|
{ .arg_name = "ed2k", .fn = cmd_ed2k, },
|
||||||
|
|
||||||
{ .arg_name = "add", .fn = cmd_add, .argcheck = cmd_add_argcheck, .need_auth = true, .need_cache = true, },
|
{ .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 = "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);
|
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(void *data);
|
||||||
enum error cmd_modify_argcheck();
|
enum error cmd_modify_argcheck();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request the mylist stats
|
||||||
|
*/
|
||||||
|
enum error cmd_stats(void *data);
|
||||||
|
|
||||||
#endif /* _CMD_H */
|
#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]),
|
.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,
|
/*{ .l_name = "stats", .s_name = UCHAR_MAX + 5,
|
||||||
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
|
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
|
||||||
.type = OTYPE_B, .handle_order = 1, .value_is_set = 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;
|
int en = errno;
|
||||||
|
|
||||||
uio_error("{net} Read failed: %s", strerror(errno));
|
uio_error("{net} Read failed: %s", strerror(errno));
|
||||||
if (en == EINTR)
|
return -en;
|
||||||
return -2;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (read == read_size)
|
if (read == read_size)
|
||||||
uio_warning("{net} Data may have been discarded!");
|
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
|
* Send and read data to and from the api
|
||||||
* Returns the number of bytes sent/read or -1 on error
|
* Returns the number of bytes sent/read or
|
||||||
* If the error is EINTR, it returns -2
|
* a negative value which is the errno */
|
||||||
*/
|
|
||||||
ssize_t net_send(const void *msg, size_t msg_len);
|
ssize_t net_send(const void *msg, size_t msg_len);
|
||||||
ssize_t net_read(void *out_data, size_t read_size);
|
ssize_t net_read(void *out_data, size_t read_size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user