Advertisement
Guest User

Untitled

a guest
Feb 29th, 2024
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.48 KB | None | 0 0
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.MoonlinkNode = void 0;
  4. const MoonlinkWebSocket_1 = require("../@Services/MoonlinkWebSocket");
  5. const index_1 = require("../../index");
  6. class MoonlinkNode {
  7. _manager = index_1.Structure.manager;
  8. reconnectTimeout;
  9. reconnectAttempts = 1;
  10. retryAmount = 6;
  11. retryDelay = 120000;
  12. resumeStatus = false;
  13. host;
  14. identifier;
  15. password;
  16. port;
  17. secure;
  18. regions;
  19. http;
  20. rest;
  21. info = {};
  22. version;
  23. resume = index_1.Structure.manager.options?.resume;
  24. resumed;
  25. autoResume = index_1.Structure.manager.options?.autoResume;
  26. resumeTimeout = 30000;
  27. sessionId;
  28. socket;
  29. state = "DISCONNECTED";
  30. stats = {};
  31. calls = 0;
  32. constructor(node) {
  33. this.check(node);
  34. this.host = node.host;
  35. this.identifier = node.identifier || null;
  36. this.password = node.password ? node.password : "youshallnotpass";
  37. this.port = node.port ? node.port : node.secure == true ? 443 : 80;
  38. this.secure = node.secure || false;
  39. this.regions = node.regions;
  40. this.http = `http${node.secure ? "s" : ""}://${this.address}/v4/`;
  41. this.rest = new (index_1.Structure.get("MoonlinkRestFul"))(this);
  42. this.connect();
  43. }
  44. get address() {
  45. return `${this.host}:${this.port}`;
  46. }
  47. check(node) {
  48. if (typeof node.host !== "string" && typeof node.host !== "undefined")
  49. throw new Error('@Moonlink(Nodes) - "host" option is not configured correctly');
  50. if (typeof node.password !== "string" &&
  51. typeof node.password !== "undefined")
  52. throw new Error('@Moonlink(Nodes) - the option "password" is not set correctly');
  53. if ((node.port && typeof node.port !== "number") ||
  54. node.port > 65535 ||
  55. node.port < 0)
  56. throw new Error('@Moonlink(Nodes) - the "port" option is not set correctly');
  57. if (typeof node.retryAmount !== "undefined" &&
  58. typeof node.retryAmount !== "number")
  59. throw new Error('@Moonlink(Nodes) - the "retryAmount" option is not set correctly');
  60. if (typeof node.retryDelay !== "undefined" &&
  61. typeof node.retryDelay !== "number")
  62. throw new Error('@Moonlink(Nodes) - the "retryDelay" option is not set correctly');
  63. }
  64. request(endpoint, params) {
  65. this.calls++;
  66. return this.rest.get(`${endpoint}?${params}`);
  67. }
  68. async connect() {
  69. if (this.state == "CONNECTED" || this.state == "READY")
  70. return;
  71. this.state = "CONNECTING";
  72. let headers = {
  73. Authorization: this.password,
  74. "User-Id": this._manager.options.clientId,
  75. "Client-Name": this._manager.options.clientName
  76. };
  77. if (this.resume)
  78. headers["Session-Id"] = index_1.Structure.db.get(`sessionId.${this.identifier ?? this.host.replace(/\./g, "-")}`);
  79. this.socket = new MoonlinkWebSocket_1.MoonlinkWebSocket(`ws${this.secure ? "s" : ""}://${this.address}/v4/websocket`, { headers });
  80. this.socket.on("open", this.open.bind(this));
  81. this.socket.on("close", this.close.bind(this));
  82. this.socket.on("message", this.message.bind(this));
  83. this.socket.on("error", this.error.bind(this));
  84. }
  85. open() {
  86. if (this.reconnectTimeout)
  87. clearTimeout(this.reconnectTimeout);
  88. this._manager.emit("debug", `@Moonlink(Node) - The Node ${this.identifier ?? this.host} has been connected successfully`);
  89. this._manager.emit("nodeCreate", this);
  90. this.state = "CONNECTED";
  91. }
  92. reconnect() {
  93. if (this.reconnectAttempts >= this.retryAmount) {
  94. this._manager.emit("debug", `@Moonlink(Node) - Node ${this.identifier ?? this.host} was destroyed due to inactivity, attempts to reconnect were failed`);
  95. this._manager.emit("nodeDestroy", this);
  96. this.socket.close(1000, "destroy");
  97. this.socket.removeAllListeners();
  98. }
  99. else {
  100. this.reconnectTimeout = setTimeout(() => {
  101. this.socket.removeAllListeners();
  102. this.socket = null;
  103. this.state = "RECONNECTING";
  104. this._manager.emit("nodeReconnect", this);
  105. this.connect();
  106. this._manager.emit("debug", `@Moonlink(Node) - We are trying to reconnect node ${this.identifier ?? this.host}, attempted number ${this.reconnectAttempts}
  107. `);
  108. if (this.getAllPlayers.length &&
  109. this._manager.options?.switchPlayersAnotherNode)
  110. this.movePlayers();
  111. this.reconnectAttempts++;
  112. }, this.retryDelay);
  113. }
  114. }
  115. close(code, reason) {
  116. if (code !== 1000 || reason !== "destroy")
  117. this.reconnect();
  118. this._manager.emit("debug", `@Moonlink(Node) - The node connection ${this.identifier ?? this.host} has been closed`);
  119. this._manager.emit("nodeClose", this, code, reason);
  120. this.getAllPlayers.forEach(player => {
  121. player.playing = false;
  122. });
  123. this.state = "DISCONNECTED";
  124. }
  125. error(error) {
  126. if (!error)
  127. return;
  128. this._manager.emit("nodeError", this, error);
  129. this._manager.emit("debug", `@Moonlink(Nodes) - The ${this.identifier ?? this.host} an error has occurred:
  130. ${error}`);
  131. }
  132. async message(data) {
  133. if (Array.isArray(data))
  134. data = Buffer.concat(data);
  135. else if (data instanceof ArrayBuffer)
  136. data = Buffer.from(data);
  137. let payload = JSON.parse(data.toString("utf8"));
  138. if (!payload.op)
  139. return;
  140. this._manager.emit("nodeRaw", this, payload);
  141. switch (payload.op) {
  142. case "ready":
  143. this.sessionId = payload.sessionId;
  144. this.resume
  145. ? index_1.Structure.db.set(`sessionId.${this.identifier ?? this.host.replace(/\./g, "-")}`, this.sessionId)
  146. : null;
  147. this.resumed = payload.resumed;
  148. this.rest.setSessionId(this.sessionId);
  149. this.state = "READY";
  150. if (!this._manager.initiated && !this.resumed) {
  151. index_1.Structure.db.delete("queue");
  152. index_1.Structure.db.delete("players");
  153. }
  154. this._manager.emit("debug", `@Moonlink(Node) - ${this.resumed ? ` session was resumed,` : ``} session is currently ${this.sessionId}`);
  155. this._manager.emit("nodeReady", this, this.sessionId, this.resumed);
  156. if (this.resume) {
  157. this.rest.patch(`sessions/${this.sessionId}`, {
  158. data: {
  159. resuming: this.resume,
  160. timeout: this.resumeTimeout
  161. }
  162. });
  163. this._manager.emit("debug", `@Moonlink(Nodes) - Resuming configured`);
  164. }
  165. this.version = await this.rest.getVersion();
  166. this.info = await this.rest.getInfo();
  167. if (this.autoResume) {
  168. let resumePlayers = this.getAllPlayers;
  169. for (const resumePlayer of resumePlayers) {
  170. resumePlayer.restart();
  171. }
  172. }
  173. if (this.resumed) {
  174. const resumedPlayers = await this.rest.get(`sessions/${this.sessionId}/players`);
  175. for (const resumedPlayer of resumedPlayers) {
  176. const previousInfosPlayer = index_1.Structure.db.get(`players.${resumedPlayer.guildId}`) || {};
  177. const player = this._manager.players.create({
  178. guildId: resumedPlayer.guildId,
  179. voiceChannel: previousInfosPlayer.voiceChannel,
  180. textChannel: previousInfosPlayer.textChannel,
  181. volume: previousInfosPlayer.volume,
  182. loop: previousInfosPlayer.loop,
  183. autoPlay: previousInfosPlayer.autoPlay,
  184. autoLeave: previousInfosPlayer.autoLeave,
  185. node: this.identifier ?? this.host,
  186. notBackup: true
  187. });
  188. player.previous = previousInfosPlayer.previous;
  189. if (resumedPlayer.track) {
  190. const track = new (index_1.Structure.get("MoonlinkTrack"))(resumedPlayer.track);
  191. player.current = track;
  192. player.current.position =
  193. resumedPlayer.state.position;
  194. await player.restart();
  195. player.playing = true;
  196. player.connected = true;
  197. }
  198. }
  199. this._manager.emit("nodeResumed", this, resumedPlayers);
  200. }
  201. break;
  202. case "stats":
  203. delete payload.op;
  204. this.stats = { ...payload };
  205. break;
  206. case "playerUpdate":
  207. let player = this._manager.players.get(payload.guildId);
  208. if (!player)
  209. return;
  210. player.ping = payload.state.ping;
  211. if (!player.current)
  212. return;
  213. player.current.position = payload.state.position;
  214. player.current.time = payload.state.time;
  215. break;
  216. case "event":
  217. this.handleEvent(payload);
  218. break;
  219. default:
  220. this._manager.emit("nodeError", this, new Error(`@Moonlink(Nodes) - Unexpected op "${payload.op}" with data: ${payload}`));
  221. }
  222. }
  223. async handleEvent(payload) {
  224. if (!payload)
  225. return;
  226. if (!payload.guildId)
  227. return;
  228. if (!this._manager.players.has(payload.guildId))
  229. return;
  230. let player = this._manager.players.get(payload.guildId);
  231. switch (payload.type) {
  232. case "TrackStartEvent": {
  233. let current = player.current;
  234. if (!current)
  235. current = new (index_1.Structure.get("MoonlinkTrack"))(payload.track);
  236. player.playing = true;
  237. player.paused = false;
  238. this._manager.emit("trackStart", player, current);
  239. break;
  240. }
  241. case "TrackEndEvent": {
  242. let track = player.current;
  243. let queue = player.queue.all;
  244. player.playing = false;
  245. if (this._manager.options.previousTracksInArray)
  246. player.previous.push(track);
  247. else
  248. player.previous = track;
  249. if (["loadFailed", "cleanup"].includes(payload.reason)) {
  250. if (!queue) {
  251. player.queue.clear();
  252. return this._manager.emit("queueEnd", player, track);
  253. }
  254. player.play();
  255. return;
  256. }
  257. if (payload.reason === "replaced") {
  258. this._manager.emit("trackEnd", player, track, payload);
  259. return;
  260. }
  261. if (track && player.loop) {
  262. if (player.loop == 1) {
  263. await this.rest.update({
  264. guildId: payload.guildId,
  265. data: { track: { encoded: payload.track.encoded } }
  266. });
  267. if (this.resumed)
  268. player.current = new (index_1.Structure.get("MoonlinkTrack"))(payload.track);
  269. return;
  270. }
  271. if (player.loop == 2) {
  272. player.queue.add(new (index_1.Structure.get("MoonlinkTrack"))(payload.track));
  273. if (!queue || queue.length === 0)
  274. return this._manager.emit("trackEnd", player, track, payload);
  275. player.play();
  276. return;
  277. }
  278. else {
  279. this._manager.emit("trackEnd", player, track);
  280. this._manager.emit("debug", "@Manager(Nodes) - invalid loop value will be ignored!");
  281. }
  282. }
  283. if (player.queue.size) {
  284. this._manager.emit("trackEnd", player, track);
  285. player.play();
  286. return;
  287. }
  288. if (typeof player.autoPlay === "boolean" &&
  289. player.autoPlay === true) {
  290. if (payload.reason == "stopped")
  291. return;
  292. let uri = `https://www.youtube.com/watch?v=${track.identifier}&list=RD${track.identifier}`;
  293. let req = await this._manager.search(uri);
  294. if (!req ||
  295. !req.tracks ||
  296. ["loadFailed", "cleanup"].includes(req.loadType))
  297. return player.stop();
  298. let data = req.tracks[Math.floor(Math.random() * Math.floor(req.tracks.length))];
  299. player.queue.add(data);
  300. player.play();
  301. return;
  302. }
  303. if (player.autoLeave) {
  304. player.destroy();
  305. this._manager.emit("autoLeaved", player, track);
  306. }
  307. if (!player.queue.size) {
  308. this._manager.emit("debug", "[ @Moonlink/Nodes ]: The queue is empty");
  309. this._manager.emit("queueEnd", player);
  310. player.current = null;
  311. player.queue.clear();
  312. }
  313. break;
  314. }
  315. case "TrackStuckEvent": {
  316. this._manager.emit("trackStuck", player, player.current);
  317. player.stop();
  318. break;
  319. }
  320. case "TrackExceptionEvent": {
  321. this._manager.emit("trackError", player, player.current);
  322. player.stop();
  323. break;
  324. }
  325. case "WebSocketClosedEvent": {
  326. this._manager.emit("socketClosed", player, payload);
  327. break;
  328. }
  329. default: {
  330. const error = new Error(`[ @Moonlink/Nodes ] unknown event '${payload.type}'.`);
  331. this._manager.emit("nodeError", this, error);
  332. }
  333. }
  334. }
  335. movePlayers() {
  336. this.getAllPlayers.forEach(player => {
  337. let anotherNode = this._manager.nodes.sortByUsage(this._manager.options?.sortNode ?? "players")[0];
  338. this._manager.emit("debug", `@Moonlink(Node) - Moving player ${player.guildId} to ${anotherNode.identifier ?? anotherNode.host}`);
  339. player.node = anotherNode;
  340. player.restart();
  341. });
  342. return true;
  343. }
  344. get getAllPlayers() {
  345. return Object.values(this._manager.players.all).filter(player => player.node === this);
  346. }
  347. }
  348. exports.MoonlinkNode = MoonlinkNode;
  349.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement