reports.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. 'use strict';
  2. const async = require('async');
  3. const hooks = require('./hooks');
  4. const moduleManager = require("../../index");
  5. const db = moduleManager.modules["db"];
  6. const cache = moduleManager.modules["cache"];
  7. const utils = moduleManager.modules["utils"];
  8. const logger = moduleManager.modules["logger"];
  9. const songs = moduleManager.modules["songs"];
  10. const reportableIssues = [
  11. {
  12. name: 'Video',
  13. reasons: [
  14. 'Doesn\'t exist',
  15. 'It\'s private',
  16. 'It\'s not available in my country'
  17. ]
  18. },
  19. {
  20. name: 'Title',
  21. reasons: [
  22. 'Incorrect',
  23. 'Inappropriate'
  24. ]
  25. },
  26. {
  27. name: 'Duration',
  28. reasons: [
  29. 'Skips too soon',
  30. 'Skips too late',
  31. 'Starts too soon',
  32. 'Skips too late'
  33. ]
  34. },
  35. {
  36. name: 'Artists',
  37. reasons: [
  38. 'Incorrect',
  39. 'Inappropriate'
  40. ]
  41. },
  42. {
  43. name: 'Thumbnail',
  44. reasons: [
  45. 'Incorrect',
  46. 'Inappropriate',
  47. 'Doesn\'t exist'
  48. ]
  49. }
  50. ];
  51. cache.sub('report.resolve', reportId => {
  52. utils.emitToRoom('admin.reports', 'event:admin.report.resolved', reportId);
  53. });
  54. cache.sub('report.create', report => {
  55. utils.emitToRoom('admin.reports', 'event:admin.report.created', report);
  56. });
  57. module.exports = {
  58. /**
  59. * Gets all reports
  60. *
  61. * @param {Object} session - the session object automatically added by socket.io
  62. * @param {Function} cb - gets called with the result
  63. */
  64. index: hooks.adminRequired((session, cb) => {
  65. async.waterfall([
  66. (next) => {
  67. db.models.report.find({ resolved: false }).sort({ released: 'desc' }).exec(next);
  68. }
  69. ], async (err, reports) => {
  70. if (err) {
  71. err = await utils.getError(err);
  72. logger.error("REPORTS_INDEX", `Indexing reports failed. "${err}"`);
  73. return cb({ 'status': 'failure', 'message': err});
  74. }
  75. logger.success("REPORTS_INDEX", "Indexing reports successful.");
  76. cb({ status: 'success', data: reports });
  77. });
  78. }),
  79. /**
  80. * Gets a specific report
  81. *
  82. * @param {Object} session - the session object automatically added by socket.io
  83. * @param {String} reportId - the id of the report to return
  84. * @param {Function} cb - gets called with the result
  85. */
  86. findOne: hooks.adminRequired((session, reportId, cb) => {
  87. async.waterfall([
  88. (next) => {
  89. db.models.report.findOne({ _id: reportId }).exec(next);
  90. }
  91. ], async (err, report) => {
  92. if (err) {
  93. err = await utils.getError(err);
  94. logger.error("REPORTS_FIND_ONE", `Finding report "${reportId}" failed. "${err}"`);
  95. return cb({ 'status': 'failure', 'message': err });
  96. }
  97. logger.success("REPORTS_FIND_ONE", `Finding report "${reportId}" successful.`);
  98. cb({ status: 'success', data: report });
  99. });
  100. }),
  101. /**
  102. * Gets all reports for a songId (_id)
  103. *
  104. * @param {Object} session - the session object automatically added by socket.io
  105. * @param {String} songId - the id of the song to index reports for
  106. * @param {Function} cb - gets called with the result
  107. */
  108. getReportsForSong: hooks.adminRequired((session, songId, cb) => {
  109. async.waterfall([
  110. (next) => {
  111. db.models.report.find({ song: { _id: songId }, resolved: false }).sort({ released: 'desc' }).exec(next);
  112. },
  113. (reports, next) => {
  114. let data = [];
  115. for (let i = 0; i < reports.length; i++) {
  116. data.push(reports[i]._id);
  117. }
  118. next(null, data);
  119. }
  120. ], async (err, data) => {
  121. if (err) {
  122. err = await utils.getError(err);
  123. logger.error("GET_REPORTS_FOR_SONG", `Indexing reports for song "${songId}" failed. "${err}"`);
  124. return cb({ 'status': 'failure', 'message': err});
  125. } else {
  126. logger.success("GET_REPORTS_FOR_SONG", `Indexing reports for song "${songId}" successful.`);
  127. return cb({ status: 'success', data });
  128. }
  129. });
  130. }),
  131. /**
  132. * Resolves a report
  133. *
  134. * @param {Object} session - the session object automatically added by socket.io
  135. * @param {String} reportId - the id of the report that is getting resolved
  136. * @param {Function} cb - gets called with the result
  137. * @param {String} userId - the userId automatically added by hooks
  138. */
  139. resolve: hooks.adminRequired((session, reportId, cb, userId) => {
  140. async.waterfall([
  141. (next) => {
  142. db.models.report.findOne({ _id: reportId }).exec(next);
  143. },
  144. (report, next) => {
  145. if (!report) return next('Report not found.');
  146. report.resolved = true;
  147. report.save(err => {
  148. if (err) next(err.message);
  149. else next();
  150. });
  151. }
  152. ], async (err) => {
  153. if (err) {
  154. err = await utils.getError(err);
  155. logger.error("REPORTS_RESOLVE", `Resolving report "${reportId}" failed by user "${userId}". "${err}"`);
  156. return cb({ 'status': 'failure', 'message': err});
  157. } else {
  158. cache.pub('report.resolve', reportId);
  159. logger.success("REPORTS_RESOLVE", `User "${userId}" resolved report "${reportId}".`);
  160. cb({ status: 'success', message: 'Successfully resolved Report' });
  161. }
  162. });
  163. }),
  164. /**
  165. * Creates a new report
  166. *
  167. * @param {Object} session - the session object automatically added by socket.io
  168. * @param {Object} data - the object of the report data
  169. * @param {Function} cb - gets called with the result
  170. * @param {String} userId - the userId automatically added by hooks
  171. */
  172. create: hooks.loginRequired((session, data, cb, userId) => {
  173. async.waterfall([
  174. (next) => {
  175. db.models.song.findOne({ songId: data.songId }).exec(next);
  176. },
  177. (song, next) => {
  178. if (!song) return next('Song not found.');
  179. songs.getSong(song._id, next);
  180. },
  181. (song, next) => {
  182. if (!song) return next('Song not found.');
  183. delete data.songId;
  184. data.song = {
  185. _id: song._id,
  186. songId: song.songId
  187. }
  188. for (let z = 0; z < data.issues.length; z++) {
  189. if (reportableIssues.filter(issue => { return issue.name == data.issues[z].name; }).length > 0) {
  190. for (let r = 0; r < reportableIssues.length; r++) {
  191. if (reportableIssues[r].reasons.every(reason => data.issues[z].reasons.indexOf(reason) < -1)) {
  192. return cb({ status: 'failure', message: 'Invalid data' });
  193. }
  194. }
  195. } else return cb({ status: 'failure', message: 'Invalid data' });
  196. }
  197. next();
  198. },
  199. (next) => {
  200. let issues = [];
  201. for (let r = 0; r < data.issues.length; r++) {
  202. if (!data.issues[r].reasons.length <= 0) issues.push(data.issues[r]);
  203. }
  204. data.issues = issues;
  205. next();
  206. },
  207. (next) => {
  208. data.createdBy = userId;
  209. data.createdAt = Date.now();
  210. db.models.report.create(data, next);
  211. }
  212. ], async (err, report) => {
  213. if (err) {
  214. err = await utils.getError(err);
  215. logger.error("REPORTS_CREATE", `Creating report for "${data.song._id}" failed by user "${userId}". "${err}"`);
  216. return cb({ 'status': 'failure', 'message': err });
  217. } else {
  218. cache.pub('report.create', report);
  219. logger.success("REPORTS_CREATE", `User "${userId}" created report for "${data.songId}".`);
  220. return cb({ 'status': 'success', 'message': 'Successfully created report' });
  221. }
  222. });
  223. })
  224. };