A tool for adding anime to your anidb list.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

215 lignes
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. }