@jesec/flood 0.0.0-master.fc39f18 → 0.0.0-master.fcbe368

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/CHANGELOG.md +606 -103
  2. package/README.md +134 -44
  3. package/SECURITY.md +27 -0
  4. package/dist/assets/icon_128x128.png +0 -0
  5. package/dist/assets/icon_192x192.png +0 -0
  6. package/dist/assets/icon_256x256.png +0 -0
  7. package/dist/assets/icon_384x384.png +0 -0
  8. package/dist/assets/icon_512x512.png +0 -0
  9. package/dist/assets/icon_96x96.png +0 -0
  10. package/dist/assets/icon_maskable.png +0 -0
  11. package/dist/assets/icon_maskable_180x180.png +0 -0
  12. package/dist/assets/index.html +1 -1
  13. package/dist/assets/manifest.json +35 -7
  14. package/dist/assets/static/css/662.37bdb6f87f387ec14604.css +1 -0
  15. package/dist/assets/static/css/main.82f95f742428b2d09013.css +1 -0
  16. package/dist/assets/static/js/179.74639e0b.chunk.js +1 -0
  17. package/dist/assets/static/js/662.dac28d6b.chunk.js +1 -0
  18. package/dist/assets/static/js/770.1f9989ff.chunk.js +1 -0
  19. package/dist/assets/static/js/996.2a53baf2.chunk.js +1 -0
  20. package/dist/assets/static/js/flag0.bb46ec33.chunk.js +1 -0
  21. package/dist/assets/static/js/flag1.f4c50ec9.chunk.js +1 -0
  22. package/dist/assets/static/js/flag2.b587d880.chunk.js +1 -0
  23. package/dist/assets/static/js/flag3.ef97056e.chunk.js +1 -0
  24. package/dist/assets/static/js/i18n0.07675919.chunk.js +1 -0
  25. package/dist/assets/static/js/i18n1.074e2d5a.chunk.js +1 -0
  26. package/dist/assets/static/js/i18n10.b99f7d09.chunk.js +1 -0
  27. package/dist/assets/static/js/i18n11.21c9a2f0.chunk.js +1 -0
  28. package/dist/assets/static/js/i18n12.804cf4da.chunk.js +1 -0
  29. package/dist/assets/static/js/i18n13.7872bf34.chunk.js +1 -0
  30. package/dist/assets/static/js/i18n14.66c9ebe5.chunk.js +1 -0
  31. package/dist/assets/static/js/i18n15.ea4e07d2.chunk.js +1 -0
  32. package/dist/assets/static/js/i18n16.d9309699.chunk.js +1 -0
  33. package/dist/assets/static/js/i18n17.21e9fc81.chunk.js +1 -0
  34. package/dist/assets/static/js/i18n18.63f43563.chunk.js +1 -0
  35. package/dist/assets/static/js/i18n19.63280231.chunk.js +1 -0
  36. package/dist/assets/static/js/i18n2.4ee01236.chunk.js +1 -0
  37. package/dist/assets/static/js/i18n20.c396e01f.chunk.js +1 -0
  38. package/dist/assets/static/js/i18n21.50b78a18.chunk.js +1 -0
  39. package/dist/assets/static/js/i18n22.f4054a1b.chunk.js +1 -0
  40. package/dist/assets/static/js/i18n23.a1cae032.chunk.js +1 -0
  41. package/dist/assets/static/js/i18n24.5b857889.chunk.js +1 -0
  42. package/dist/assets/static/js/i18n25.6b36bde1.chunk.js +1 -0
  43. package/dist/assets/static/js/i18n26.72ddc962.chunk.js +1 -0
  44. package/dist/assets/static/js/i18n27.f9276181.chunk.js +1 -0
  45. package/dist/assets/static/js/i18n28.950e91ff.chunk.js +1 -0
  46. package/dist/assets/static/js/i18n3.da232d77.chunk.js +1 -0
  47. package/dist/assets/static/js/i18n4.e88e49ab.chunk.js +1 -0
  48. package/dist/assets/static/js/i18n5.e2d59d0d.chunk.js +1 -0
  49. package/dist/assets/static/js/i18n6.483bf024.chunk.js +1 -0
  50. package/dist/assets/static/js/i18n8.434e060c.chunk.js +1 -0
  51. package/dist/assets/static/js/i18n9.193030d4.chunk.js +1 -0
  52. package/dist/assets/static/js/main.5708d913.js +1 -0
  53. package/dist/index.js +131278 -0
  54. package/package.json +212 -132
  55. package/config.js +0 -173
  56. package/dist/assets/android-chrome-192x192.png +0 -0
  57. package/dist/assets/android-chrome-512x512.png +0 -0
  58. package/dist/assets/apple-touch-icon.png +0 -0
  59. package/dist/assets/asset-manifest.json +0 -229
  60. package/dist/assets/browserconfig.xml +0 -9
  61. package/dist/assets/favicon-16x16.png +0 -0
  62. package/dist/assets/favicon-32x32.png +0 -0
  63. package/dist/assets/mstile-144x144.png +0 -0
  64. package/dist/assets/mstile-150x150.png +0 -0
  65. package/dist/assets/mstile-310x150.png +0 -0
  66. package/dist/assets/mstile-310x310.png +0 -0
  67. package/dist/assets/mstile-70x70.png +0 -0
  68. package/dist/assets/static/js/main.537275cb.js +0 -339
  69. package/dist/assets/static/media/ABOUT.d02918c9.md +0 -13
  70. package/dist/assets/static/media/Roboto-500.64e69384.woff +0 -0
  71. package/dist/assets/static/media/Roboto-500.7f8f0146.eot +0 -0
  72. package/dist/assets/static/media/Roboto-500.916656a2.ttf +0 -0
  73. package/dist/assets/static/media/Roboto-500.abd255e8.svg +0 -305
  74. package/dist/assets/static/media/Roboto-700.8d11d1e1.ttf +0 -0
  75. package/dist/assets/static/media/Roboto-700.9c9c164e.svg +0 -310
  76. package/dist/assets/static/media/Roboto-700.c65552c8.eot +0 -0
  77. package/dist/assets/static/media/Roboto-700.ee82bda2.woff +0 -0
  78. package/dist/assets/static/media/Roboto-700italic.1dc5bfed.eot +0 -0
  79. package/dist/assets/static/media/Roboto-700italic.686da014.woff +0 -0
  80. package/dist/assets/static/media/Roboto-700italic.896656dc.ttf +0 -0
  81. package/dist/assets/static/media/Roboto-700italic.cacb9681.svg +0 -325
  82. package/dist/assets/static/media/Roboto-italic.09ed2f27.svg +0 -323
  83. package/dist/assets/static/media/Roboto-italic.c1421604.woff +0 -0
  84. package/dist/assets/static/media/Roboto-italic.c38ecad2.ttf +0 -0
  85. package/dist/assets/static/media/Roboto-italic.f7677a07.eot +0 -0
  86. package/dist/assets/static/media/Roboto-regular.5107f918.eot +0 -0
  87. package/dist/assets/static/media/Roboto-regular.6a307cf2.woff +0 -0
  88. package/dist/assets/static/media/Roboto-regular.81dc9b21.ttf +0 -0
  89. package/dist/assets/static/media/Roboto-regular.bcf2ba9e.svg +0 -308
  90. package/run/db/README.md +0 -3
  91. package/run/temp/README.md +0 -3
  92. package/server/.eslintrc.js +0 -15
  93. package/server/app.js +0 -88
  94. package/server/bin/enforce-prerequisites.js +0 -63
  95. package/server/bin/migrations/fix-is-admin-flag.js +0 -49
  96. package/server/bin/migrations/per-user-rtorrent-instances.js +0 -76
  97. package/server/bin/migrations/run.js +0 -8
  98. package/server/bin/start.js +0 -16
  99. package/server/bin/web-server.js +0 -98
  100. package/server/config/passport.js +0 -36
  101. package/server/constants/clientGatewayServiceEvents.js +0 -12
  102. package/server/constants/diskUsageServiceEvents.js +0 -5
  103. package/server/constants/fileListPropMap.js +0 -34
  104. package/server/constants/historyServiceEvents.js +0 -17
  105. package/server/constants/notificationServiceEvents.js +0 -5
  106. package/server/constants/taxonomyServiceEvents.js +0 -5
  107. package/server/constants/torrentListPropMap.js +0 -247
  108. package/server/constants/torrentServiceEvents.js +0 -5
  109. package/server/constants/transferSummaryPropMap.js +0 -33
  110. package/server/middleware/appendUserServices.js +0 -6
  111. package/server/middleware/booleanCoerce.js +0 -9
  112. package/server/middleware/clientActivityStream.js +0 -150
  113. package/server/middleware/eventStream.js +0 -27
  114. package/server/middleware/requireAdmin.js +0 -6
  115. package/server/models/ClientRequest.js +0 -389
  116. package/server/models/Feed.js +0 -74
  117. package/server/models/Filesystem.js +0 -45
  118. package/server/models/HistoryEra.js +0 -205
  119. package/server/models/ServerEvent.js +0 -32
  120. package/server/models/TemporaryStorage.js +0 -20
  121. package/server/models/Users.js +0 -188
  122. package/server/models/client.js +0 -435
  123. package/server/models/settings.js +0 -138
  124. package/server/routes/api.js +0 -86
  125. package/server/routes/auth.js +0 -213
  126. package/server/routes/client.js +0 -120
  127. package/server/services/BaseService.js +0 -22
  128. package/server/services/clientGatewayService.js +0 -265
  129. package/server/services/clientRequestManager.js +0 -83
  130. package/server/services/diskUsageService.js +0 -155
  131. package/server/services/feedService.js +0 -363
  132. package/server/services/historyService.js +0 -212
  133. package/server/services/index.js +0 -127
  134. package/server/services/notificationService.js +0 -125
  135. package/server/services/taxonomyService.js +0 -133
  136. package/server/services/torrentService.js +0 -283
  137. package/server/util/ajaxUtil.js +0 -21
  138. package/server/util/clientResponseUtil.js +0 -127
  139. package/server/util/fileUtil.js +0 -47
  140. package/server/util/mediainfo.js +0 -38
  141. package/server/util/methodCallUtil.js +0 -28
  142. package/server/util/minifyUtil.js +0 -0
  143. package/server/util/numberUtils.js +0 -6
  144. package/server/util/rTorrentDeserializer.js +0 -109
  145. package/server/util/rTorrentPropMap.js +0 -12
  146. package/server/util/scgiUtil.js +0 -43
  147. package/server/util/torrentFileUtil.js +0 -24
  148. package/server/views/error.pug +0 -6
  149. package/server/views/layout.pug +0 -6
  150. package/shared/config/paths.js +0 -30
  151. package/shared/constants/clientSettingsMap.js +0 -101
  152. package/shared/constants/diffActionTypes.js +0 -7
  153. package/shared/constants/historySnapshotTypes.js +0 -12
  154. package/shared/constants/serverEventTypes.js +0 -19
  155. package/shared/constants/torrentFilePropsMap.js +0 -6
  156. package/shared/constants/torrentPeerPropsMap.js +0 -32
  157. package/shared/constants/torrentStatusMap.js +0 -19
  158. package/shared/constants/torrentTrackerPropsMap.js +0 -6
  159. package/shared/util/formatUtil.js +0 -71
  160. package/shared/util/objectUtil.js +0 -72
  161. package/shared/util/regEx.js +0 -7
  162. package/shared/util/stringUtil.js +0 -16
  163. /package/dist/assets/{safari-pinned-tab.svg → icon.svg} +0 -0
  164. /package/dist/assets/static/{images/flags/ad.png → media/ad.1b24595d.png} +0 -0
  165. /package/dist/assets/static/{images/flags/ae.png → media/ae.4dd8f55e.png} +0 -0
  166. /package/dist/assets/static/{images/flags/af.png → media/af.4ce660eb.png} +0 -0
  167. /package/dist/assets/static/{images/flags/ag.png → media/ag.fd9409e4.png} +0 -0
  168. /package/dist/assets/static/{images/flags/al.png → media/al.a297aacf.png} +0 -0
  169. /package/dist/assets/static/{images/flags/am.png → media/am.c84ee0cf.png} +0 -0
  170. /package/dist/assets/static/{images/flags/ao.png → media/ao.a7c9214e.png} +0 -0
  171. /package/dist/assets/static/{images/flags/ar.png → media/ar.7e57ef92.png} +0 -0
  172. /package/dist/assets/static/{images/flags/at.png → media/at.5aa9728a.png} +0 -0
  173. /package/dist/assets/static/{images/flags/au.png → media/au.155b51d8.png} +0 -0
  174. /package/dist/assets/static/{images/flags/az.png → media/az.63afef5b.png} +0 -0
  175. /package/dist/assets/static/{images/flags/ba.png → media/ba.5ce8f273.png} +0 -0
  176. /package/dist/assets/static/{images/flags/bb.png → media/bb.f369fc62.png} +0 -0
  177. /package/dist/assets/static/{images/flags/bd.png → media/bd.516278fc.png} +0 -0
  178. /package/dist/assets/static/{images/flags/be.png → media/be.08ec4a8d.png} +0 -0
  179. /package/dist/assets/static/{images/flags/bf.png → media/bf.50bfcb31.png} +0 -0
  180. /package/dist/assets/static/{images/flags/bg.png → media/bg.d9346b96.png} +0 -0
  181. /package/dist/assets/static/{images/flags/bh.png → media/bh.f06d5914.png} +0 -0
  182. /package/dist/assets/static/{images/flags/bi.png → media/bi.4923e3a3.png} +0 -0
  183. /package/dist/assets/static/{images/flags/bj.png → media/bj.019fa79b.png} +0 -0
  184. /package/dist/assets/static/{images/flags/bn.png → media/bn.077671e2.png} +0 -0
  185. /package/dist/assets/static/{images/flags/bo.png → media/bo.8fb15fc6.png} +0 -0
  186. /package/dist/assets/static/{images/flags/br.png → media/br.ec051f0c.png} +0 -0
  187. /package/dist/assets/static/{images/flags/bs.png → media/bs.a74a126f.png} +0 -0
  188. /package/dist/assets/static/{images/flags/bt.png → media/bt.4217b804.png} +0 -0
  189. /package/dist/assets/static/{images/flags/bw.png → media/bw.21fe1567.png} +0 -0
  190. /package/dist/assets/static/{images/flags/by.png → media/by.d247fe16.png} +0 -0
  191. /package/dist/assets/static/{images/flags/bz.png → media/bz.98ec59f6.png} +0 -0
  192. /package/dist/assets/static/{images/flags/ca.png → media/ca.25743e11.png} +0 -0
  193. /package/dist/assets/static/{images/flags/cd.png → media/cd.a5bfda53.png} +0 -0
  194. /package/dist/assets/static/{images/flags/cf.png → media/cf.de7d5d92.png} +0 -0
  195. /package/dist/assets/static/{images/flags/cg.png → media/cg.a47b626b.png} +0 -0
  196. /package/dist/assets/static/{images/flags/ch.png → media/ch.445f47a1.png} +0 -0
  197. /package/dist/assets/static/{images/flags/ci.png → media/ci.a6009c5b.png} +0 -0
  198. /package/dist/assets/static/{images/flags/cl.png → media/cl.de1d715e.png} +0 -0
  199. /package/dist/assets/static/{images/flags/cm.png → media/cm.3ce8a86a.png} +0 -0
  200. /package/dist/assets/static/{images/flags/cn.png → media/cn.e6a26073.png} +0 -0
  201. /package/dist/assets/static/{images/flags/co.png → media/co.e9244faa.png} +0 -0
  202. /package/dist/assets/static/{images/flags/cr.png → media/cr.c895e035.png} +0 -0
  203. /package/dist/assets/static/{images/flags/cu.png → media/cu.e486c055.png} +0 -0
  204. /package/dist/assets/static/{images/flags/cv.png → media/cv.a9585acf.png} +0 -0
  205. /package/dist/assets/static/{images/flags/cw.png → media/cw.df13039d.png} +0 -0
  206. /package/dist/assets/static/{images/flags/cy.png → media/cy.b31f43a9.png} +0 -0
  207. /package/dist/assets/static/{images/flags/cz.png → media/cz.8ec5948b.png} +0 -0
  208. /package/dist/assets/static/{images/flags/de.png → media/de.d12f391a.png} +0 -0
  209. /package/dist/assets/static/{images/flags/dj.png → media/dj.154c3580.png} +0 -0
  210. /package/dist/assets/static/{images/flags/dk.png → media/dk.da382fe2.png} +0 -0
  211. /package/dist/assets/static/{images/flags/dm.png → media/dm.f452e6cd.png} +0 -0
  212. /package/dist/assets/static/{images/flags/do.png → media/do.c6bd7637.png} +0 -0
  213. /package/dist/assets/static/{images/flags/dz.png → media/dz.672a69c0.png} +0 -0
  214. /package/dist/assets/static/{images/flags/ec.png → media/ec.349d9bd7.png} +0 -0
  215. /package/dist/assets/static/{images/flags/ee.png → media/ee.2396205f.png} +0 -0
  216. /package/dist/assets/static/{images/flags/eg.png → media/eg.ccbf3f45.png} +0 -0
  217. /package/dist/assets/static/{images/flags/eh.png → media/eh.af65674a.png} +0 -0
  218. /package/dist/assets/static/{images/flags/er.png → media/er.21afb638.png} +0 -0
  219. /package/dist/assets/static/{images/flags/es.png → media/es.2a6eaee4.png} +0 -0
  220. /package/dist/assets/static/{images/flags/et.png → media/et.8beb65c8.png} +0 -0
  221. /package/dist/assets/static/{images/flags/fi.png → media/fi.331f70fd.png} +0 -0
  222. /package/dist/assets/static/{images/flags/fj.png → media/fj.7724d800.png} +0 -0
  223. /package/dist/assets/static/{images/flags/fm.png → media/fm.eeaf71e9.png} +0 -0
  224. /package/dist/assets/static/{images/flags/fr.png → media/fr.5d5ab008.png} +0 -0
  225. /package/dist/assets/static/{images/flags/ga.png → media/ga.77ed474c.png} +0 -0
  226. /package/dist/assets/static/{images/flags/gb.png → media/gb.e00065bf.png} +0 -0
  227. /package/dist/assets/static/{images/flags/gd.png → media/gd.b4522267.png} +0 -0
  228. /package/dist/assets/static/{images/flags/ge.png → media/ge.91a7654d.png} +0 -0
  229. /package/dist/assets/static/{images/flags/gh.png → media/gh.4759f92f.png} +0 -0
  230. /package/dist/assets/static/{images/flags/gm.png → media/gm.81cd9f75.png} +0 -0
  231. /package/dist/assets/static/{images/flags/gn.png → media/gn.9f3d376e.png} +0 -0
  232. /package/dist/assets/static/{images/flags/gq.png → media/gq.e8ad58be.png} +0 -0
  233. /package/dist/assets/static/{images/flags/gr.png → media/gr.26f3ac0b.png} +0 -0
  234. /package/dist/assets/static/{images/flags/gt.png → media/gt.9d81c52e.png} +0 -0
  235. /package/dist/assets/static/{images/flags/gw.png → media/gw.dc906982.png} +0 -0
  236. /package/dist/assets/static/{images/flags/gy.png → media/gy.a4f62b6c.png} +0 -0
  237. /package/dist/assets/static/{images/flags/hk.png → media/hk.56555c3f.png} +0 -0
  238. /package/dist/assets/static/{images/flags/hn.png → media/hn.64ee6aad.png} +0 -0
  239. /package/dist/assets/static/{images/flags/hr.png → media/hr.93ebecd3.png} +0 -0
  240. /package/dist/assets/static/{images/flags/ht.png → media/ht.42ca1596.png} +0 -0
  241. /package/dist/assets/static/{images/flags/hu.png → media/hu.bb30f05d.png} +0 -0
  242. /package/dist/assets/static/{images/flags/id.png → media/id.2cb49f2d.png} +0 -0
  243. /package/dist/assets/static/{images/flags/ie.png → media/ie.b4dd1f19.png} +0 -0
  244. /package/dist/assets/static/{images/flags/il.png → media/il.cd1d1faf.png} +0 -0
  245. /package/dist/assets/static/{images/flags/in.png → media/in.2df03847.png} +0 -0
  246. /package/dist/assets/static/{images/flags/iq.png → media/iq.a9b670ab.png} +0 -0
  247. /package/dist/assets/static/{images/flags/ir.png → media/ir.9a3de085.png} +0 -0
  248. /package/dist/assets/static/{images/flags/is.png → media/is.d88f4fc9.png} +0 -0
  249. /package/dist/assets/static/{images/flags/it.png → media/it.b73713e3.png} +0 -0
  250. /package/dist/assets/static/{images/flags/je.png → media/je.0353f56a.png} +0 -0
  251. /package/dist/assets/static/{images/flags/jm.png → media/jm.20330ef4.png} +0 -0
  252. /package/dist/assets/static/{images/flags/jo.png → media/jo.eb66f1d1.png} +0 -0
  253. /package/dist/assets/static/{images/flags/jp.png → media/jp.63e382ae.png} +0 -0
  254. /package/dist/assets/static/{images/flags/ke.png → media/ke.ab2e43b8.png} +0 -0
  255. /package/dist/assets/static/{images/flags/kg.png → media/kg.2c47c2af.png} +0 -0
  256. /package/dist/assets/static/{images/flags/kh.png → media/kh.4732c810.png} +0 -0
  257. /package/dist/assets/static/{images/flags/ki.png → media/ki.5fba09fd.png} +0 -0
  258. /package/dist/assets/static/{images/flags/km.png → media/km.7bbed3e9.png} +0 -0
  259. /package/dist/assets/static/{images/flags/kn.png → media/kn.a9595a16.png} +0 -0
  260. /package/dist/assets/static/{images/flags/kp.png → media/kp.8a4dc30a.png} +0 -0
  261. /package/dist/assets/static/{images/flags/kr.png → media/kr.5273be1d.png} +0 -0
  262. /package/dist/assets/static/{images/flags/ks.png → media/ks.99f78645.png} +0 -0
  263. /package/dist/assets/static/{images/flags/kw.png → media/kw.af3521bc.png} +0 -0
  264. /package/dist/assets/static/{images/flags/kz.png → media/kz.ea47ef79.png} +0 -0
  265. /package/dist/assets/static/{images/flags/la.png → media/la.78a598d7.png} +0 -0
  266. /package/dist/assets/static/{images/flags/lb.png → media/lb.7a7c15a9.png} +0 -0
  267. /package/dist/assets/static/{images/flags/lc.png → media/lc.6083a4ff.png} +0 -0
  268. /package/dist/assets/static/{images/flags/li.png → media/li.61c564a4.png} +0 -0
  269. /package/dist/assets/static/{images/flags/lk.png → media/lk.6fa85802.png} +0 -0
  270. /package/dist/assets/static/{images/flags/lr.png → media/lr.8063f7db.png} +0 -0
  271. /package/dist/assets/static/{images/flags/ls.png → media/ls.901ddb71.png} +0 -0
  272. /package/dist/assets/static/{images/flags/lt.png → media/lt.9209ace3.png} +0 -0
  273. /package/dist/assets/static/{images/flags/lu.png → media/lu.c9872bc1.png} +0 -0
  274. /package/dist/assets/static/{images/flags/lv.png → media/lv.7bcacf0a.png} +0 -0
  275. /package/dist/assets/static/{images/flags/ly.png → media/ly.2830aa63.png} +0 -0
  276. /package/dist/assets/static/{images/flags/ma.png → media/ma.ce5f697b.png} +0 -0
  277. /package/dist/assets/static/{images/flags/mc.png → media/mc.4bd5d57a.png} +0 -0
  278. /package/dist/assets/static/{images/flags/md.png → media/md.fb4b5bdf.png} +0 -0
  279. /package/dist/assets/static/{images/flags/me.png → media/me.1f1d1772.png} +0 -0
  280. /package/dist/assets/static/{images/flags/mg.png → media/mg.89101bd2.png} +0 -0
  281. /package/dist/assets/static/{images/flags/mh.png → media/mh.ff11dff7.png} +0 -0
  282. /package/dist/assets/static/{images/flags/mk.png → media/mk.8420e604.png} +0 -0
  283. /package/dist/assets/static/{images/flags/ml.png → media/ml.4db47c66.png} +0 -0
  284. /package/dist/assets/static/{images/flags/mm.png → media/mm.8e4ac30a.png} +0 -0
  285. /package/dist/assets/static/{images/flags/mn.png → media/mn.dc1daa04.png} +0 -0
  286. /package/dist/assets/static/{images/flags/mr.png → media/mr.7cbca6d0.png} +0 -0
  287. /package/dist/assets/static/{images/flags/mt.png → media/mt.28a4b863.png} +0 -0
  288. /package/dist/assets/static/{images/flags/mu.png → media/mu.d93db6c7.png} +0 -0
  289. /package/dist/assets/static/{images/flags/mv.png → media/mv.7d026bf1.png} +0 -0
  290. /package/dist/assets/static/{images/flags/mw.png → media/mw.960cd4fb.png} +0 -0
  291. /package/dist/assets/static/{images/flags/mx.png → media/mx.39b78eb2.png} +0 -0
  292. /package/dist/assets/static/{images/flags/my.png → media/my.916a8392.png} +0 -0
  293. /package/dist/assets/static/{images/flags/mz.png → media/mz.facb4ea3.png} +0 -0
  294. /package/dist/assets/static/{images/flags/na.png → media/na.472666a9.png} +0 -0
  295. /package/dist/assets/static/{images/flags/ne.png → media/ne.d774701f.png} +0 -0
  296. /package/dist/assets/static/{images/flags/ng.png → media/ng.7b06a49f.png} +0 -0
  297. /package/dist/assets/static/{images/flags/ni.png → media/ni.7140131c.png} +0 -0
  298. /package/dist/assets/static/{images/flags/nl.png → media/nl.4c04aa96.png} +0 -0
  299. /package/dist/assets/static/{images/flags/no.png → media/no.c19eb00d.png} +0 -0
  300. /package/dist/assets/static/{images/flags/np.png → media/np.54fb4f2f.png} +0 -0
  301. /package/dist/assets/static/{images/flags/nr.png → media/nr.7527cc38.png} +0 -0
  302. /package/dist/assets/static/{images/flags/nz.png → media/nz.738be05b.png} +0 -0
  303. /package/dist/assets/static/{images/flags/om.png → media/om.b25e0a17.png} +0 -0
  304. /package/dist/assets/static/{images/flags/pa.png → media/pa.b28a9059.png} +0 -0
  305. /package/dist/assets/static/{images/flags/pe.png → media/pe.c1fc1d96.png} +0 -0
  306. /package/dist/assets/static/{images/flags/pg.png → media/pg.380115db.png} +0 -0
  307. /package/dist/assets/static/{images/flags/ph.png → media/ph.02199ddc.png} +0 -0
  308. /package/dist/assets/static/{images/flags/pk.png → media/pk.094f9517.png} +0 -0
  309. /package/dist/assets/static/{images/flags/pl.png → media/pl.41521283.png} +0 -0
  310. /package/dist/assets/static/{images/flags/pt.png → media/pt.1f82dc04.png} +0 -0
  311. /package/dist/assets/static/{images/flags/pw.png → media/pw.a26c2316.png} +0 -0
  312. /package/dist/assets/static/{images/flags/py.png → media/py.926c65ed.png} +0 -0
  313. /package/dist/assets/static/{images/flags/qa.png → media/qa.c6a3c20e.png} +0 -0
  314. /package/dist/assets/static/{images/flags/ro.png → media/ro.a36876c9.png} +0 -0
  315. /package/dist/assets/static/{images/flags/rs.png → media/rs.c6629de8.png} +0 -0
  316. /package/dist/assets/static/{images/flags/ru.png → media/ru.a9b948c1.png} +0 -0
  317. /package/dist/assets/static/{images/flags/rw.png → media/rw.e8aecba0.png} +0 -0
  318. /package/dist/assets/static/{images/flags/sa.png → media/sa.859049c8.png} +0 -0
  319. /package/dist/assets/static/{images/flags/sb.png → media/sb.4ad27b27.png} +0 -0
  320. /package/dist/assets/static/{images/flags/sc.png → media/sc.3293efde.png} +0 -0
  321. /package/dist/assets/static/{images/flags/sd.png → media/sd.19c94faa.png} +0 -0
  322. /package/dist/assets/static/{images/flags/se.png → media/se.195b3f93.png} +0 -0
  323. /package/dist/assets/static/{images/flags/sg.png → media/sg.19d81907.png} +0 -0
  324. /package/dist/assets/static/{images/flags/si.png → media/si.367c5443.png} +0 -0
  325. /package/dist/assets/static/{images/flags/sk.png → media/sk.4e5b8a39.png} +0 -0
  326. /package/dist/assets/static/{images/flags/sl.png → media/sl.4b174b1c.png} +0 -0
  327. /package/dist/assets/static/{images/flags/sm.png → media/sm.2cba3dac.png} +0 -0
  328. /package/dist/assets/static/{images/flags/sn.png → media/sn.a4c1041d.png} +0 -0
  329. /package/dist/assets/static/{images/flags/so.png → media/so.b455e3bf.png} +0 -0
  330. /package/dist/assets/static/{images/flags/sr.png → media/sr.5adc1c00.png} +0 -0
  331. /package/dist/assets/static/{images/flags/st.png → media/st.5ae44155.png} +0 -0
  332. /package/dist/assets/static/{images/flags/sv.png → media/sv.43aa6cdf.png} +0 -0
  333. /package/dist/assets/static/{images/flags/sy.png → media/sy.0fbd24f7.png} +0 -0
  334. /package/dist/assets/static/{images/flags/sz.png → media/sz.ff204912.png} +0 -0
  335. /package/dist/assets/static/{images/flags/td.png → media/td.c7aa2a4e.png} +0 -0
  336. /package/dist/assets/static/{images/flags/tg.png → media/tg.857c3bec.png} +0 -0
  337. /package/dist/assets/static/{images/flags/th.png → media/th.683600c7.png} +0 -0
  338. /package/dist/assets/static/{images/flags/tj.png → media/tj.d20c5570.png} +0 -0
  339. /package/dist/assets/static/{images/flags/tl.png → media/tl.5edd8ea7.png} +0 -0
  340. /package/dist/assets/static/{images/flags/tm.png → media/tm.15960215.png} +0 -0
  341. /package/dist/assets/static/{images/flags/tn.png → media/tn.40df718e.png} +0 -0
  342. /package/dist/assets/static/{images/flags/to.png → media/to.c3b054df.png} +0 -0
  343. /package/dist/assets/static/{images/flags/tr.png → media/tr.adeace6d.png} +0 -0
  344. /package/dist/assets/static/{images/flags/tt.png → media/tt.839bd7f1.png} +0 -0
  345. /package/dist/assets/static/{images/flags/tv.png → media/tv.628cae3e.png} +0 -0
  346. /package/dist/assets/static/{images/flags/tw.png → media/tw.4e885914.png} +0 -0
  347. /package/dist/assets/static/{images/flags/tz.png → media/tz.b2f0dc37.png} +0 -0
  348. /package/dist/assets/static/{images/flags/ua.png → media/ua.6b103313.png} +0 -0
  349. /package/dist/assets/static/{images/flags/ug.png → media/ug.c84042fc.png} +0 -0
  350. /package/dist/assets/static/{images/flags/us.png → media/us.8523c31d.png} +0 -0
  351. /package/dist/assets/static/{images/flags/uy.png → media/uy.a943f85e.png} +0 -0
  352. /package/dist/assets/static/{images/flags/uz.png → media/uz.25552673.png} +0 -0
  353. /package/dist/assets/static/{images/flags/va.png → media/va.a29e1b53.png} +0 -0
  354. /package/dist/assets/static/{images/flags/vc.png → media/vc.7480bd37.png} +0 -0
  355. /package/dist/assets/static/{images/flags/ve.png → media/ve.fd4273c2.png} +0 -0
  356. /package/dist/assets/static/{images/flags/vn.png → media/vn.7d2eff1b.png} +0 -0
  357. /package/dist/assets/static/{images/flags/vu.png → media/vu.48b64cf3.png} +0 -0
  358. /package/dist/assets/static/{images/flags/ws.png → media/ws.f3d9202f.png} +0 -0
  359. /package/dist/assets/static/{images/flags/ye.png → media/ye.311a0e50.png} +0 -0
  360. /package/dist/assets/static/{images/flags/za.png → media/za.090a856f.png} +0 -0
  361. /package/dist/assets/static/{images/flags/zm.png → media/zm.8371e197.png} +0 -0
  362. /package/dist/assets/static/{images/flags/zw.png → media/zw.a6809447.png} +0 -0
@@ -1,213 +0,0 @@
1
- const express = require('express');
2
- const joi = require('joi');
3
- const jwt = require('jsonwebtoken');
4
- const passport = require('passport');
5
- const ajaxUtil = require('../util/ajaxUtil');
6
-
7
- const requireAdmin = require('../middleware/requireAdmin');
8
- const config = require('../../config');
9
-
10
- const router = express.Router();
11
- const services = require('../services');
12
- const Users = require('../models/Users');
13
-
14
- const failedLoginResponse = 'Failed login.';
15
-
16
- const setAuthToken = (res, username, isAdmin) => {
17
- const expirationSeconds = 60 * 60 * 24 * 7; // one week
18
- const cookieExpiration = Date.now() + expirationSeconds * 1000;
19
-
20
- // Create token if the password matched and no error was thrown.
21
- const token = jwt.sign({username}, config.secret, {
22
- expiresIn: expirationSeconds,
23
- });
24
-
25
- res.cookie('jwt', token, {expires: new Date(cookieExpiration), httpOnly: true, sameSite: 'Strict'});
26
-
27
- return res.json({
28
- success: true,
29
- token: `JWT ${token}`,
30
- username,
31
- isAdmin,
32
- });
33
- };
34
-
35
- const authValidation = joi.object().keys({
36
- username: joi.string(),
37
- password: joi.string(),
38
- host: joi.string(),
39
- port: joi.string(),
40
- socketPath: joi.string(),
41
- isAdmin: joi.bool(),
42
- });
43
-
44
- router.use('/', (req, res, next) => {
45
- const validation = authValidation.validate(req.body);
46
-
47
- if (!validation.error) {
48
- next();
49
- } else {
50
- res.status(422).json({
51
- message: 'Validation error.',
52
- error: validation.error,
53
- });
54
- }
55
- });
56
-
57
- router.use('/users', passport.authenticate('jwt', {session: false}), requireAdmin);
58
-
59
- router.post('/authenticate', (req, res) => {
60
- if (config.disableUsersAndAuth) {
61
- return setAuthToken(res, Users.getConfigUser()._id, true);
62
- }
63
- const credentials = {
64
- password: req.body.password,
65
- username: req.body.username,
66
- };
67
-
68
- Users.comparePassword(credentials, (isMatch, isAdmin, err) => {
69
- if (isMatch != null && !err) {
70
- return setAuthToken(res, credentials.username, isAdmin);
71
- }
72
-
73
- // Incorrect username or password.
74
- return res.status(401).json({
75
- message: failedLoginResponse,
76
- });
77
- });
78
- });
79
-
80
- // Allow unauthenticated registration if no users are currently registered.
81
- router.use('/register', (req, res, next) => {
82
- Users.initialUserGate({
83
- handleInitialUser: () => {
84
- next();
85
- },
86
- handleSubsequentUser: () => {
87
- passport.authenticate('jwt', {session: false}, (passportReq, passportRes) => {
88
- passportRes.json({username: req.username});
89
- });
90
- },
91
- });
92
- });
93
-
94
- router.post('/register', (req, res) => {
95
- // No user can be registered when disableUsersAndAuth is true
96
- if (config.disableUsersAndAuth) {
97
- // Return 404
98
- res.status(404).send('Not found');
99
- return;
100
- }
101
- // Attempt to save the user
102
- Users.createUser(
103
- {
104
- username: req.body.username,
105
- password: req.body.password,
106
- host: req.body.host,
107
- port: req.body.port,
108
- socketPath: req.body.socketPath,
109
- isAdmin: true,
110
- },
111
- (createUserResponse, createUserError) => {
112
- if (createUserError) {
113
- ajaxUtil.getResponseFn(res)(createUserResponse, createUserError);
114
- return;
115
- }
116
-
117
- setAuthToken(res, req.body.username, true);
118
- },
119
- );
120
- });
121
-
122
- // Allow unauthenticated verification if no users are currently registered.
123
- router.use('/verify', (req, res, next) => {
124
- if (config.disableUsersAndAuth) {
125
- return setAuthToken(res, Users.getConfigUser()._id, true);
126
- }
127
- Users.initialUserGate({
128
- handleInitialUser: () => {
129
- req.initialUser = true;
130
- next();
131
- },
132
- handleSubsequentUser: () => {
133
- req.initialUser = false;
134
- passport.authenticate('jwt', {session: false})(req, res, next);
135
- },
136
- });
137
- });
138
-
139
- router.get('/verify', (req, res) => {
140
- res.json({
141
- initialUser: req.initialUser,
142
- username: req.user && req.user.username,
143
- isAdmin: req.user && req.user.isAdmin,
144
- });
145
- });
146
-
147
- // All subsequent routes are protected.
148
- router.use('/', passport.authenticate('jwt', {session: false}));
149
-
150
- router.get('/logout', (req, res) => {
151
- res.clearCookie('jwt').send();
152
- });
153
-
154
- router.use('/users', (req, res, next) => {
155
- // No operation on user when disableUsersAndAuth is true
156
- if (config.disableUsersAndAuth) {
157
- // Return 404
158
- res.status(404).send('Not found');
159
- return;
160
- }
161
-
162
- if (req.user && req.user.isAdmin) {
163
- next();
164
- return;
165
- }
166
-
167
- res.status(401).send('Not authorized');
168
- });
169
-
170
- router.get('/users', (req, res) => {
171
- Users.listUsers(ajaxUtil.getResponseFn(res));
172
- });
173
-
174
- router.delete('/users/:username', (req, res) => {
175
- Users.removeUser(req.params.username, ajaxUtil.getResponseFn(res));
176
- services.destroyUserServices(req.user);
177
- });
178
-
179
- router.patch('/users/:username', (req, res) => {
180
- const {username} = req.params;
181
- const userPatch = req.body;
182
-
183
- if (!userPatch.socketPath) {
184
- userPatch.socketPath = null;
185
- } else {
186
- userPatch.host = null;
187
- userPatch.port = null;
188
- }
189
-
190
- Users.updateUser(username, userPatch, () => {
191
- Users.lookupUser({username}, (err, user) => {
192
- if (err) return req.status(500).json({error: err});
193
- services.updateUserServices(user);
194
- res.send();
195
- });
196
- });
197
- });
198
-
199
- router.put('/users', (req, res) => {
200
- Users.createUser(
201
- {
202
- username: req.body.username,
203
- password: req.body.password,
204
- host: req.body.host,
205
- port: req.body.port,
206
- socketPath: req.body.socketPath,
207
- isAdmin: req.body.isAdmin,
208
- },
209
- ajaxUtil.getResponseFn(res),
210
- );
211
- });
212
-
213
- module.exports = router;
@@ -1,120 +0,0 @@
1
- const express = require('express');
2
- const multer = require('multer');
3
-
4
- const ajaxUtil = require('../util/ajaxUtil');
5
- const booleanCoerce = require('../middleware/booleanCoerce');
6
- const client = require('../models/client');
7
-
8
- const router = express.Router();
9
-
10
- const upload = multer({
11
- dest: 'uploads/',
12
- limits: {fileSize: 10000000},
13
- storage: multer.memoryStorage(),
14
- });
15
-
16
- router.get('/connection-test', (req, res) => {
17
- req.services.clientGatewayService
18
- .testGateway()
19
- .then(() => {
20
- res.status(200).json({isConnected: true});
21
- })
22
- .catch(() => {
23
- res.status(500).json({isConnected: false});
24
- });
25
- });
26
-
27
- router.post('/connection-test', (req, res) => {
28
- req.services.clientGatewayService
29
- .testGateway(req.body)
30
- .then(() => {
31
- res.status(200).json({isConnected: true});
32
- })
33
- .catch(() => {
34
- res.status(500).json({isConnected: false});
35
- });
36
- });
37
-
38
- router.post('/add', (req, res) => {
39
- client.addUrls(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
40
- });
41
-
42
- router.post('/add-files', upload.array('torrents'), booleanCoerce('isBasePath'), (req, res) => {
43
- client.addFiles(req.user, req.services, req, ajaxUtil.getResponseFn(res));
44
- });
45
-
46
- router.get('/settings', (req, res) => {
47
- client.getSettings(req.user, req.services, req.query, ajaxUtil.getResponseFn(res));
48
- });
49
-
50
- router.patch('/settings', (req, res) => {
51
- client.setSettings(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
52
- });
53
-
54
- router.put('/settings/speed-limits', (req, res) => {
55
- client.setSpeedLimits(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
56
- });
57
-
58
- router.post('/start', (req, res) => {
59
- client.startTorrent(req.user, req.services, req.body.hashes, ajaxUtil.getResponseFn(res));
60
- });
61
-
62
- router.post('/stop', (req, res) => {
63
- client.stopTorrent(req.user, req.services, req.body.hashes, ajaxUtil.getResponseFn(res));
64
- });
65
-
66
- router.post('/torrent-details', (req, res) => {
67
- client.getTorrentDetails(req.user, req.services, req.body.hash, ajaxUtil.getResponseFn(res));
68
- });
69
-
70
- router.patch('/torrents/:hash/priority', (req, res) => {
71
- client.setPriority(req.user, req.services, req.params.hash, req.body, ajaxUtil.getResponseFn(res));
72
- });
73
-
74
- router.patch('/torrents/:hash/file-priority', (req, res) => {
75
- client.setFilePriority(req.user, req.services, req.params.hash, req.body, ajaxUtil.getResponseFn(res));
76
- });
77
-
78
- router.post('/torrents/check-hash', (req, res) => {
79
- client.checkHash(req.user, req.services, req.body.hash, ajaxUtil.getResponseFn(res));
80
- });
81
-
82
- router.post('/torrents/move', (req, res) => {
83
- client.moveTorrents(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
84
- });
85
-
86
- router.post('/torrents/delete', (req, res) => {
87
- const {deleteData, hash: hashes} = req.body;
88
- const callback = ajaxUtil.getResponseFn(res);
89
-
90
- req.services.clientGatewayService
91
- .removeTorrents({hashes, deleteData})
92
- .then(callback)
93
- .catch((err) => {
94
- callback(null, err);
95
- });
96
- });
97
-
98
- router.patch('/torrents/taxonomy', (req, res) => {
99
- client.setTaxonomy(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
100
- });
101
-
102
- router.patch('/torrents/tracker', (req, res) => {
103
- client.setTracker(req.user, req.services, req.body, ajaxUtil.getResponseFn(res));
104
- });
105
-
106
- router.get('/methods.json', (req, res) => {
107
- const {type} = req.query;
108
- const {args} = req.query;
109
- let method = 'system.listMethods';
110
-
111
- if (type === 'help') {
112
- method = 'system.methodHelp';
113
- } else if (type === 'signature') {
114
- method = 'system.methodSignature';
115
- }
116
-
117
- client.listMethods(req.user, req.services, method, args, ajaxUtil.getResponseFn(res));
118
- });
119
-
120
- module.exports = router;
@@ -1,22 +0,0 @@
1
- const EventEmitter = require('events');
2
-
3
- class BaseService extends EventEmitter {
4
- constructor(user, services, ...eventEmitterConfig) {
5
- super(...eventEmitterConfig);
6
- if (!user || !user._id) throw new Error('Missing user ID');
7
- this.user = user;
8
- this.services = services;
9
- }
10
-
11
- destroy() {
12
- delete this.services;
13
- delete this.user;
14
- }
15
-
16
- updateUser(user, services) {
17
- this.user = user;
18
- this.services = services;
19
- }
20
- }
21
-
22
- module.exports = BaseService;
@@ -1,265 +0,0 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
-
4
- const BaseService = require('./BaseService');
5
- const clientGatewayServiceEvents = require('../constants/clientGatewayServiceEvents');
6
- const fileListPropMap = require('../constants/fileListPropMap');
7
- const methodCallUtil = require('../util/methodCallUtil');
8
- const scgiUtil = require('../util/scgiUtil');
9
-
10
- const fileListMethodCallConfig = methodCallUtil.getMethodCallConfigFromPropMap(fileListPropMap, ['pathComponents']);
11
-
12
- class ClientGatewayService extends BaseService {
13
- constructor(...serviceConfig) {
14
- super(...serviceConfig);
15
-
16
- this.hasError = null;
17
- this.torrentListReducers = [];
18
- this.processClientRequestError = this.processClientRequestError.bind(this);
19
- this.processClientRequestSuccess = this.processClientRequestSuccess.bind(this);
20
- }
21
-
22
- /**
23
- * Adds a reducer to be applied when processing the torrent list.
24
- *
25
- * @param {Object} reducer - The reducer object
26
- * @param {string} reducer.key - The key of the reducer, to be applied to the
27
- * torrent list object.
28
- * @param {function} reducer.reduce - The actual reducer. This will recevie
29
- * the entire processed torrent list response and it should return it own
30
- * processed value, to be assigned to the provided key.
31
- */
32
- addTorrentListReducer(reducer = {}) {
33
- if (typeof reducer.key !== 'string') {
34
- throw new Error('reducer.key must be a string.');
35
- }
36
-
37
- if (typeof reducer.reduce !== 'function') {
38
- throw new Error('reducer.reduce must be a function.');
39
- }
40
-
41
- this.torrentListReducers.push(reducer);
42
- }
43
-
44
- removeTorrents(options = {hashes: [], deleteData: false}) {
45
- const methodCalls = options.hashes.reduce((accumulator, hash, index) => {
46
- let eraseFileMethodCallIndex = index;
47
-
48
- // If we're deleting files, we grab each torrents' file list before we
49
- // remove them.
50
- if (options.deleteData) {
51
- // We offset the indices of these method calls so that we know exactly
52
- // where to retrieve the responses in the future.
53
- const directoryBaseMethodCallIndex = index + options.hashes.length;
54
- // We also need to ensure that the erase method call occurs after
55
- // our request for information.
56
- eraseFileMethodCallIndex = index + options.hashes.length * 2;
57
-
58
- accumulator[index] = {
59
- methodName: 'f.multicall',
60
- params: [hash, ''].concat(fileListMethodCallConfig.methodCalls),
61
- };
62
-
63
- accumulator[directoryBaseMethodCallIndex] = {
64
- methodName: 'd.directory_base',
65
- params: [hash],
66
- };
67
- }
68
-
69
- accumulator[eraseFileMethodCallIndex] = {
70
- methodName: 'd.erase',
71
- params: [hash],
72
- };
73
-
74
- return accumulator;
75
- }, []);
76
-
77
- return this.services.clientRequestManager
78
- .methodCall('system.multicall', [methodCalls])
79
- .then((response) => {
80
- if (options.deleteData) {
81
- const torrentCount = options.hashes.length;
82
- const filesToDelete = options.hashes.reduce((accumulator, hash, hashIndex) => {
83
- const fileList = response[hashIndex][0];
84
- const directoryBase = response[hashIndex + torrentCount][0];
85
-
86
- const torrentFilesToDelete = fileList.reduce((fileListAccumulator, file) => {
87
- // We only look at the first path component returned because
88
- // if it's a directory within the torrent, then we'll remove
89
- // the entire directory.
90
- const filePath = path.join(directoryBase, file[0][0]);
91
-
92
- // filePath might be a directory, so it may have already been
93
- // added. If not, we add it.
94
- if (!fileListAccumulator.includes(filePath)) {
95
- fileListAccumulator.push(filePath);
96
- }
97
-
98
- return fileListAccumulator;
99
- }, []);
100
-
101
- return accumulator.concat(torrentFilesToDelete);
102
- }, []);
103
-
104
- filesToDelete.forEach((file) => {
105
- try {
106
- if (fs.lstatSync(file).isDirectory()) {
107
- fs.rmdirSync(file, {recursive: true});
108
- } else {
109
- fs.unlinkSync(file);
110
- }
111
- } catch (error) {
112
- console.error(`Error deleting file: ${file}\n${error}`);
113
- }
114
- });
115
- }
116
-
117
- this.emit(clientGatewayServiceEvents.TORRENTS_REMOVED);
118
-
119
- return response;
120
- })
121
- .catch(this.processClientError);
122
- }
123
-
124
- /**
125
- * Sends a multicall request to rTorrent with the requested method calls.
126
- *
127
- * @param {Object} options - An object of options...
128
- * @param {Array} options.methodCalls - An array of strings representing
129
- * method calls, which the client uses to retrieve details.
130
- * @param {Array} options.propLabels - An array of strings that are used as
131
- * keys for the transformed torrent details.
132
- * @param {Array} options.valueTransformations - An array of functions that
133
- * will be called with the values as returned by the client. These return
134
- * values will be assigned to the key from the propLabels array.
135
- * @return {Promise} - Resolves with the processed client response or rejects
136
- * with the processed client error.
137
- */
138
- fetchTorrentList(options) {
139
- return this.services.clientRequestManager
140
- .methodCall('d.multicall2', ['', 'main'].concat(options.methodCalls))
141
- .then(this.processClientRequestSuccess)
142
- .then((torrents) => this.processTorrentListResponse(torrents, options))
143
- .catch(this.processClientRequestError);
144
- }
145
-
146
- fetchTransferSummary(options) {
147
- const methodCalls = options.methodCalls.map((methodName) => ({methodName, params: []}));
148
-
149
- return this.services.clientRequestManager
150
- .methodCall('system.multicall', [methodCalls])
151
- .then(this.processClientRequestSuccess)
152
- .then((transferRate) => this.processTransferRateResponse(transferRate, options))
153
- .catch(this.processClientRequestError);
154
- }
155
-
156
- processClientRequestSuccess(response) {
157
- if (this.hasError == null || this.hasError === true) {
158
- this.hasError = false;
159
- this.emit(clientGatewayServiceEvents.CLIENT_CONNECTION_STATE_CHANGE);
160
- }
161
-
162
- return response;
163
- }
164
-
165
- processClientRequestError(error) {
166
- if (!this.hasError) {
167
- this.hasError = true;
168
- this.emit(clientGatewayServiceEvents.CLIENT_CONNECTION_STATE_CHANGE);
169
- }
170
- throw error;
171
- }
172
-
173
- /**
174
- * After rTorrent responds with the requested torrent details, we construct
175
- * an object with hashes as keys and processed details as values.
176
- *
177
- * @param {Array} response - The array of all torrents and their details.
178
- * @param {Object} options - An object of options that instruct us how to
179
- * process the client's response.
180
- * @param {Array} options.propLabels - An array of strings that map to the
181
- * method call. These are the keys of the torrent details.
182
- * @param {Array} options.valueTransformations - An array of functions that
183
- * transform the detail from the client's response.
184
- * @return {Object} - An object that represents all torrents with hashes as
185
- * keys, each value being an object of detail labels and values.
186
- */
187
- processTorrentListResponse(torrentList, options) {
188
- this.emit(clientGatewayServiceEvents.PROCESS_TORRENT_LIST_START);
189
-
190
- // We map the array of details to objects with sensibly named keys. We want
191
- // to return an object with torrent hashes as keys and an object of torrent
192
- // details as values.
193
- const processedTorrentList = torrentList.reduce(
194
- (listAccumulator, torrentDetailValues) => {
195
- // Transform the array of torrent detail values to an object with
196
- // sensibly named keys.
197
- const processedTorrentDetailValues = torrentDetailValues.reduce((valueAccumulator, value, valueIndex) => {
198
- const key = options.propLabels[valueIndex];
199
- const transformValue = options.valueTransformations[valueIndex];
200
-
201
- valueAccumulator[key] = transformValue(value);
202
- return valueAccumulator;
203
- }, {});
204
-
205
- // Assign values from external reducers to the torrent list object.
206
- this.torrentListReducers.forEach((reducer) => {
207
- const {key, reduce} = reducer;
208
-
209
- processedTorrentDetailValues[key] = reduce(processedTorrentDetailValues);
210
- });
211
-
212
- listAccumulator.torrents[processedTorrentDetailValues.hash] = processedTorrentDetailValues;
213
-
214
- this.emit(clientGatewayServiceEvents.PROCESS_TORRENT, processedTorrentDetailValues);
215
-
216
- return listAccumulator;
217
- },
218
- {torrents: {}},
219
- );
220
-
221
- // Provide the number of torrents.
222
- processedTorrentList.length = torrentList.length;
223
- // Provide a unique ID for this specific torrent list.
224
- processedTorrentList.id = Date.now();
225
-
226
- this.emit(clientGatewayServiceEvents.PROCESS_TORRENT_LIST_END, processedTorrentList);
227
-
228
- return processedTorrentList;
229
- }
230
-
231
- processTransferRateResponse(transferRate = [], options) {
232
- this.emit(clientGatewayServiceEvents.PROCESS_TRANSFER_RATE_START);
233
-
234
- return transferRate.reduce((accumulator, value, index) => {
235
- const key = options.propLabels[index];
236
- const transformValue = options.valueTransformations[index];
237
-
238
- accumulator[key] = transformValue(value);
239
-
240
- return accumulator;
241
- }, {});
242
- }
243
-
244
- testGateway(clientSettings) {
245
- if (!clientSettings) {
246
- return this.services.clientRequestManager
247
- .methodCall('system.methodExist', ['system.multicall'])
248
- .then(this.processClientRequestSuccess)
249
- .catch(this.processClientRequestError);
250
- }
251
-
252
- return scgiUtil.methodCall(
253
- {
254
- socket: clientSettings.socket,
255
- socketPath: clientSettings.socketPath,
256
- port: clientSettings.port,
257
- host: clientSettings.host,
258
- },
259
- 'system.methodExist',
260
- ['system.multicall'],
261
- );
262
- }
263
- }
264
-
265
- module.exports = ClientGatewayService;
@@ -1,83 +0,0 @@
1
- const BaseService = require('./BaseService');
2
- const scgiUtil = require('../util/scgiUtil');
3
-
4
- class ClientRequestManager extends BaseService {
5
- constructor(...serviceConfig) {
6
- super(...serviceConfig);
7
-
8
- this.isRequestPending = false;
9
- this.lastResponseTimestamp = 0;
10
- this.pendingRequests = [];
11
-
12
- this.sendDefferedMethodCall = this.sendDefferedMethodCall.bind(this);
13
- this.sendMethodCall = this.sendMethodCall.bind(this);
14
- this.methodCall = this.methodCall.bind(this);
15
- }
16
-
17
- handleRequestEnd() {
18
- this.isRequestPending = false;
19
-
20
- // We avoid initiating any deffered requests until at least 250ms have
21
- // since the previous response.
22
- const currentTimestamp = Date.now();
23
- const timeSinceLastResponse = currentTimestamp - this.lastResponseTimestamp;
24
-
25
- if (timeSinceLastResponse <= 250) {
26
- const delay = 250 - timeSinceLastResponse;
27
- setTimeout(this.sendDefferedMethodCall, delay);
28
- this.lastResponseTimestamp = currentTimestamp + delay;
29
- } else {
30
- this.sendDefferedMethodCall();
31
- this.lastResponseTimestamp = currentTimestamp;
32
- }
33
- }
34
-
35
- sendDefferedMethodCall() {
36
- if (this.pendingRequests.length > 0) {
37
- this.isRequestPending = true;
38
-
39
- const nextRequest = this.pendingRequests.shift();
40
-
41
- this.sendMethodCall(nextRequest.methodName, nextRequest.parameters)
42
- .then(nextRequest.resolve)
43
- .catch(nextRequest.reject);
44
- }
45
- }
46
-
47
- sendMethodCall(methodName, parameters) {
48
- const connectionMethod = {
49
- host: this.user.host,
50
- port: this.user.port,
51
- socketPath: this.user.socketPath,
52
- };
53
-
54
- return scgiUtil
55
- .methodCall(connectionMethod, methodName, parameters)
56
- .then((response) => {
57
- this.handleRequestEnd();
58
- return response;
59
- })
60
- .catch((error) => {
61
- this.handleRequestEnd();
62
- throw error;
63
- });
64
- }
65
-
66
- methodCall(methodName, parameters) {
67
- // We only allow one request at a time.
68
- if (this.isRequestPending) {
69
- return new Promise((resolve, reject) => {
70
- this.pendingRequests.push({
71
- methodName,
72
- parameters,
73
- resolve,
74
- reject,
75
- });
76
- });
77
- }
78
- this.isRequestPending = true;
79
- return this.sendMethodCall(methodName, parameters);
80
- }
81
- }
82
-
83
- module.exports = ClientRequestManager;