Baphomet is the dedicated bot for nulloctet matrix
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.

136 lines
4.4 KiB

  1. /**
  2. * Szurubooru api client
  3. */
  4. let axios = require('axios');
  5. let { logger } = require('../../logging');
  6. function getRandomInt(min, max) {
  7. min = Math.ceil(min);
  8. max = Math.floor(max);
  9. return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
  10. }
  11. class SzurubooruClient {
  12. url: string;
  13. baseUrl: string;
  14. username: string;
  15. token: string;
  16. randomImageCount: number;
  17. _randomSearchQueryValues: string = "type:image,animated,video sort:random";
  18. _randomSearchUrlTemplate: string = "%s/posts/?offset=%s&limit=%d&query=%s";
  19. constructor(url: string, username: string, token: string) {
  20. this.url = url;
  21. this.baseUrl = url.replace('/api', '');
  22. this.username = username;
  23. this.token = token;
  24. this.updateRandomScope();
  25. }
  26. getRandomSearchUrl(offset: number, limit: number, tags: Array<string> = []) {
  27. var searchQuery = this._randomSearchQueryValues;
  28. if (tags !== null && tags.length > 0) {
  29. searchQuery = this._randomSearchQueryValues + tags.join(" ");
  30. }
  31. return this.url + '/posts/?offset=' + offset + '&limit=' + limit + '&query=' + searchQuery;
  32. }
  33. /**
  34. * Determine a sane range of offset values
  35. *
  36. * @param {*} limit The content limit of a single page
  37. * @param {*} total The number of objects to search through
  38. */
  39. getValidOffsetRange(limit: number, total: number): Array<number> {
  40. let offsetOverflow = total % limit;
  41. var offsetCeiling = (Math.round(total / limit));
  42. if (offsetOverflow === 0) {
  43. offsetCeiling -= 1;
  44. }
  45. return [0, offsetCeiling];
  46. }
  47. /**
  48. * Determine a random offset based on the potential random search size
  49. *
  50. * Because Szurubooru doesn't randomize each sort:random search request, we must
  51. * manually calculate a random offset for each request to simulate randomness in the
  52. * posts returned.
  53. *
  54. * @param {*} self
  55. * @param {*} imageCount
  56. */
  57. getRandomSearchParameters(imageCount?: number) {
  58. let resultLimit = 10;
  59. var offsetRange = [0, 1];
  60. if (imageCount === null) {
  61. offsetRange = this.getValidOffsetRange(resultLimit, this.randomImageCount);
  62. } else {
  63. offsetRange = this.getValidOffsetRange(resultLimit, imageCount);
  64. }
  65. return [resultLimit, getRandomInt(offsetRange[0], offsetRange[1])];
  66. }
  67. async updateRandomScope() {
  68. let client = this;
  69. let target = this.getRandomSearchUrl(0, 1);
  70. await this.makeGetRequest(target).then((result: any) => {
  71. client.randomImageCount = result.total;
  72. });
  73. }
  74. makeGetRequest(url: string) {
  75. logger.debug("Making get request to %s", url);
  76. return axios.get(url, {
  77. headers: {
  78. "Authorization": "Token " + Buffer.from(this.username + ':' + this.token).toString('base64'),
  79. "Accept": "application/json"
  80. }
  81. }).then((response: any) => {
  82. logger.debug("Recieved: %o", response.data);
  83. return response.data;
  84. }, (err: any) => {
  85. logger.error("Unexpected client error: %o", err);
  86. return null;
  87. });
  88. }
  89. /**
  90. * Return a random post matching the optionally provided tags.
  91. *
  92. * @param {*} self
  93. * @param {*} tags
  94. */
  95. getRandomPost(tags: Array<string> = []) {
  96. let client = this;
  97. var resultLimit = 0;
  98. var randomSearchOffset = 0;
  99. if (tags.length === 0) {
  100. let randomSearchParameters = this.getRandomSearchParameters();
  101. resultLimit = randomSearchParameters[0];
  102. randomSearchOffset = randomSearchParameters[1];
  103. }
  104. let searchUrl = this.getRandomSearchUrl(randomSearchOffset, resultLimit, tags);
  105. return this.makeGetRequest(searchUrl)
  106. .then((data: any) => {
  107. if (data !== null) {
  108. let limitSpace = Math.min(resultLimit, data.results.length - 1);
  109. let randomPost = data.results[getRandomInt(0, limitSpace)];
  110. return client.baseUrl + '/' + randomPost.contentUrl;
  111. } else {
  112. return null
  113. }
  114. }, (err: any) => {
  115. logger.error("Unexpected error: %o", err);
  116. return null;
  117. })
  118. }
  119. }
  120. export { SzurubooruClient as Client };