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.

186 lines
5.1KB

  1. #include <sys/stat.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <stdbool.h>
  5. #include <time.h>
  6. #include "cmd.h"
  7. #include "error.h"
  8. #include "uio.h"
  9. #include "api.h"
  10. #include "config.h"
  11. #include "ed2k_util.h"
  12. #include "cache.h"
  13. #include "util.h"
  14. static enum error cmd_add_update(uint64_t lid)
  15. {
  16. enum error err;
  17. struct api_result res;
  18. struct api_mylistadd_opts mods;
  19. err = api_cmd_mylist(lid, &res);
  20. if (err != NOERR)
  21. return err;
  22. mods.state = res.mylist.state;
  23. mods.state_set = true;
  24. mods.watched = res.mylist.viewdate != 0;
  25. mods.watched_set = true;
  26. if (mods.watched) {
  27. mods.wdate = res.mylist.viewdate;
  28. mods.wdate_set = true;
  29. }
  30. err = cache_update(lid, &mods);
  31. return err;
  32. }
  33. static enum error cmd_add_cachecheck(const char *path, const struct stat *st,
  34. void *data)
  35. {
  36. struct cache_entry ce;
  37. const char *bname = util_basename(path);
  38. enum error err;
  39. err = cache_get(bname, st->st_size,
  40. CACHE_S_LID | CACHE_S_WATCHDATE | CACHE_S_MODDATE, &ce);
  41. if (err == NOERR) {
  42. /* We could get the entry, so it exists already */
  43. uio_user("This file (%s) with size (%lu) already exists in cache."
  44. " Skipping hashing", bname, st->st_size);
  45. /* Update time is older than 5 days and it's not watched yet */
  46. if (ce.wdate == 0 && ce.moddate - time(NULL) > 5 * 24 * 60 * 60) {
  47. uio_debug("Updating entry with id: %lu", ce.lid);
  48. if (cmd_add_update(ce.lid) != NOERR) {
  49. uio_warning("Cannot update file that is in cache");
  50. }
  51. }
  52. return ED2KUTIL_DONTHASH;
  53. } else if (err != ERR_CACHE_NO_EXISTS) {
  54. uio_error("Some error when trying to get from cache: %s",
  55. error_to_string(err));
  56. return ED2KUTIL_DONTHASH;
  57. }
  58. uio_user("Hashing %s", path);
  59. return NOERR;
  60. }
  61. static enum error cmd_add_apisend(const char *path, const uint8_t *hash,
  62. const struct stat *st, void *data)
  63. {
  64. struct api_result r;
  65. struct api_mylistadd_opts *mopt = (struct api_mylistadd_opts *)data;
  66. if (api_cmd_mylistadd(st->st_size, hash, mopt, &r)
  67. != NOERR)
  68. return ERR_CMD_FAILED;
  69. if (r.code == APICODE_FILE_ALREADY_IN_MYLIST) {
  70. struct api_mylist_result *x = &r.mylist;
  71. uio_warning("File already added! Adding it to cache");
  72. uio_debug("File info: lid: %ld, fid: %ld, eid: %ld, aid: %ld,"
  73. " gid: %ld, date: %ld, viewdate: %ld, state: %d,"
  74. " filestate: %d\nstorage: %s\nsource: %s\nother: %s",
  75. x->lid, x->fid, x->eid, x->aid, x->gid, x->date, x->viewdate,
  76. x->state, x->filestate, x->storage, x->source, x->other);
  77. cache_add(x->lid, util_basename(path), st->st_size, hash, x->viewdate,
  78. x->state);
  79. if (x->storage)
  80. free(x->storage);
  81. if (x->source)
  82. free(x->source);
  83. if (x->other)
  84. free(x->other);
  85. return NOERR;
  86. }
  87. if (r.code == APICODE_NO_SUCH_FILE) {
  88. uio_error("This file does not exists in the AniDB databse: %s",
  89. path);
  90. return NOERR;
  91. }
  92. if (r.code != APICODE_MYLIST_ENTRY_ADDED) {
  93. uio_error("Mylistadd failure: %hu", r.code);
  94. return ERR_CMD_FAILED;
  95. }
  96. uio_user("Succesfully added!");
  97. uio_debug("New mylist id is: %ld", r.mylistadd.new_id);
  98. uint64_t wdate = 0;
  99. if (mopt->watched_set && mopt->watched) {
  100. if (mopt->wdate_set)
  101. wdate = mopt->wdate;
  102. else
  103. wdate = time(NULL);
  104. }
  105. cache_add(r.mylistadd.new_id, util_basename(path), st->st_size, hash,
  106. wdate, mopt->state_set ? mopt->state : MYLIST_STATE_INTERNAL);
  107. return NOERR;
  108. }
  109. enum error cmd_add(void *data)
  110. {
  111. struct api_mylistadd_opts mopt = {0};
  112. struct ed2k_util_opts ed2k_opts = {
  113. .pre_hash_fn = cmd_add_cachecheck,
  114. .post_hash_fn = cmd_add_apisend,
  115. .data = &mopt,
  116. };
  117. bool *watched;
  118. const char **wdate_str;
  119. enum error err = NOERR;
  120. int fcount;
  121. fcount = config_get_nonopt_count();
  122. if (fcount == 0) {
  123. uio_error("No files specified");
  124. return ERR_CMD_ARG;
  125. }
  126. if (config_get("watched", (void**)&watched) == NOERR && *watched) {
  127. mopt.watched = *watched;
  128. mopt.watched_set = true;
  129. if (config_get("wdate", (void**)&wdate_str) == NOERR) {
  130. uint64_t wdate = util_iso2unix(*wdate_str);
  131. if (wdate == 0) {
  132. uio_error("Invalid time value: '%s'", *wdate_str);
  133. return ERR_CMD_ARG;
  134. }
  135. mopt.wdate = wdate;
  136. mopt.wdate_set = true;
  137. }
  138. }
  139. mopt.state = MYLIST_STATE_INTERNAL;
  140. mopt.state_set = true;
  141. for (int i = 0; i < fcount; i++) {
  142. err = ed2k_util_iterpath(config_get_nonopt(i), &ed2k_opts);
  143. if (err != NOERR)
  144. break;
  145. }
  146. return err;
  147. }
  148. enum error cmd_add_argcheck()
  149. {
  150. if (config_get_nonopt_count() == 0) {
  151. uio_error("No files specified");
  152. return ERR_CMD_ARG;
  153. }
  154. return NOERR;
  155. }