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.

178 lines
5.2 KiB

11 months ago
  1. const { EncryptionManager } = require("../EncryptionManager");
  2. // When running locally will occupy the 0.0.0.0 hostname space but when deployed inside
  3. // of docker this endpoint is not exposed so it is only on the Docker instances internal network
  4. // so no additional security is needed on the endpoint directly. Auth is done however by the express
  5. // middleware prior to leaving the node-side of the application so that is good enough >:)
  6. class CollectorApi {
  7. constructor() {
  8. const { CommunicationKey } = require("../comKey");
  9. this.comkey = new CommunicationKey();
  10. this.endpoint = `http://0.0.0.0:${process.env.COLLECTOR_PORT || 8888}`;
  11. }
  12. log(text, ...args) {
  13. console.log(`\x1b[36m[CollectorApi]\x1b[0m ${text}`, ...args);
  14. }
  15. #attachOptions() {
  16. return {
  17. whisperProvider: process.env.WHISPER_PROVIDER || "local",
  18. WhisperModelPref: process.env.WHISPER_MODEL_PREF,
  19. openAiKey: process.env.OPEN_AI_KEY || null,
  20. };
  21. }
  22. async online() {
  23. return await fetch(this.endpoint)
  24. .then((res) => res.ok)
  25. .catch(() => false);
  26. }
  27. async acceptedFileTypes() {
  28. return await fetch(`${this.endpoint}/accepts`)
  29. .then((res) => {
  30. if (!res.ok) throw new Error("failed to GET /accepts");
  31. return res.json();
  32. })
  33. .then((res) => res)
  34. .catch((e) => {
  35. this.log(e.message);
  36. return null;
  37. });
  38. }
  39. async processDocument(filename = "") {
  40. if (!filename) return false;
  41. const data = JSON.stringify({
  42. filename,
  43. options: this.#attachOptions(),
  44. });
  45. return await fetch(`${this.endpoint}/process`, {
  46. method: "POST",
  47. headers: {
  48. "Content-Type": "application/json",
  49. "X-Integrity": this.comkey.sign(data),
  50. "X-Payload-Signer": this.comkey.encrypt(
  51. new EncryptionManager().xPayload
  52. ),
  53. },
  54. body: data,
  55. })
  56. .then((res) => {
  57. if (!res.ok) throw new Error("Response could not be completed");
  58. return res.json();
  59. })
  60. .then((res) => res)
  61. .catch((e) => {
  62. this.log(e.message);
  63. return { success: false, reason: e.message, documents: [] };
  64. });
  65. }
  66. async processLink(link = "") {
  67. if (!link) return false;
  68. const data = JSON.stringify({ link });
  69. return await fetch(`${this.endpoint}/process-link`, {
  70. method: "POST",
  71. headers: {
  72. "Content-Type": "application/json",
  73. "X-Integrity": this.comkey.sign(data),
  74. "X-Payload-Signer": this.comkey.encrypt(
  75. new EncryptionManager().xPayload
  76. ),
  77. },
  78. body: data,
  79. })
  80. .then((res) => {
  81. if (!res.ok) throw new Error("Response could not be completed");
  82. return res.json();
  83. })
  84. .then((res) => res)
  85. .catch((e) => {
  86. this.log(e.message);
  87. return { success: false, reason: e.message, documents: [] };
  88. });
  89. }
  90. async processRawText(textContent = "", metadata = {}) {
  91. const data = JSON.stringify({ textContent, metadata });
  92. return await fetch(`${this.endpoint}/process-raw-text`, {
  93. method: "POST",
  94. headers: {
  95. "Content-Type": "application/json",
  96. "X-Integrity": this.comkey.sign(data),
  97. "X-Payload-Signer": this.comkey.encrypt(
  98. new EncryptionManager().xPayload
  99. ),
  100. },
  101. body: data,
  102. })
  103. .then((res) => {
  104. if (!res.ok) throw new Error("Response could not be completed");
  105. return res.json();
  106. })
  107. .then((res) => res)
  108. .catch((e) => {
  109. this.log(e.message);
  110. return { success: false, reason: e.message, documents: [] };
  111. });
  112. }
  113. // We will not ever expose the document processor to the frontend API so instead we relay
  114. // all requests through the server. You can use this function to directly expose a specific endpoint
  115. // on the document processor.
  116. async forwardExtensionRequest({ endpoint, method, body }) {
  117. return await fetch(`${this.endpoint}${endpoint}`, {
  118. method,
  119. body, // Stringified JSON!
  120. headers: {
  121. "Content-Type": "application/json",
  122. "X-Integrity": this.comkey.sign(body),
  123. "X-Payload-Signer": this.comkey.encrypt(
  124. new EncryptionManager().xPayload
  125. ),
  126. },
  127. })
  128. .then((res) => {
  129. if (!res.ok) throw new Error("Response could not be completed");
  130. return res.json();
  131. })
  132. .then((res) => res)
  133. .catch((e) => {
  134. this.log(e.message);
  135. return { success: false, data: {}, reason: e.message };
  136. });
  137. }
  138. async getLinkContent(link = "", captureAs = "text") {
  139. if (!link) return false;
  140. const data = JSON.stringify({ link, captureAs });
  141. return await fetch(`${this.endpoint}/util/get-link`, {
  142. method: "POST",
  143. headers: {
  144. "Content-Type": "application/json",
  145. "X-Integrity": this.comkey.sign(data),
  146. "X-Payload-Signer": this.comkey.encrypt(
  147. new EncryptionManager().xPayload
  148. ),
  149. },
  150. body: data,
  151. })
  152. .then((res) => {
  153. if (!res.ok) throw new Error("Response could not be completed");
  154. return res.json();
  155. })
  156. .then((res) => res)
  157. .catch((e) => {
  158. this.log(e.message);
  159. return { success: false, content: null };
  160. });
  161. }
  162. }
  163. module.exports.CollectorApi = CollectorApi;