yukimu 1.3.0 → 2.0.0

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 (135) hide show
  1. package/dist/BitrateOptimizer.d.ts +52 -0
  2. package/dist/BitrateOptimizer.d.ts.map +1 -0
  3. package/dist/BitrateOptimizer.js +115 -0
  4. package/dist/BitrateOptimizer.js.map +1 -0
  5. package/dist/ConnectionPool.d.ts +52 -3
  6. package/dist/ConnectionPool.d.ts.map +1 -1
  7. package/dist/ConnectionPool.js +124 -32
  8. package/dist/ConnectionPool.js.map +1 -1
  9. package/dist/Constants.d.ts +27 -2
  10. package/dist/Constants.d.ts.map +1 -1
  11. package/dist/Constants.js +133 -11
  12. package/dist/Constants.js.map +1 -1
  13. package/dist/Logger.d.ts +22 -0
  14. package/dist/Logger.d.ts.map +1 -0
  15. package/dist/Logger.js +74 -0
  16. package/dist/Logger.js.map +1 -0
  17. package/dist/Node.d.ts +17 -4
  18. package/dist/Node.d.ts.map +1 -1
  19. package/dist/Node.js +226 -88
  20. package/dist/Node.js.map +1 -1
  21. package/dist/Player.d.ts +74 -7
  22. package/dist/Player.d.ts.map +1 -1
  23. package/dist/Player.js +317 -92
  24. package/dist/Player.js.map +1 -1
  25. package/dist/Plugin.d.ts +19 -1
  26. package/dist/Plugin.d.ts.map +1 -1
  27. package/dist/Plugin.js +8 -0
  28. package/dist/Plugin.js.map +1 -1
  29. package/dist/Queue.d.ts +69 -2
  30. package/dist/Queue.d.ts.map +1 -1
  31. package/dist/Queue.js +138 -17
  32. package/dist/Queue.js.map +1 -1
  33. package/dist/Resolver.d.ts +33 -2
  34. package/dist/Resolver.d.ts.map +1 -1
  35. package/dist/Resolver.js +225 -33
  36. package/dist/Resolver.js.map +1 -1
  37. package/dist/Rest.d.ts +27 -4
  38. package/dist/Rest.d.ts.map +1 -1
  39. package/dist/Rest.js +157 -25
  40. package/dist/Rest.js.map +1 -1
  41. package/dist/TrackCache.d.ts +30 -5
  42. package/dist/TrackCache.d.ts.map +1 -1
  43. package/dist/TrackCache.js +119 -15
  44. package/dist/TrackCache.js.map +1 -1
  45. package/dist/WsQueue.d.ts +31 -1
  46. package/dist/WsQueue.d.ts.map +1 -1
  47. package/dist/WsQueue.js +70 -12
  48. package/dist/WsQueue.js.map +1 -1
  49. package/dist/Yukimu.d.ts +38 -5
  50. package/dist/Yukimu.d.ts.map +1 -1
  51. package/dist/Yukimu.js +150 -57
  52. package/dist/Yukimu.js.map +1 -1
  53. package/dist/connector/Connector.d.ts +26 -0
  54. package/dist/connector/Connector.d.ts.map +1 -1
  55. package/dist/connector/Connector.js +28 -0
  56. package/dist/connector/Connector.js.map +1 -1
  57. package/dist/connector/DiscordJS.d.ts +20 -1
  58. package/dist/connector/DiscordJS.d.ts.map +1 -1
  59. package/dist/connector/DiscordJS.js +44 -2
  60. package/dist/connector/DiscordJS.js.map +1 -1
  61. package/dist/connector/Eris.d.ts +12 -1
  62. package/dist/connector/Eris.d.ts.map +1 -1
  63. package/dist/connector/Eris.js +40 -6
  64. package/dist/connector/Eris.js.map +1 -1
  65. package/dist/connector/Oceanic.d.ts +12 -1
  66. package/dist/connector/Oceanic.d.ts.map +1 -1
  67. package/dist/connector/Oceanic.js +39 -4
  68. package/dist/connector/Oceanic.js.map +1 -1
  69. package/dist/errors/YukimuError.d.ts +40 -4
  70. package/dist/errors/YukimuError.d.ts.map +1 -1
  71. package/dist/errors/YukimuError.js +79 -8
  72. package/dist/errors/YukimuError.js.map +1 -1
  73. package/dist/index.d.ts +13 -4
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +30 -16
  76. package/dist/index.js.map +1 -1
  77. package/dist/plugins/AutoResume.d.ts +18 -1
  78. package/dist/plugins/AutoResume.d.ts.map +1 -1
  79. package/dist/plugins/AutoResume.js +109 -21
  80. package/dist/plugins/AutoResume.js.map +1 -1
  81. package/dist/plugins/AutoplayPlugin.d.ts +35 -0
  82. package/dist/plugins/AutoplayPlugin.d.ts.map +1 -0
  83. package/dist/plugins/AutoplayPlugin.js +111 -0
  84. package/dist/plugins/AutoplayPlugin.js.map +1 -0
  85. package/dist/plugins/InactivityPlugin.d.ts +30 -0
  86. package/dist/plugins/InactivityPlugin.d.ts.map +1 -0
  87. package/dist/plugins/InactivityPlugin.js +86 -0
  88. package/dist/plugins/InactivityPlugin.js.map +1 -0
  89. package/dist/plugins/PlayerMoved.d.ts +23 -1
  90. package/dist/plugins/PlayerMoved.d.ts.map +1 -1
  91. package/dist/plugins/PlayerMoved.js +57 -12
  92. package/dist/plugins/PlayerMoved.js.map +1 -1
  93. package/dist/types.d.ts +198 -71
  94. package/dist/types.d.ts.map +1 -1
  95. package/dist/types.js +1 -0
  96. package/dist/types.js.map +1 -1
  97. package/package.json +49 -5
  98. package/.cache/replit/env/latest +0 -88
  99. package/.cache/replit/env/latest.json +0 -1
  100. package/.cache/replit/modules/nodejs-20.res +0 -1
  101. package/.cache/replit/modules/python-3.11.res +0 -1
  102. package/.cache/replit/modules/replit.res +0 -1
  103. package/.cache/replit/modules.stamp +0 -0
  104. package/.cache/replit/nix/dotreplitenv.json +0 -1
  105. package/.cache/replit/toolchain.json +0 -1
  106. package/.local/state/workflow-logs/7zVU0iVo-fBL1ccMCmELy/configure_your_app.packager.installForAll.0 +0 -9
  107. package/.local/state/workflow-logs/7zVU0iVo-fBL1ccMCmELy/configure_your_app.shell.exec.1 +0 -1
  108. package/.local/state/workflow-logs/KRgHXizaECjWI5nWtS7Dj/configure_your_app.packager.installForAll.0 +0 -1
  109. package/.local/state/workflow-logs/KRgHXizaECjWI5nWtS7Dj/configure_your_app.shell.exec.1 +0 -1
  110. package/.local/state/workflow-logs/U0AinJQVHonnwGjj0RXLn/configure_your_app.packager.installForAll.0 +0 -2
  111. package/.local/state/workflow-logs/jVavLOnv1MqxUvxhMmqER/configure_your_app.packager.installForAll.0 +0 -1
  112. package/.local/state/workflow-logs/jVavLOnv1MqxUvxhMmqER/configure_your_app.shell.exec.1 +0 -1
  113. package/.replit +0 -7
  114. package/.upm/store.json +0 -1
  115. package/src/ConnectionPool.ts +0 -114
  116. package/src/Constants.ts +0 -45
  117. package/src/Node.ts +0 -302
  118. package/src/Player.ts +0 -332
  119. package/src/Plugin.ts +0 -7
  120. package/src/Queue.ts +0 -66
  121. package/src/Resolver.ts +0 -90
  122. package/src/Rest.ts +0 -127
  123. package/src/TrackCache.ts +0 -46
  124. package/src/WsQueue.ts +0 -58
  125. package/src/Yukimu.ts +0 -213
  126. package/src/connector/Connector.ts +0 -13
  127. package/src/connector/DiscordJS.ts +0 -26
  128. package/src/connector/Eris.ts +0 -24
  129. package/src/connector/Oceanic.ts +0 -22
  130. package/src/errors/YukimuError.ts +0 -31
  131. package/src/index.ts +0 -24
  132. package/src/plugins/AutoResume.ts +0 -37
  133. package/src/plugins/PlayerMoved.ts +0 -26
  134. package/src/types.ts +0 -145
  135. package/tsconfig.json +0 -22
@@ -1,88 +0,0 @@
1
- declare -gx POETRY_CACHE_DIR=/home/runner/workspace/.cache/pypoetry
2
- declare -gx NIX_LDFLAGS=''
3
- declare -gx XDG_DATA_DIRS=/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/share:/nix/store/y7m7h744qpw8hidkkxnhx7wzgv59w287-replit-runtime-path/share
4
- declare -gx HOSTNAME=d71dd0c5f660
5
- declare -gx REPLIT_HELIUM_ENABLED=true
6
- declare -gx PROMPT_DIRTRIM=2
7
- declare -gx REPL_OWNER_ID=37551296
8
- declare -gx REPLIT_EXPO_DEV_DOMAIN=5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.expo.sisko.replit.dev
9
- declare -gx REPLIT_CONNECTORS_HOSTNAME=connectors.replit.com
10
- declare -gx REPLIT_CLUSTER=sisko
11
- declare -gx REPLIT_RTLD_LOADER=1
12
- declare -gx PYTHONUSERBASE=/home/runner/workspace/.pythonlibs
13
- declare -gx UV_PROJECT_ENVIRONMENT=/home/runner/workspace/.pythonlibs
14
- declare -gx PKG_CONFIG_PATH=''
15
- declare -gx REPL_PUBKEYS='{"crosis-ci":"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=","crosis-ci:1":"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=","crosis-ci:latest":"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=","prod":"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=","prod:1":"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=","prod:3":"9+MCOSHQSQlcodXoot8dC8NLhc862nLkx1/VMsbY2h8=","prod:4":"8uGN+vfszlnV93/HCSHlVLG0xddMlPkir1Ni4JKT4+w=","prod:5":"9+MCOSHQSQlcodXoot8dC8NLhc862nLkx1/VMsbY2h8=","prod:latest":"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=","vault-goval-token":"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E=","vault-goval-token:1":"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E=","vault-goval-token:latest":"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E="}'
16
- declare -gx PGUSER=postgres
17
- declare -gx REPLIT_DEV_DOMAIN=5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.sisko.replit.dev
18
- declare -gx GIT_EDITOR=replit-git-editor
19
- declare -gx UV_PYTHON_DOWNLOADS=never
20
- declare -gx PGPASSWORD=password
21
- declare -gx NIXPKGS_ALLOW_UNFREE=1
22
- declare -gx REPLIT_ARTIFACT_ROUTER=/nix/store/mcy1kl5dlr0l1gpv6z21bkabyylx0wjb-artifact-router-0.1.0/bin/artifact-router
23
- declare -gx NIX_PROFILES='/nix/var/nix/profiles/default /home/runner/.nix-profile'
24
- declare -gx NIX_PS1='\[\033[01;34m\]\w\[\033[00m\]\$ '
25
- declare -gx POETRY_PIP_NO_ISOLATE=1
26
- declare -gx PGHOST=helium
27
- declare -gx XDG_DATA_HOME=/home/runner/workspace/.local/share
28
- declare -gx COLORTERM=truecolor
29
- declare -gx CFLAGS=''
30
- declare -gx PYTHONPATH=/nix/store/y50fwh2sha400s38m12psfxpvk2c8w39-sitecustomize/lib/python/site-packages:/nix/store/sqs1z4grvym0nv6r3ksdc990m8sr5wgx-python3.11-pip-25.0.1/lib/python3.11/site-packages
31
- declare -gx __EGL_VENDOR_LIBRARY_FILENAMES=/nix/store/l4myp7qn0q9bqgmkqq4vnnii22ql1r68-mesa-25.0.7/share/glvnd/egl_vendor.d/50_mesa.json
32
- declare -gx REPL_HOME=/home/runner/workspace
33
- declare -gx PGDATABASE=heliumdb
34
- declare -gx REPLIT_HEIMDALL_ADDR=https://heimdall.replit.com
35
- declare -gx REPLIT_GITSAFE_EXISTING_REPLS_ENABLED=true
36
- declare -gx npm_config_prefix=/home/runner/workspace/.config/npm/node_global
37
- declare -gx POETRY_VIRTUALENVS_CREATE=0
38
- declare -gx NIX_CFLAGS_COMPILE=''
39
- declare -gx GI_TYPELIB_PATH=''
40
- read -r _new_path <<< "/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/bin:/home/runner/workspace/.pythonlibs/bin:/nix/store/flbj8bq2vznkcwss7sm0ky8rd0k6kar7-python-wrapped-0.1.0/bin:/nix/store/xwg0ddq9mjf6ibwdvp93jsp0cf51z3xr-pip-wrapper/bin:/nix/store/ypy3l3k428kc1kmcw090wlbxi8vj1m8l-poetry-wrapper/bin:/nix/store/6m2322jq0rkfdnv6cm3dq8437djbfv1l-uv-0.9.5/bin:/nix/store/b1kq183rmmiv453fn6f8bfmi1drxvxba-npx/bin:/home/runner/workspace/.config/npm/node_global/bin:/home/runner/workspace/node_modules/.bin:/nix/store/1lagpgadaybvs1n2312gysg2phjk89y8-nodejs-20.20.0-wrapped/bin:/nix/store/1xk3mgscq548ypyrgm2n5kwdii92w9ql-bun-1.3.6/bin:/nix/store/61lr9izijvg30pcribjdxgjxvh3bysp4-pnpm-10.26.1/bin:/nix/store/23078nfww258q1vjxbmyak0svvxcvj4s-yarn-1.22.22/bin:/nix/store/8sa75mbvbn3kxicggyyjggmkigvzddks-prettier-3.6.2/bin:/nix/store/v4a60n406fy3b1w8c9qfkj3bzvhjb4bv-pid1/bin:/nix/store/y7m7h744qpw8hidkkxnhx7wzgv59w287-replit-runtime-path/bin:/home/runner/.nix-profile/bin:/home/runner/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
41
- #PATH=/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/bin:/home/runner/workspace/.pythonlibs/bin:/nix/store/flbj8bq2vznkcwss7sm0ky8rd0k6kar7-python-wrapped-0.1.0/bin:/nix/store/xwg0ddq9mjf6ibwdvp93jsp0cf51z3xr-pip-wrapper/bin:/nix/store/ypy3l3k428kc1kmcw090wlbxi8vj1m8l-poetry-wrapper/bin:/nix/store/6m2322jq0rkfdnv6cm3dq8437djbfv1l-uv-0.9.5/bin:/nix/store/b1kq183rmmiv453fn6f8bfmi1drxvxba-npx/bin:/home/runner/workspace/.config/npm/node_global/bin:/home/runner/workspace/node_modules/.bin:/nix/store/1lagpgadaybvs1n2312gysg2phjk89y8-nodejs-20.20.0-wrapped/bin:/nix/store/1xk3mgscq548ypyrgm2n5kwdii92w9ql-bun-1.3.6/bin:/nix/store/61lr9izijvg30pcribjdxgjxvh3bysp4-pnpm-10.26.1/bin:/nix/store/23078nfww258q1vjxbmyak0svvxcvj4s-yarn-1.22.22/bin:/nix/store/8sa75mbvbn3kxicggyyjggmkigvzddks-prettier-3.6.2/bin:/nix/store/v4a60n406fy3b1w8c9qfkj3bzvhjb4bv-pid1/bin:/nix/store/y7m7h744qpw8hidkkxnhx7wzgv59w287-replit-runtime-path/bin:/home/runner/.nix-profile/bin:/home/runner/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
42
- if [ -e "/run/replit/env/last" ]; then read -r _last_path < <(\grep '^#PATH=' /run/replit/env/last | cut -f 2 -d =); fi
43
- _user_components="$(\tr : $'\n' <<< "${PATH:-}" |\grep -xv -f <(\tr : $'\n' <<< "${_last_path}") |\tr $'\n' :)"
44
- declare -gx PATH="${_user_components}${_new_path}"
45
- declare -gx XDG_CONFIG_HOME=/home/runner/workspace/.config
46
- declare -gx POETRY_INSTALLER_MODERN_INSTALLATION=1
47
- declare -gx POETRY_PIP_USE_PIP_CACHE=1
48
- declare -gx NIX_PATH=/home/runner/.nix-defexpr/channels
49
- declare -gx REPLIT_NIX_CHANNEL=legacy
50
- declare -gx REPLIT_GITSAFE_ENABLED=true
51
- declare -gx DATABASE_URL='postgresql://postgres:password@helium/heliumdb?sslmode=disable'
52
- declare -gx REPLIT_DOMAINS=5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.sisko.replit.dev
53
- declare -gx PIP_CONFIG_FILE=/nix/store/z0d7kvaycmw342xmz4xwwybm6p3p0zcs-pip.conf
54
- declare -gx PKG_CONFIG_PATH_FOR_TARGET=''
55
- declare -gx LOCALE_ARCHIVE=/usr/lib/locale/locale-archive
56
- declare -gx PGPORT=5432
57
- declare -gx LDFLAGS=''
58
- declare -gx HOME=/home/runner
59
- declare -gx REPLIT_CONTAINER=gcr.io/marine-cycle-160323/repl-base:3c526f0870c482ef04b1ca6073a0d578ba34e814
60
- declare -gx TZDIR=/etc/zoneinfo
61
- declare -gx CONNECTORS_HOSTNAME=connectors.replit.com
62
- declare -gx POETRY_USE_USER_SITE=1
63
- declare -gx REPLIT_PYTHONPATH=/home/runner/workspace/.pythonlibs/lib/python3.11/site-packages:/nix/store/lxnbcmx15m3yascasf4c9qh7zk19pd2b-python3.11-setuptools-80.9.0/lib/python3.11/site-packages
64
- declare -gx REPL_OWNER=babyprank598
65
- declare -gx USER=runner
66
- declare -gx LANG=en_US.UTF-8
67
- declare -gx REPLIT_RIPPKGS_INDICES=/nix/store/cg6q7dm7h9jp20vwj79ahnbsd9cs6iay-rippkgs-indices
68
- declare -gx REPLIT_BASHRC=/nix/store/lsgsb0ar7rdwa09d1z2dnfjh4188pddk-replit-bashrc/bashrc
69
- declare -gx POETRY_CONFIG_DIR=/nix/store/cyg6h5fbgsfqdimyrc1gflmpx8p0hbkv-poetry-config
70
- declare -gx POETRY_PIP_FROM_PATH=1
71
- declare -gx REPLIT_SUBCLUSTER=interactive
72
- declare -gx REPLIT_GITSAFE_NEW_REPLS_ENABLED=true
73
- declare -gx REPL_ID=5880c157-f106-4406-b020-cef4a1c1600e
74
- declare -gx REPL_LANGUAGE=nix
75
- declare -gx REPLIT_ENVIRONMENT=production
76
- declare -gx REPL_SLUG=workspace
77
- declare -gx REPLIT_PYTHON_LD_LIBRARY_PATH=/nix/store/pya3p1ihjm446jpqpql93542cirqyn23-cpplibs/lib:/nix/store/c2qsgf2832zi4n29gfkqgkjpvmbmxam6-zlib-1.3.1/lib:/nix/store/f7rcazhd826xlcz43il4vafv28888cgj-glib-2.86.3/lib:/nix/store/ii3ybky5dqjikcrw7vdnh1j76ssy0ycm-libx11-1.8.12/lib:/nix/store/zshby6nalhw4mvap0rr97hv042808c2k-libxext-1.3.6/lib:/nix/store/0r6d7iw0q9wgxxj28zy87n1gjwvk0klp-libxinerama-1.1.5/lib:/nix/store/bb5xxw11ndww7iivcmdpxga9n1da24vg-libxcursor-1.2.3/lib:/nix/store/dyn0y5clf5b556yqwmj4841h43hz75p6-libxrandr-1.5.4/lib:/nix/store/x1f9a0qsj6a1y5nf178naagm2vbxnazc-libxi-1.8.2/lib:/nix/store/pv432a54y6di3n12iqix2dglkswvq1px-libxxf86vm-1.1.6/lib
78
- declare -gx REPLIT_CLI=/nix/store/pjjdi4mgzxj5r4j4w5vqiv2wli2dggi7-replit-cli-0.0.1/bin/replit
79
- declare -gx DISPLAY=:0
80
- declare -gx LIBGL_DRIVERS_PATH=/nix/store/l4myp7qn0q9bqgmkqq4vnnii22ql1r68-mesa-25.0.7/lib/dri
81
- declare -gx DOCKER_CONFIG=/home/runner/workspace/.config/docker
82
- declare -gx GIT_ASKPASS=replit-git-askpass
83
- declare -gx POETRY_DOWNLOAD_WITH_CURL=1
84
- declare -gx UV_PYTHON_PREFERENCE=only-system
85
- declare -gx POETRY_PIP_NO_PREFIX=1
86
- declare -gx REPLIT_PID1_VERSION=0.0.0-625c12a
87
- declare -gx XDG_CACHE_HOME=/home/runner/workspace/.cache
88
- declare -gx REPLIT_LD_AUDIT=/nix/store/sj11ljhx4n79h9g0167f8lg8hp7n545m-replit_rtld_loader-1/rtld_loader.so
@@ -1 +0,0 @@
1
- {"environment":{"CFLAGS":"","COLORTERM":"truecolor","CONNECTORS_HOSTNAME":"connectors.replit.com","DATABASE_URL":"postgresql://postgres:password@helium/heliumdb?sslmode=disable","DISPLAY":":0","DOCKER_CONFIG":"/home/runner/workspace/.config/docker","GIT_ASKPASS":"replit-git-askpass","GIT_EDITOR":"replit-git-editor","GI_TYPELIB_PATH":"","HOME":"/home/runner","HOSTNAME":"d71dd0c5f660","LANG":"en_US.UTF-8","LDFLAGS":"","LIBGL_DRIVERS_PATH":"/nix/store/l4myp7qn0q9bqgmkqq4vnnii22ql1r68-mesa-25.0.7/lib/dri","LOCALE_ARCHIVE":"/usr/lib/locale/locale-archive","NIXPKGS_ALLOW_UNFREE":"1","NIX_CFLAGS_COMPILE":"","NIX_LDFLAGS":"","NIX_PATH":"/home/runner/.nix-defexpr/channels","NIX_PROFILES":"/nix/var/nix/profiles/default /home/runner/.nix-profile","NIX_PS1":"\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ ","PATH":"/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/bin:/home/runner/workspace/.pythonlibs/bin:/nix/store/flbj8bq2vznkcwss7sm0ky8rd0k6kar7-python-wrapped-0.1.0/bin:/nix/store/xwg0ddq9mjf6ibwdvp93jsp0cf51z3xr-pip-wrapper/bin:/nix/store/ypy3l3k428kc1kmcw090wlbxi8vj1m8l-poetry-wrapper/bin:/nix/store/6m2322jq0rkfdnv6cm3dq8437djbfv1l-uv-0.9.5/bin:/nix/store/b1kq183rmmiv453fn6f8bfmi1drxvxba-npx/bin:/home/runner/workspace/.config/npm/node_global/bin:/home/runner/workspace/node_modules/.bin:/nix/store/1lagpgadaybvs1n2312gysg2phjk89y8-nodejs-20.20.0-wrapped/bin:/nix/store/1xk3mgscq548ypyrgm2n5kwdii92w9ql-bun-1.3.6/bin:/nix/store/61lr9izijvg30pcribjdxgjxvh3bysp4-pnpm-10.26.1/bin:/nix/store/23078nfww258q1vjxbmyak0svvxcvj4s-yarn-1.22.22/bin:/nix/store/8sa75mbvbn3kxicggyyjggmkigvzddks-prettier-3.6.2/bin:/nix/store/v4a60n406fy3b1w8c9qfkj3bzvhjb4bv-pid1/bin:/nix/store/y7m7h744qpw8hidkkxnhx7wzgv59w287-replit-runtime-path/bin:/home/runner/.nix-profile/bin:/home/runner/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PGDATABASE":"heliumdb","PGHOST":"helium","PGPASSWORD":"password","PGPORT":"5432","PGUSER":"postgres","PIP_CONFIG_FILE":"/nix/store/z0d7kvaycmw342xmz4xwwybm6p3p0zcs-pip.conf","PKG_CONFIG_PATH":"","PKG_CONFIG_PATH_FOR_TARGET":"","POETRY_CACHE_DIR":"/home/runner/workspace/.cache/pypoetry","POETRY_CONFIG_DIR":"/nix/store/cyg6h5fbgsfqdimyrc1gflmpx8p0hbkv-poetry-config","POETRY_DOWNLOAD_WITH_CURL":"1","POETRY_INSTALLER_MODERN_INSTALLATION":"1","POETRY_PIP_FROM_PATH":"1","POETRY_PIP_NO_ISOLATE":"1","POETRY_PIP_NO_PREFIX":"1","POETRY_PIP_USE_PIP_CACHE":"1","POETRY_USE_USER_SITE":"1","POETRY_VIRTUALENVS_CREATE":"0","PROMPT_DIRTRIM":"2","PYTHONPATH":"/nix/store/y50fwh2sha400s38m12psfxpvk2c8w39-sitecustomize/lib/python/site-packages:/nix/store/sqs1z4grvym0nv6r3ksdc990m8sr5wgx-python3.11-pip-25.0.1/lib/python3.11/site-packages","PYTHONUSERBASE":"/home/runner/workspace/.pythonlibs","REPLIT_ARTIFACT_ROUTER":"/nix/store/mcy1kl5dlr0l1gpv6z21bkabyylx0wjb-artifact-router-0.1.0/bin/artifact-router","REPLIT_BASHRC":"/nix/store/lsgsb0ar7rdwa09d1z2dnfjh4188pddk-replit-bashrc/bashrc","REPLIT_CLI":"/nix/store/pjjdi4mgzxj5r4j4w5vqiv2wli2dggi7-replit-cli-0.0.1/bin/replit","REPLIT_CLUSTER":"sisko","REPLIT_CONNECTORS_HOSTNAME":"connectors.replit.com","REPLIT_CONTAINER":"gcr.io/marine-cycle-160323/repl-base:3c526f0870c482ef04b1ca6073a0d578ba34e814","REPLIT_DEV_DOMAIN":"5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.sisko.replit.dev","REPLIT_DOMAINS":"5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.sisko.replit.dev","REPLIT_ENVIRONMENT":"production","REPLIT_EXPO_DEV_DOMAIN":"5880c157-f106-4406-b020-cef4a1c1600e-00-1vwlyfui4qmee.expo.sisko.replit.dev","REPLIT_GITSAFE_ENABLED":"true","REPLIT_GITSAFE_EXISTING_REPLS_ENABLED":"true","REPLIT_GITSAFE_NEW_REPLS_ENABLED":"true","REPLIT_HEIMDALL_ADDR":"https://heimdall.replit.com","REPLIT_HELIUM_ENABLED":"true","REPLIT_LD_AUDIT":"/nix/store/sj11ljhx4n79h9g0167f8lg8hp7n545m-replit_rtld_loader-1/rtld_loader.so","REPLIT_NIX_CHANNEL":"legacy","REPLIT_PID1_VERSION":"0.0.0-625c12a","REPLIT_PYTHONPATH":"/home/runner/workspace/.pythonlibs/lib/python3.11/site-packages:/nix/store/lxnbcmx15m3yascasf4c9qh7zk19pd2b-python3.11-setuptools-80.9.0/lib/python3.11/site-packages","REPLIT_PYTHON_LD_LIBRARY_PATH":"/nix/store/pya3p1ihjm446jpqpql93542cirqyn23-cpplibs/lib:/nix/store/c2qsgf2832zi4n29gfkqgkjpvmbmxam6-zlib-1.3.1/lib:/nix/store/f7rcazhd826xlcz43il4vafv28888cgj-glib-2.86.3/lib:/nix/store/ii3ybky5dqjikcrw7vdnh1j76ssy0ycm-libx11-1.8.12/lib:/nix/store/zshby6nalhw4mvap0rr97hv042808c2k-libxext-1.3.6/lib:/nix/store/0r6d7iw0q9wgxxj28zy87n1gjwvk0klp-libxinerama-1.1.5/lib:/nix/store/bb5xxw11ndww7iivcmdpxga9n1da24vg-libxcursor-1.2.3/lib:/nix/store/dyn0y5clf5b556yqwmj4841h43hz75p6-libxrandr-1.5.4/lib:/nix/store/x1f9a0qsj6a1y5nf178naagm2vbxnazc-libxi-1.8.2/lib:/nix/store/pv432a54y6di3n12iqix2dglkswvq1px-libxxf86vm-1.1.6/lib","REPLIT_RIPPKGS_INDICES":"/nix/store/cg6q7dm7h9jp20vwj79ahnbsd9cs6iay-rippkgs-indices","REPLIT_RTLD_LOADER":"1","REPLIT_SUBCLUSTER":"interactive","REPL_HOME":"/home/runner/workspace","REPL_ID":"5880c157-f106-4406-b020-cef4a1c1600e","REPL_LANGUAGE":"nix","REPL_OWNER":"babyprank598","REPL_OWNER_ID":"37551296","REPL_PUBKEYS":"{\"crosis-ci\":\"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=\",\"crosis-ci:1\":\"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=\",\"crosis-ci:latest\":\"7YlpcYh82oR9NSTtSYtR5jDL4onNzCGJGq6b+9CuZII=\",\"prod\":\"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=\",\"prod:1\":\"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=\",\"prod:3\":\"9+MCOSHQSQlcodXoot8dC8NLhc862nLkx1/VMsbY2h8=\",\"prod:4\":\"8uGN+vfszlnV93/HCSHlVLG0xddMlPkir1Ni4JKT4+w=\",\"prod:5\":\"9+MCOSHQSQlcodXoot8dC8NLhc862nLkx1/VMsbY2h8=\",\"prod:latest\":\"tGsjlu/BJvWTgvMaX7acuUb7AO1dXOrRiuk7y083RFE=\",\"vault-goval-token\":\"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E=\",\"vault-goval-token:1\":\"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E=\",\"vault-goval-token:latest\":\"D5jJoMx1Ml54HM92NLgXl+MzptwDqbSsfyFG6f52g9E=\"}","REPL_SLUG":"workspace","TZDIR":"/etc/zoneinfo","USER":"runner","UV_PROJECT_ENVIRONMENT":"/home/runner/workspace/.pythonlibs","UV_PYTHON_DOWNLOADS":"never","UV_PYTHON_PREFERENCE":"only-system","XDG_CACHE_HOME":"/home/runner/workspace/.cache","XDG_CONFIG_HOME":"/home/runner/workspace/.config","XDG_DATA_DIRS":"/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/share:/nix/store/y7m7h744qpw8hidkkxnhx7wzgv59w287-replit-runtime-path/share","XDG_DATA_HOME":"/home/runner/workspace/.local/share","__EGL_VENDOR_LIBRARY_FILENAMES":"/nix/store/l4myp7qn0q9bqgmkqq4vnnii22ql1r68-mesa-25.0.7/share/glvnd/egl_vendor.d/50_mesa.json","npm_config_prefix":"/home/runner/workspace/.config/npm/node_global"}}
@@ -1 +0,0 @@
1
- {"type":"resolve","resolvedModuleId":"nodejs-20","inputHash":"","resolutionPath":["nodejs-20"],"error":"","Changed":true}
@@ -1 +0,0 @@
1
- {"type":"resolve","resolvedModuleId":"python-3.11","inputHash":"","resolutionPath":["python-3.11"],"error":"","Changed":true}
@@ -1 +0,0 @@
1
- {"type":"resolve","resolvedModuleId":"replit","inputHash":"","resolutionPath":["replit"],"error":"","Changed":true}
File without changes
@@ -1 +0,0 @@
1
- {"channel":"","channel_nix_path":"/nix/store/42iv6n6l2izliq7lhy3gsaqsycj6np1h-nixpkgs/nixpkgs","env":{"CFLAGS":"","GI_TYPELIB_PATH":"","LDFLAGS":"","NIX_CFLAGS_COMPILE":"","NIX_LDFLAGS":"","PATH":"/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/bin","PKG_CONFIG_PATH":"","PKG_CONFIG_PATH_FOR_TARGET":"","REPLIT_LD_LIBRARY_PATH":"","XDG_DATA_DIRS":"/nix/store/ynhhsbqi66v2pcy3r8l6g391vpasr3sy-zip-3.0/share"},"packages":["zip"]}
@@ -1 +0,0 @@
1
- {"runs":[{"id":"module:nodejs-20/runner:nodeJS", "name":"Node.js", "fileParam":true, "language":"javascript", "fileTypeAttrs":{}, "displayVersion":"20.20.0", "run":{"command":{"args":["sh", "-c", "/nix/store/1lagpgadaybvs1n2312gysg2phjk89y8-nodejs-20.20.0-wrapped/bin/node $file"]}}, "defaultEntrypoints":["index.js", "main.js"]}, {"id":"module:python-3.11/runner:python", "name":"Python 3.11", "fileParam":true, "language":"python3", "fileTypeAttrs":{}, "displayVersion":"3.11.14", "run":{"command":{"args":["sh", "-c", "/nix/store/s4ckxp77ljlikarkka88ba7qr5mlka97-python3-wrapper/bin/python3 $file"]}}, "defaultEntrypoints":["main.py", "app.py", "run.py"]}], "languageServers":[{"id":"module:python-3.11/languageServer:ty", "name":"ty", "language":"python3", "fileTypeAttrs":{}, "config":{"startCommand":{"args":["sh", "-c", "/nix/store/775cppcslcvxd4x2v8x4k78xw94zg88a-ty-0.0.21/bin/ty server"]}}, "displayVersion":"0.0.21"}, {"id":"module:replit/languageServer:dotreplit-lsp", "name":".replit LSP", "language":"dotreplit", "fileTypeAttrs":{}, "config":{"startCommand":{"args":["sh", "-c", "/nix/store/qq4mijbp008lc0r1h42jy3fhwakqz6nf-taplo-0.patched/bin/taplo lsp -c /nix/store/7nplpw32gfk08i6d1v3wmwj3b1qd0apw-taplo-config.toml stdio"]}}}, {"id":"module:nodejs-20/languageServer:typescript-language-server", "name":"TypeScript Language Server", "language":"javascript", "fileTypeAttrs":{"extensions":[".js", ".jsx", ".ts", ".tsx", ".mjs", ".mts", ".cjs", ".cts", ".es6", ".json"]}, "config":{"startCommand":{"args":["sh", "-c", "/nix/store/pkx0287w1vx971gahfkggqa59v35d4bm-typescript-language-server-5.1.3/bin/typescript-language-server --stdio"]}, "initializationOptionsJson":"{\"disableAutomaticTypingAcquisition\":true,\"maxTsServerMemory\":1536,\"tsserver\":{\"fallbackPath\":\"/nix/store/6wjhsy7rpyxbpl65grd5a8aq96b50i8a-typescript-5.9.3/lib/node_modules/typescript/lib\"}}"}, "displayVersion":"5.1.3"}], "packagers":[{"id":"module:python-3.11/packager:upmPython", "name":"Python packager", "language":"python3", "packageSearch":true, "guessImports":true}, {"id":"module:nodejs-20/packager:upmNodejs", "name":"Node.js packager (npm, yarn, pnpm, bun)", "language":"nodejs", "packageSearch":true, "guessImports":true}], "formatters":[{"id":"module:nodejs-20/formatter:prettier", "name":"Prettier", "startCommand":{"args":["/nix/store/h0yq53vj17w8bqs8bdldg2kg1llkqi7i-run-prettier/bin/run-prettier"], "lifecycle":"STDIN", "splitStderr":true}, "fileTypeAttrs":{"extensions":[".js", ".jsx", ".ts", ".tsx", ".json", ".html"]}, "displayVersion":"3.6.2", "supportsRangeFormatting":true}, {"id":"module:nodejs-20/languageServer:typescript-language-server", "name":"TypeScript Language Server", "fileTypeAttrs":{"extensions":[".js", ".jsx", ".ts", ".tsx", ".mjs", ".mts", ".cjs", ".cts", ".es6", ".json"]}, "displayVersion":"5.1.3"}, {"id":"module:python-3.11/formatter:ruff", "name":"Ruff", "startCommand":{"args":["/nix/store/mqvkfmbcri2jllqsjmqcgr353i4j6k7r-run-ruff-format/bin/run-ruff-format"], "lifecycle":"STDIN", "splitStderr":true}, "fileTypeAttrs":{"extensions":[".py"]}, "displayVersion":"0.14.11"}, {"id":"module:python-3.11/languageServer:ty", "name":"ty", "fileTypeAttrs":{}, "displayVersion":"0.0.21"}, {"id":"module:replit/languageServer:dotreplit-lsp", "name":".replit LSP", "fileTypeAttrs":{}}]}
@@ -1,9 +0,0 @@
1
- --> npm install
2
- ⠙⠹⠸⠼⠴
3
- up to date, audited 28 packages in 657ms
4
- ⠴
5
- ⠴7 packages are looking for funding
6
- ⠴ run `npm fund` for details
7
- ⠴
8
- found 0 vulnerabilities
9
- ⠴
@@ -1 +0,0 @@
1
- Please use the Workflows pane to configure your app. For more info, see: https://docs.replit.com/replit-workspace/workflows#creating-workflows
@@ -1 +0,0 @@
1
- Please use the Workflows pane to configure your app. For more info, see: https://docs.replit.com/replit-workspace/workflows#creating-workflows
@@ -1,2 +0,0 @@
1
- --> npm install
2
- ⠙⠹
@@ -1 +0,0 @@
1
- Please use the Workflows pane to configure your app. For more info, see: https://docs.replit.com/replit-workspace/workflows#creating-workflows
package/.replit DELETED
@@ -1,7 +0,0 @@
1
- modules = ["nodejs-20", "python-3.11"]
2
-
3
- [agent]
4
- expertMode = true
5
-
6
- [nix]
7
- packages = ["zip"]
package/.upm/store.json DELETED
@@ -1 +0,0 @@
1
- {"version":2,"languages":{"nodejs-npm":{},"python3-uv":{}}}
@@ -1,114 +0,0 @@
1
- import type { Yukimu } from "./Yukimu";
2
-
3
- export interface VoiceConnection {
4
- guildId: string;
5
- channelId: string;
6
- sessionId: string | null;
7
- token: string | null;
8
- endpoint: string | null;
9
- timeout: ReturnType<typeof setTimeout> | null;
10
- retryTimeout: ReturnType<typeof setTimeout> | null;
11
- connected: boolean;
12
- retries: number;
13
- }
14
-
15
- const MAX_VOICE_RETRIES = 3;
16
- const VOICE_RETRY_DELAY = 5000;
17
-
18
- export class ConnectionPool {
19
- private readonly manager: Yukimu;
20
- private readonly connections: Map<string, VoiceConnection> = new Map();
21
-
22
- constructor(manager: Yukimu) { this.manager = manager; }
23
-
24
- public add(guildId: string, channelId: string): VoiceConnection {
25
- const existing = this.connections.get(guildId);
26
- if (existing) { existing.channelId = channelId; return existing; }
27
- const conn: VoiceConnection = {
28
- guildId, channelId,
29
- sessionId: null, token: null, endpoint: null,
30
- timeout: null, retryTimeout: null,
31
- connected: false, retries: 0,
32
- };
33
- this.connections.set(guildId, conn);
34
- this.startTimeout(conn);
35
- return conn;
36
- }
37
-
38
- public get(guildId: string): VoiceConnection | undefined { return this.connections.get(guildId); }
39
-
40
- public remove(guildId: string): void {
41
- const conn = this.connections.get(guildId);
42
- if (!conn) return;
43
- if (conn.timeout) clearTimeout(conn.timeout);
44
- if (conn.retryTimeout) clearTimeout(conn.retryTimeout);
45
- this.connections.delete(guildId);
46
- }
47
-
48
- public has(guildId: string): boolean { return this.connections.has(guildId); }
49
-
50
- public updateSession(guildId: string, sessionId: string, channelId?: string): void {
51
- const conn = this.connections.get(guildId);
52
- if (!conn) return;
53
- conn.sessionId = sessionId;
54
- if (channelId) conn.channelId = channelId;
55
- }
56
-
57
- public updateServer(guildId: string, token: string, endpoint: string): void {
58
- const conn = this.connections.get(guildId);
59
- if (!conn) return;
60
- conn.token = token;
61
- conn.endpoint = endpoint;
62
- }
63
-
64
- public markConnected(guildId: string): void {
65
- const conn = this.connections.get(guildId);
66
- if (!conn) return;
67
- conn.connected = true;
68
- conn.retries = 0;
69
- if (conn.timeout) { clearTimeout(conn.timeout); conn.timeout = null; }
70
- if (conn.retryTimeout) { clearTimeout(conn.retryTimeout); conn.retryTimeout = null; }
71
- }
72
-
73
- public isReady(guildId: string): boolean {
74
- const conn = this.connections.get(guildId);
75
- return !!(conn?.sessionId && conn?.token && conn?.endpoint);
76
- }
77
-
78
- public getVoiceState(guildId: string): { token: string; endpoint: string; sessionId: string; channelId?: string } | null {
79
- const conn = this.connections.get(guildId);
80
- if (!conn?.sessionId || !conn?.token || !conn?.endpoint) return null;
81
- return { token: conn.token, endpoint: conn.endpoint, sessionId: conn.sessionId, channelId: conn.channelId };
82
- }
83
-
84
- private startTimeout(conn: VoiceConnection): void {
85
- const timeoutMs = (this.manager.options as any).voiceConnectionTimeout ?? 15000;
86
- if (conn.timeout) clearTimeout(conn.timeout);
87
- conn.timeout = setTimeout(() => {
88
- if (!conn.connected) this.handleConnectionFailure(conn);
89
- }, timeoutMs);
90
- }
91
-
92
- private handleConnectionFailure(conn: VoiceConnection): void {
93
- if (conn.retries >= MAX_VOICE_RETRIES) {
94
- const player = this.manager.players.get(conn.guildId);
95
- if (player) {
96
- (this.manager as any).emit("playerError", player, new Error(`Voice connection failed after ${MAX_VOICE_RETRIES} retries`));
97
- this.manager.destroyPlayer(conn.guildId).catch(() => {});
98
- }
99
- this.remove(conn.guildId);
100
- return;
101
- }
102
- conn.retries++;
103
- console.warn(`[Yukimu] Voice retry ${conn.retries}/${MAX_VOICE_RETRIES} for guild ${conn.guildId}`);
104
- conn.retryTimeout = setTimeout(() => {
105
- this.manager.connector.sendPayload(conn.guildId, {
106
- op: 4,
107
- d: { guild_id: conn.guildId, channel_id: conn.channelId, self_deaf: true, self_mute: false },
108
- });
109
- this.startTimeout(conn);
110
- }, VOICE_RETRY_DELAY * conn.retries);
111
- }
112
-
113
- get size(): number { return this.connections.size; }
114
- }
package/src/Constants.ts DELETED
@@ -1,45 +0,0 @@
1
- export const VERSION = "1.3.0";
2
- export const CLIENT_NAME = `Yukimu/${VERSION}`;
3
-
4
- export enum State {
5
- CONNECTING = 0,
6
- NEARLY = 1,
7
- CONNECTED = 2,
8
- DISCONNECTING = 3,
9
- DISCONNECTED = 4,
10
- RECONNECTING = 5,
11
- }
12
-
13
- export enum PlayerState {
14
- CONNECTING = 0,
15
- CONNECTED = 1,
16
- DISCONNECTING = 2,
17
- DISCONNECTED = 3,
18
- }
19
-
20
- export const SOURCE_PREFIXES: Record<string, string> = {
21
- youtube: "ytsearch",
22
- youtubemusic: "ytmsearch",
23
- spotify: "spsearch",
24
- deezer: "dzsearch",
25
- applemusic: "amsearch",
26
- soundcloud: "scsearch",
27
- tidal: "tdsearch",
28
- jiosaavn: "jssearch",
29
- yandexmusic: "ymsearch",
30
- };
31
-
32
- export const URL_PATTERNS: Record<string, RegExp[]> = {
33
- youtube: [/^https?:\/\/(www\.)?(youtube\.com|youtu\.be)\/.+/, /^https?:\/\/music\.youtube\.com\/.+/],
34
- spotify: [/^https?:\/\/open\.spotify\.com\/(track|album|playlist|artist)\/.+/],
35
- soundcloud: [/^https?:\/\/(www\.)?soundcloud\.com\/.+/],
36
- deezer: [/^https?:\/\/(www\.)?deezer\.com\/(track|album|playlist)\/.+/],
37
- applemusic: [/^https?:\/\/music\.apple\.com\/.+/],
38
- tidal: [/^https?:\/\/(www\.)?tidal\.com\/.+/],
39
- jiosaavn: [/^https?:\/\/(www\.)?jiosaavn\.com\/.+/],
40
- yandexmusic: [/^https?:\/\/music\.yandex\.(ru|com)\/.+/],
41
- };
42
-
43
- export const STOPPED_REASONS = new Set([
44
- "replaced", "stopped", "REPLACED", "STOPPED",
45
- ]);
package/src/Node.ts DELETED
@@ -1,302 +0,0 @@
1
- import WebSocket from "ws";
2
- import { Rest } from "./Rest";
3
- import { WsQueue } from "./WsQueue";
4
- import { State } from "./Constants";
5
- import { NodeError } from "./errors/YukimuError";
6
- import type { Yukimu } from "./Yukimu";
7
- import type { NodeOptions, NodeStats, NodeInfo, Track, SearchResult, LavalinkException } from "./types";
8
-
9
- const WS_CLOSE_NORMAL = 1000;
10
- const HEARTBEAT_INTERVAL = 30000;
11
-
12
- export class Node {
13
- public readonly manager: Yukimu;
14
- public readonly options: NodeOptions;
15
- public readonly rest: Rest;
16
- public readonly wsQueue: WsQueue;
17
- public readonly version: 3 | 4;
18
-
19
- public ws: WebSocket | null = null;
20
- public state: State = State.DISCONNECTED;
21
- public stats: NodeStats | null = null;
22
- public info: NodeInfo | null = null;
23
- public sessionId: string | null = null;
24
- public resumed: boolean = false;
25
- public penalties: number = 0;
26
- public ping: number = -1;
27
-
28
- private restQueue: Promise<any> = Promise.resolve();
29
- private reconnectAttempts = 0;
30
- private reconnectTimeout?: ReturnType<typeof setTimeout>;
31
- private heartbeatInterval?: ReturnType<typeof setInterval>;
32
- private lastHeartbeatAt = 0;
33
-
34
- constructor(manager: Yukimu, options: NodeOptions) {
35
- this.manager = manager;
36
- this.options = { secure: false, retries: 5, version: 4, resumeTimeout: 60, ...options };
37
- this.version = (this.options.version ?? 4) as 3 | 4;
38
- this.rest = new Rest(this);
39
- this.wsQueue = new WsQueue();
40
- }
41
-
42
- get connected(): boolean {
43
- return this.state === State.CONNECTED || this.state === State.NEARLY;
44
- }
45
-
46
- get wsUrl(): string {
47
- const protocol = this.options.secure ? "wss" : "ws";
48
- const base = `${protocol}://${this.options.host}:${this.options.port}`;
49
- return this.version === 4 ? `${base}/v4/websocket` : base;
50
- }
51
-
52
- get wsHeaders(): Record<string, string> {
53
- const h: Record<string, string> = {
54
- Authorization: this.options.password,
55
- "User-Id": this.manager.options.clientId,
56
- "Client-Name": "Yukimu/1.3.0",
57
- };
58
- if (this.version === 3) h["Num-Shards"] = "1";
59
- if (this.options.resumeKey) h["Resume-Key"] = this.options.resumeKey;
60
- return h;
61
- }
62
-
63
- public calculatePenalties(): number {
64
- if (!this.stats) return Infinity;
65
- const cpu = Math.pow(1.05, 100 * this.stats.cpu.systemLoad) * 10 - 10;
66
- const fs = this.stats.frameStats;
67
- const deficit = fs ? Math.pow(1.03, 500 * fs.deficit / 3000) * 600 - 600 : 0;
68
- const nulled = fs ? Math.pow(1.03, 500 * fs.nulled / 3000) * 300 - 300 : 0;
69
- this.penalties = ~~(cpu + deficit + nulled + this.stats.playingPlayers);
70
- return this.penalties;
71
- }
72
-
73
- public connect(): void {
74
- if (this.ws?.readyState === WebSocket.OPEN) return;
75
- this.state = State.CONNECTING;
76
- this.manager.emit("nodeConnecting", this);
77
- this.ws = new WebSocket(this.wsUrl, { headers: this.wsHeaders });
78
- this.wsQueue.setSocket(this.ws);
79
- this.ws.on("open", () => this.onOpen());
80
- this.ws.on("message", (d: any) => this.onMessage(d));
81
- this.ws.on("close", (code: number, reason: any) => this.onClose(code, reason.toString()));
82
- this.ws.on("error", (err: Error) => this.onError(err));
83
- }
84
-
85
- public destroy(reconnect = false): void {
86
- if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);
87
- if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
88
- this.wsQueue.clear();
89
- this.wsQueue.setSocket(null);
90
- this.ws?.removeAllListeners();
91
- this.ws?.close(WS_CLOSE_NORMAL, "destroy");
92
- this.ws = null;
93
- this.state = State.DISCONNECTED;
94
- if (!reconnect) this.sessionId = null;
95
- }
96
-
97
- private async onOpen(): Promise<void> {
98
- this.state = State.NEARLY;
99
- this.reconnectAttempts = 0;
100
- this.manager.emit("nodeConnect", this);
101
- console.log(`[Yukimu] Node "${this.options.name}" connected (v${this.version})`);
102
-
103
- try { this.info = await this.rest.getInfo(); } catch {}
104
-
105
- if (this.version === 4 && this.options.resumeKey) {
106
- await this.rest.updateSession({ resuming: true, timeout: this.options.resumeTimeout ?? 60 }).catch(() => {});
107
- }
108
-
109
- if (this.version === 3) {
110
- this.state = State.CONNECTED;
111
- this.sessionId = this.options.resumeKey ?? `v3-${Date.now()}`;
112
- this.manager.emit("nodeReady", this);
113
- }
114
-
115
- this.startHeartbeat();
116
- }
117
-
118
- private onMessage(raw: any): void {
119
- let payload: any;
120
- try { payload = JSON.parse(raw.toString()); } catch { return; }
121
- const op = payload.op as string;
122
-
123
- if (this.version === 4) {
124
- switch (op) {
125
- case "ready":
126
- this.state = State.CONNECTED;
127
- this.sessionId = payload.sessionId;
128
- this.resumed = payload.resumed ?? false;
129
- this.manager.emit("nodeReady", this);
130
- console.log(`[Yukimu] Node "${this.options.name}" ready | session: ${this.sessionId} | resumed: ${this.resumed}`);
131
- if (this.resumed) this.reconnectPlayers();
132
- break;
133
- case "stats":
134
- this.stats = payload;
135
- this.calculatePenalties();
136
- break;
137
- case "playerUpdate":
138
- this.handlePlayerUpdate(payload);
139
- break;
140
- case "event":
141
- this.handleEvent(payload);
142
- break;
143
- }
144
- return;
145
- }
146
-
147
- switch (op) {
148
- case "stats": this.stats = payload; this.calculatePenalties(); break;
149
- case "playerUpdate": this.handlePlayerUpdate(payload); break;
150
- case "event": this.handleEvent(payload); break;
151
- }
152
- }
153
-
154
- private onClose(code: number, reason: string): void {
155
- if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
156
- this.state = State.DISCONNECTED;
157
- this.manager.emit("nodeDisconnect", this, code, reason);
158
- console.warn(`[Yukimu] Node "${this.options.name}" disconnected (${code}): ${reason || "No reason"}`);
159
- if (code !== WS_CLOSE_NORMAL) this.scheduleReconnect();
160
- else this.movePlayers();
161
- }
162
-
163
- private onError(error: Error): void {
164
- this.manager.emit("nodeError", this, error);
165
- console.error(`[Yukimu] Node "${this.options.name}" error:`, error.message);
166
- }
167
-
168
- private startHeartbeat(): void {
169
- if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
170
- this.heartbeatInterval = setInterval(async () => {
171
- if (!this.connected) return;
172
- this.lastHeartbeatAt = Date.now();
173
- try {
174
- this.stats = await this.rest.getStats();
175
- this.ping = Date.now() - this.lastHeartbeatAt;
176
- this.calculatePenalties();
177
- } catch {}
178
- }, HEARTBEAT_INTERVAL);
179
- }
180
-
181
- private scheduleReconnect(): void {
182
- const max = this.options.retries ?? 5;
183
- if (this.reconnectAttempts >= max) {
184
- this.manager.emit("nodeError", this, new NodeError(`Node "${this.options.name}" max retries reached`));
185
- this.movePlayers();
186
- return;
187
- }
188
- const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
189
- this.reconnectAttempts++;
190
- this.state = State.RECONNECTING;
191
- console.log(`[Yukimu] Reconnecting "${this.options.name}" in ${delay}ms (${this.reconnectAttempts}/${max})`);
192
- this.reconnectTimeout = setTimeout(() => { this.destroy(true); this.connect(); }, delay);
193
- }
194
-
195
- private movePlayers(): void {
196
- const players = [...this.manager.players.values()].filter((p: any) => p.node === this);
197
- if (!players.length) return;
198
- let best: Node;
199
- try { best = this.manager.getBestNode(); } catch { return; }
200
- if (best === this) return;
201
- console.log(`[Yukimu] Moving ${players.length} players to "${best.options.name}"`);
202
- for (const player of players) (player as any).moveToNode(best).catch(console.error);
203
- }
204
-
205
- private reconnectPlayers(): void {
206
- for (const player of this.manager.players.values()) {
207
- if ((player as any).node === this) (player as any).checkVoiceReady();
208
- }
209
- }
210
-
211
- private handlePlayerUpdate(payload: any): void {
212
- const player = this.manager.players.get(payload.guildId);
213
- if (!player) return;
214
- const state = payload.state ?? {};
215
- (player as any).position = state.position ?? (player as any).position;
216
- (player as any).ping = state.ping ?? (player as any).ping;
217
- (player as any).lastUpdated = state.time ?? Date.now();
218
- this.manager.emit("playerUpdate", player);
219
- }
220
-
221
- private handleEvent(payload: any): void {
222
- const player = this.manager.players.get(payload.guildId);
223
- if (!player) return;
224
-
225
- let track: Track;
226
- if (this.version === 3) {
227
- track = { encoded: payload.track, info: {} as any, pluginInfo: {} };
228
- } else {
229
- track = payload.track;
230
- if (track?.encoded) this.manager.trackCache.set(track.encoded, track);
231
- }
232
-
233
- const p = player as any;
234
-
235
- switch (payload.type) {
236
- case "TrackStartEvent":
237
- p.playing = true;
238
- p.paused = false;
239
- p.lastUpdated = Date.now();
240
- this.manager.emit("trackStart", player, track);
241
- break;
242
-
243
- case "TrackEndEvent": {
244
- const reason = payload.reason;
245
- p.playing = false;
246
- p.position = 0;
247
- this.manager.emit("trackEnd", player, track, reason);
248
- const stopped = ["replaced", "stopped", "REPLACED", "STOPPED"].includes(reason);
249
- if (!stopped) {
250
- if (p.loop === "track" && p.queue.current) {
251
- p.play(p.queue.current).catch(() => {});
252
- } else {
253
- if (p.loop === "queue" && p.queue.current) p.queue.add(p.queue.current);
254
- const next = p.queue.next();
255
- if (next) {
256
- p.play(next).catch(() => {});
257
- } else {
258
- this.manager.emit("queueEnd", player);
259
- if (p.autoplay && track.info?.uri) {
260
- this.manager.emit("autoplayRequest", player, track);
261
- }
262
- }
263
- }
264
- }
265
- break;
266
- }
267
-
268
- case "TrackExceptionEvent":
269
- this.manager.emit("trackError", player, track, payload.exception);
270
- break;
271
-
272
- case "TrackStuckEvent":
273
- this.manager.emit("trackStuck", player, track, payload.thresholdMs);
274
- p.skip().catch(() => {});
275
- break;
276
-
277
- case "WebSocketClosedEvent":
278
- this.manager.emit("socketClosed", player, payload.code, payload.reason, payload.byRemote);
279
- break;
280
- }
281
- }
282
-
283
- public send(data: Record<string, any>): Promise<void> {
284
- return this.wsQueue.send(data);
285
- }
286
-
287
- public enqueueRest<T>(fn: () => Promise<T>): Promise<T> {
288
- const result = this.restQueue.then(() => fn());
289
- this.restQueue = result.catch(() => {});
290
- return result;
291
- }
292
-
293
- public async loadTracks(identifier: string): Promise<SearchResult> {
294
- return this.rest.loadTracks(identifier);
295
- }
296
-
297
- public playerPath(guildId: string): string {
298
- return this.version === 4
299
- ? `/sessions/${this.sessionId}/players/${guildId}`
300
- : `/players/${guildId}`;
301
- }
302
- }