soundcloud.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import async from "async";
  2. import isLoginRequired from "../hooks/loginRequired";
  3. import { useHasPermission } from "../hooks/hasPermission";
  4. // eslint-disable-next-line
  5. import moduleManager from "../../index";
  6. const DBModule = moduleManager.modules.db;
  7. const UtilsModule = moduleManager.modules.utils;
  8. const SoundcloudModule = moduleManager.modules.soundcloud;
  9. const CacheModule = moduleManager.modules.cache;
  10. export default {
  11. /**
  12. * Fetches new SoundCloud API key
  13. *
  14. * @returns {{status: string, data: object}}
  15. */
  16. fetchNewApiKey: useHasPermission("soundcloud.fetchNewApiKey", async function fetchNewApiKey(session, cb) {
  17. this.keepLongJob();
  18. this.publishProgress({
  19. status: "started",
  20. title: "Fetch new SoundCloud API key",
  21. message: "Fetching new SoundCloud API key.",
  22. id: this.toString()
  23. });
  24. await CacheModule.runJob("RPUSH", { key: `longJobs.${session.userId}`, value: this.toString() }, this);
  25. await CacheModule.runJob(
  26. "PUB",
  27. {
  28. channel: "longJob.added",
  29. value: { jobId: this.toString(), userId: session.userId }
  30. },
  31. this
  32. );
  33. SoundcloudModule.runJob("GENERATE_SOUNDCLOUD_API_KEY", {}, this)
  34. .then(response => {
  35. this.log("SUCCESS", "SOUNDCLOUD_FETCH_NEW_API_KEY", `Fetching new API key was successful.`);
  36. this.publishProgress({
  37. status: "success",
  38. message: "Successfully fetched new SoundCloud API key."
  39. });
  40. return cb({
  41. status: "success",
  42. data: { response }
  43. });
  44. })
  45. .catch(async err => {
  46. err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
  47. this.log("ERROR", "SOUNDCLOUD_FETCH_NEW_API_KEY", `Fetching new API key failed. "${err}"`);
  48. this.publishProgress({
  49. status: "error",
  50. message: err
  51. });
  52. return cb({ status: "error", message: err });
  53. });
  54. }),
  55. /**
  56. * Tests SoundCloud API key
  57. *
  58. * @returns {{status: string, data: object}}
  59. */
  60. testApiKey: useHasPermission("soundcloud.testApiKey", async function testApiKey(session, cb) {
  61. this.keepLongJob();
  62. this.publishProgress({
  63. status: "started",
  64. title: "Test SoundCloud API key",
  65. message: "Testing SoundCloud API key.",
  66. id: this.toString()
  67. });
  68. await CacheModule.runJob("RPUSH", { key: `longJobs.${session.userId}`, value: this.toString() }, this);
  69. await CacheModule.runJob(
  70. "PUB",
  71. {
  72. channel: "longJob.added",
  73. value: { jobId: this.toString(), userId: session.userId }
  74. },
  75. this
  76. );
  77. SoundcloudModule.runJob("TEST_SOUNDCLOUD_API_KEY", {}, this)
  78. .then(response => {
  79. this.log(
  80. "SUCCESS",
  81. "SOUNDCLOUD_TEST_API_KEY",
  82. `Testing API key was successful. Response: ${response}.`
  83. );
  84. this.publishProgress({
  85. status: "success",
  86. message: "Successfully tested SoundCloud API key."
  87. });
  88. return cb({
  89. status: "success",
  90. data: { status: response.status }
  91. });
  92. })
  93. .catch(async err => {
  94. err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
  95. this.log("ERROR", "SOUNDCLOUD_TEST_API_KEY", `Testing API key failed. "${err}"`);
  96. this.publishProgress({
  97. status: "error",
  98. message: err
  99. });
  100. return cb({ status: "error", message: err });
  101. });
  102. }),
  103. /**
  104. * Get a Soundcloud artist from ID
  105. *
  106. * @returns {{status: string, data: object}}
  107. */
  108. getArtist: useHasPermission("soundcloud.getArtist", function getArtist(session, userPermalink, cb) {
  109. return SoundcloudModule.runJob("GET_ARTISTS_FROM_PERMALINKS", { userPermalinks: [userPermalink] }, this)
  110. .then(res => {
  111. if (res.artists.length === 0) {
  112. this.log("ERROR", "SOUNDCLOUD_GET_ARTISTS_FROM_PERMALINKS", `Fetching artist failed.`);
  113. return cb({ status: "error", message: "Failed to get artist" });
  114. }
  115. this.log("SUCCESS", "SOUNDCLOUD_GET_ARTISTS_FROM_PERMALINKS", `Fetching artist was successful.`);
  116. return cb({
  117. status: "success",
  118. message: "Successfully fetched Soundcloud artist",
  119. data: res.artists[0]
  120. });
  121. })
  122. .catch(async err => {
  123. err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
  124. this.log("ERROR", "SOUNDCLOUD_GET_ARTISTS_FROM_PERMALINKS", `Fetching artist failed. "${err}"`);
  125. return cb({ status: "error", message: err });
  126. });
  127. }),
  128. /**
  129. * Gets videos, used in the admin youtube page by the AdvancedTable component
  130. *
  131. * @param {object} session - the session object automatically added by the websocket
  132. * @param page - the page
  133. * @param pageSize - the size per page
  134. * @param properties - the properties to return for each news item
  135. * @param sort - the sort object
  136. * @param queries - the queries array
  137. * @param operator - the operator for queries
  138. * @param cb
  139. */
  140. getTracks: useHasPermission(
  141. "admin.view.soundcloudTracks",
  142. async function getTracks(session, page, pageSize, properties, sort, queries, operator, cb) {
  143. async.waterfall(
  144. [
  145. next => {
  146. DBModule.runJob(
  147. "GET_DATA",
  148. {
  149. page,
  150. pageSize,
  151. properties,
  152. sort,
  153. queries,
  154. operator,
  155. modelName: "soundcloudTrack",
  156. blacklistedProperties: [],
  157. specialProperties: {
  158. songId: [
  159. // Fetch songs from songs collection with a matching mediaSource, which we first need to assemble
  160. {
  161. $lookup: {
  162. from: "songs",
  163. let: {
  164. mediaSource: { $concat: ["soundcloud:", { $toString: "$trackId" }] }
  165. },
  166. pipeline: [
  167. {
  168. $match: {
  169. $expr: { $eq: ["$mediaSource", "$$mediaSource"] }
  170. }
  171. }
  172. ],
  173. as: "song"
  174. }
  175. },
  176. // Turn the array of songs returned in the last step into one object, since only one song should have been returned maximum
  177. {
  178. $unwind: {
  179. path: "$song",
  180. preserveNullAndEmptyArrays: true
  181. }
  182. },
  183. // Add new field songId, which grabs the song object's _id and tries turning it into a string
  184. {
  185. $addFields: {
  186. songId: {
  187. $convert: {
  188. input: "$song._id",
  189. to: "string",
  190. onError: "",
  191. onNull: ""
  192. }
  193. }
  194. }
  195. },
  196. // Cleanup, don't return the song object for any further steps
  197. {
  198. $project: {
  199. song: 0
  200. }
  201. }
  202. ]
  203. },
  204. specialQueries: {},
  205. specialFilters: {}
  206. },
  207. this
  208. )
  209. .then(response => {
  210. next(null, response);
  211. })
  212. .catch(err => {
  213. next(err);
  214. });
  215. }
  216. ],
  217. async (err, response) => {
  218. if (err && err !== true) {
  219. err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
  220. this.log("ERROR", "SOUNDCLOUD_GET_TRACKS", `Failed to get SoundCloud tracks. "${err}"`);
  221. return cb({ status: "error", message: err });
  222. }
  223. this.log("SUCCESS", "SOUNDCLOUD_GET_TRACKS", `Fetched SoundCloud tracks successfully.`);
  224. return cb({
  225. status: "success",
  226. message: "Successfully fetched SoundCloud tracks.",
  227. data: response
  228. });
  229. }
  230. );
  231. }
  232. ),
  233. /**
  234. * Get a SoundCloud track
  235. *
  236. * @param {object} session - the session object automatically added by the websocket
  237. * @param identifier - the identifier of the SoundCloud track
  238. * @param createMissing - whether to create/fetch the SoundCloud track if it's missing
  239. * @returns {{status: string, data: object}}
  240. */
  241. getTrack: isLoginRequired(function getTrack(session, identifier, createMissing, cb) {
  242. return SoundcloudModule.runJob("GET_TRACK", { identifier, createMissing }, this)
  243. .then(res => {
  244. this.log("SUCCESS", "SOUNDCLOUD_GET_TRACK", `Fetching track was successful.`);
  245. return cb({ status: "success", message: "Successfully fetched SoundCloud track", data: res.track });
  246. })
  247. .catch(async err => {
  248. err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
  249. this.log("ERROR", "SOUNDCLOUD_GET_TRACK", `Fetching track failed. "${err}"`);
  250. return cb({ status: "error", message: err });
  251. });
  252. })
  253. };