A tool for adding anime to your anidb list.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
5.2KB

  1. #include <sys/stat.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include "cmd.h"
  8. #include "error.h"
  9. #include "uio.h"
  10. #include "api.h"
  11. #include "config.h"
  12. #include "cache.h"
  13. #include "util.h"
  14. bool did_cache_init = false;
  15. uint64_t cmd_modify_arg_parse(const char *str, uint64_t *out_wdate)
  16. {
  17. uint64_t val;
  18. struct cache_entry ce;
  19. enum error err;
  20. const char *fn_st = strrchr(str, '/');
  21. const char *size_st = strchr(str, '/');
  22. *out_wdate = 0;
  23. /* Skip the '/' */
  24. if (fn_st)
  25. fn_st++;
  26. if (size_st)
  27. size_st++;
  28. if (fn_st == size_st) {
  29. /* size/filename format */
  30. size_st = str;
  31. } else {
  32. size_t timelen = size_st - str - 1; /* -1 for the skipped '/' */
  33. char timstr[timelen + 1];
  34. memcpy(timstr, str, timelen);
  35. timstr[timelen] = '\0';
  36. *out_wdate = util_iso2unix(timstr);
  37. }
  38. if (sscanf(size_st, "%lu", &val) != 1)
  39. return 0;
  40. if (!fn_st && !size_st) /* Only lid format */
  41. return val;
  42. if (!cache_is_init()) {
  43. if (cache_init() != NOERR)
  44. return 0;
  45. did_cache_init = true;
  46. }
  47. err = cache_get(fn_st, val, CACHE_S_LID, &ce);
  48. if (err != NOERR)
  49. return 0;
  50. return ce.lid;
  51. }
  52. static enum error cmd_modify_api_send(uint64_t lid, struct api_mylistadd_opts *opts)
  53. {
  54. struct api_result res;
  55. enum error err = api_cmd_mylistmod(lid, opts, &res);
  56. if (err != NOERR)
  57. return err;
  58. if (res.code == APICODE_NO_SUCH_MYLIST_ENTRY) {
  59. uio_error("No mylist entry with id: '%lu'", lid);
  60. return ERR_UNKNOWN;
  61. }
  62. #if 0
  63. if (!cache_is_init()) {
  64. if ((err = cache_init()) != NOERR)
  65. return err;
  66. did_cache_init = true;
  67. }
  68. #endif
  69. err = cache_update(lid, opts);
  70. if (err == NOERR) {
  71. uio_user("Successfully updated entry with lid:%lu", lid);
  72. }
  73. return err;
  74. }
  75. static enum error cmd_modify_file_cb(const char *path, const struct stat *fstat, void *data)
  76. {
  77. struct cache_entry ce;
  78. enum error err;
  79. struct api_mylistadd_opts *opts = data;
  80. char *basename = util_basename(path);
  81. uio_debug("Modifying mylist by file: %s", basename);
  82. /* Get the mylist id from the cache */
  83. err = cache_get(basename, fstat->st_size, CACHE_S_LID, &ce);
  84. if (err != NOERR) {
  85. uio_error("Failed to get file from cache: %lu:%s. Maybe we should add it now?",
  86. fstat->st_size, basename);
  87. return err;
  88. }
  89. /* We have the mylistid, so actually send the change to the api */
  90. return cmd_modify_api_send(ce.lid, opts);
  91. }
  92. static enum error cmd_modify_by_file(const char *fpath, struct api_mylistadd_opts *opts)
  93. {
  94. return util_iterpath(fpath, cmd_modify_file_cb, opts);
  95. }
  96. static enum error cmd_modify_by_mylistid(const char *arg, struct api_mylistadd_opts *opts)
  97. {
  98. struct api_mylistadd_opts local_opts = *opts;
  99. uint64_t wdate, lid;
  100. lid = cmd_modify_arg_parse(arg, &wdate);
  101. if (lid == 0) {
  102. uio_error("Argument '%s' is not valid. Skipping", arg);
  103. return ERR_UNKNOWN;
  104. }
  105. /* If info is present in the argument line set it for the update */
  106. if (wdate != 0) {
  107. local_opts.watched = true;
  108. local_opts.watched_set = true;
  109. local_opts.wdate = wdate;
  110. local_opts.wdate_set = true;
  111. }
  112. return cmd_modify_api_send(lid, &local_opts);
  113. }
  114. static enum error cmd_modify_process_arg(const char *arg, struct api_mylistadd_opts *opts)
  115. {
  116. struct stat fs;
  117. /* Check if the given path is a file/directory */
  118. if (stat(arg, &fs) == 0) {
  119. /* File exists handle with the file handler */
  120. return cmd_modify_by_file(arg, opts);
  121. }
  122. /* If stat failed */
  123. int eno = errno;
  124. if (eno != ENOENT) {
  125. /* Failed for some other reason apart from file not existing */
  126. uio_warning("Stat for file '%s' failed with: %s", arg, strerror(eno));
  127. return ERR_UNKNOWN;
  128. }
  129. /* File simply not found, try the with the mylistid syntax */
  130. return cmd_modify_by_mylistid(arg, opts);
  131. }
  132. enum error cmd_modify(void *data)
  133. {
  134. struct api_mylistadd_opts mopt = {0};
  135. bool *watched;
  136. const char **wdate_str;
  137. enum error err = NOERR;
  138. int fcount;
  139. fcount = config_get_nonopt_count();
  140. if (config_get_subopt("modify", "watched", (void**)&watched) == NOERR && *watched) {
  141. mopt.watched = *watched;
  142. mopt.watched_set = true;
  143. if (config_get_subopt("modify", "wdate", (void**)&wdate_str) == NOERR) {
  144. uint64_t wdate = util_iso2unix(*wdate_str);
  145. if (wdate == 0) {
  146. uio_error("Invalid time value: '%s'", *wdate_str);
  147. return ERR_CMD_ARG;
  148. }
  149. mopt.wdate = wdate;
  150. mopt.wdate_set = true;
  151. }
  152. }
  153. for (int i = 0; i < fcount; i++) {
  154. const char *arg = config_get_nonopt(i);
  155. cmd_modify_process_arg(arg, &mopt);
  156. }
  157. #if 0
  158. if (did_cache_init) {
  159. did_cache_init = false;
  160. cache_free();
  161. }
  162. #endif
  163. return err;
  164. }
  165. enum error cmd_modify_argcheck()
  166. {
  167. if (config_get_nonopt_count() == 0) {
  168. uio_error("No arguments given for modify");
  169. return ERR_CMD_ARG;
  170. }
  171. return NOERR;
  172. }