Compare commits

...

2 Commits

Author SHA1 Message Date
x3
1135f9df05
Remove TODO from readme 2023-08-09 17:27:24 +02:00
x3
be61d8dabc
Add 'myliststats' command 2023-08-09 17:26:53 +02:00
9 changed files with 161 additions and 18 deletions

View File

@ -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
View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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
View 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;
}

View File

@ -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 },*/

View File

@ -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!");

View File

@ -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);