comty.js 0.58.0 → 0.59.1

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.
@@ -7,6 +7,12 @@ exports. default = async () => {
7
7
  new Promise(async (resolve) => {
8
8
  const start = Date.now()
9
9
 
10
+ const failTimeout = setTimeout(() => {
11
+ timings.http = "failed"
12
+
13
+ resolve()
14
+ }, 10000)
15
+
10
16
  _request2.default.call(void 0, {
11
17
  method: "GET",
12
18
  url: "/ping",
@@ -15,35 +21,34 @@ exports. default = async () => {
15
21
  // set http timing in ms
16
22
  timings.http = Date.now() - start
17
23
 
24
+ failTimeout && clearTimeout(failTimeout)
25
+
18
26
  resolve()
19
27
  })
20
28
  .catch(() => {
21
29
  timings.http = "failed"
30
+
22
31
  resolve()
23
32
  })
33
+ }),
34
+ new Promise((resolve) => {
35
+ const start = Date.now()
24
36
 
25
- setTimeout(() => {
26
- timings.http = "failed"
37
+ const failTimeout = setTimeout(() => {
38
+ timings.ws = "failed"
27
39
 
28
40
  resolve()
29
41
  }, 10000)
30
- }),
31
- new Promise((resolve) => {
32
- const start = Date.now()
33
42
 
34
43
  __comty_shared_state.wsInstances["default"].on("pong", () => {
35
44
  timings.ws = Date.now() - start
36
45
 
46
+ failTimeout && clearTimeout(failTimeout)
47
+
37
48
  resolve()
38
49
  })
39
50
 
40
51
  __comty_shared_state.wsInstances["default"].emit("ping")
41
-
42
- setTimeout(() => {
43
- timings.ws = "failed"
44
-
45
- resolve()
46
- }, 10000)
47
52
  })
48
53
  ]
49
54
 
package/dist/index.js CHANGED
@@ -67,7 +67,7 @@ if (globalThis.isServerMode) {
67
67
 
68
68
  if (_remotes2.default[key].useClassicAuth && _remotes2.default[key].noAuth !== true) {
69
69
  // try to auth
70
- instance.emit("authenticate", {
70
+ instance.emit("auth", {
71
71
  token: _session2.default.token,
72
72
  })
73
73
  }
@@ -95,6 +95,16 @@ if (globalThis.isServerMode) {
95
95
  }
96
96
  } exports.createWebsockets = createWebsockets;
97
97
 
98
+ async function disconnectWebsockets() {
99
+ const instances = globalThis.__comty_shared_state.wsInstances
100
+
101
+ for (let [key, instance] of Object.entries(instances)) {
102
+ if (instance.connected) {
103
+ instance.disconnect()
104
+ }
105
+ }
106
+ } exports.disconnectWebsockets = disconnectWebsockets;
107
+
98
108
  async function reconnectWebsockets({ force = false } = {}) {
99
109
  const instances = globalThis.__comty_shared_state.wsInstances
100
110
 
@@ -7,6 +7,21 @@ var _sync = require('../sync'); var _sync2 = _interopRequireDefault(_sync);
7
7
  return globalThis.__comty_shared_state.instances["music"]
8
8
  }
9
9
 
10
+ /**
11
+ * Retrieves the official featured playlists.
12
+ *
13
+ * @return {Promise<Object>} The data containing the featured playlists.
14
+ */
15
+ static async getFeaturedPlaylists() {
16
+ const response = await _request2.default.call(void 0, {
17
+ instance: MusicModel.api_instance,
18
+ method: "GET",
19
+ url: "/featured/playlists",
20
+ })
21
+
22
+ return response.data
23
+ }
24
+
10
25
  /**
11
26
  * Retrieves track data for a given ID.
12
27
  *
@@ -506,21 +521,41 @@ var _sync = require('../sync'); var _sync2 = _interopRequireDefault(_sync);
506
521
  /**
507
522
  * Toggles the like status of a track.
508
523
  *
509
- * @param {number} track_id - The ID of the track.
510
- * @throws {Error} If track_id is not provided.
511
- * @return {Promise<Object>} The response data.
524
+ * @param {Object} manifest - The manifest object containing track information.
525
+ * @param {boolean} to - The like status to toggle (true for like, false for unlike).
526
+ * @throws {Error} Throws an error if the manifest is missing.
527
+ * @return {Object} The response data from the API.
512
528
  */
513
- static async toggleTrackLike(track_id) {
514
- if (!track_id) {
515
- throw new Error("Track ID is required")
529
+ static async toggleTrackLike(manifest, to) {
530
+ if (!manifest) {
531
+ throw new Error("Manifest is required")
516
532
  }
517
533
 
518
- const response = await _request2.default.call(void 0, {
519
- instance: MusicModel.api_instance,
520
- method: "POST",
521
- url: `/tracks/${track_id}/toggle-like`,
522
- })
534
+ console.log(`Toggling track ${manifest._id} like status to ${to}`)
523
535
 
524
- return response.data
536
+ const track_id = manifest._id
537
+
538
+ switch (manifest.service) {
539
+ case "tidal": {
540
+ const response = await _sync2.default.tidalCore.toggleTrackLike({
541
+ track_id,
542
+ to,
543
+ })
544
+
545
+ return response
546
+ }
547
+ default: {
548
+ const response = await _request2.default.call(void 0, {
549
+ instance: MusicModel.api_instance,
550
+ method: to ? "POST" : "DELETE",
551
+ url: `/tracks/${track_id}/like`,
552
+ params: {
553
+ service: manifest.service
554
+ }
555
+ })
556
+
557
+ return response.data
558
+ }
559
+ }
525
560
  }
526
561
  } exports.default = MusicModel;
@@ -32,7 +32,24 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
32
32
  return data
33
33
  }}
34
34
 
35
- static __initStatic3() {this.getPostComments = async ({ post_id }) => {
35
+ static __initStatic3() {this.getReplies = async ({ post_id, trim, limit }) => {
36
+ if (!post_id) {
37
+ throw new Error("Post ID is required")
38
+ }
39
+
40
+ const { data } = await _request2.default.call(void 0, {
41
+ method: "GET",
42
+ url: `/posts/post/${post_id}/replies`,
43
+ params: {
44
+ offset: _nullishCoalesce(trim, () => ( 0)),
45
+ limit: _nullishCoalesce(limit, () => ( _withSettings2.default.get("feed_max_fetch"))),
46
+ }
47
+ })
48
+
49
+ return data
50
+ }}
51
+
52
+ static __initStatic4() {this.getPostComments = async ({ post_id }) => {
36
53
  if (!post_id) {
37
54
  throw new Error("Post ID is required")
38
55
  }
@@ -45,7 +62,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
45
62
  return data
46
63
  }}
47
64
 
48
- static __initStatic4() {this.sendComment = async ({ post_id, comment }) => {
65
+ static __initStatic5() {this.sendComment = async ({ post_id, comment }) => {
49
66
  if (!post_id || !comment) {
50
67
  throw new Error("Post ID and/or comment are required")
51
68
  }
@@ -61,7 +78,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
61
78
  return data
62
79
  }}
63
80
 
64
- static __initStatic5() {this.deleteComment = async ({ post_id, comment_id }) => {
81
+ static __initStatic6() {this.deleteComment = async ({ post_id, comment_id }) => {
65
82
  if (!post_id || !comment_id) {
66
83
  throw new Error("Post ID and/or comment ID are required")
67
84
  }
@@ -74,7 +91,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
74
91
  return data
75
92
  }}
76
93
 
77
- static __initStatic6() {this.getExplorePosts = async ({ trim, limit }) => {
94
+ static __initStatic7() {this.getExplorePosts = async ({ trim, limit }) => {
78
95
  const { data } = await _request2.default.call(void 0, {
79
96
  method: "GET",
80
97
  url: `/posts/explore`,
@@ -87,7 +104,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
87
104
  return data
88
105
  }}
89
106
 
90
- static __initStatic7() {this.getSavedPosts = async ({ trim, limit }) => {
107
+ static __initStatic8() {this.getSavedPosts = async ({ trim, limit }) => {
91
108
  const { data } = await _request2.default.call(void 0, {
92
109
  method: "GET",
93
110
  url: `/posts/saved`,
@@ -100,7 +117,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
100
117
  return data
101
118
  }}
102
119
 
103
- static __initStatic8() {this.getUserPosts = async ({ user_id, trim, limit }) => {
120
+ static __initStatic9() {this.getUserPosts = async ({ user_id, trim, limit }) => {
104
121
  if (!user_id) {
105
122
  // use current user_id
106
123
  user_id = _optionalChain([app, 'access', _3 => _3.userData, 'optionalAccess', _4 => _4._id])
@@ -118,7 +135,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
118
135
  return data
119
136
  }}
120
137
 
121
- static __initStatic9() {this.toggleLike = async ({ post_id }) => {
138
+ static __initStatic10() {this.toggleLike = async ({ post_id }) => {
122
139
  if (!post_id) {
123
140
  throw new Error("Post ID is required")
124
141
  }
@@ -131,7 +148,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
131
148
  return data
132
149
  }}
133
150
 
134
- static __initStatic10() {this.toggleSave = async ({ post_id }) => {
151
+ static __initStatic11() {this.toggleSave = async ({ post_id }) => {
135
152
  if (!post_id) {
136
153
  throw new Error("Post ID is required")
137
154
  }
@@ -144,7 +161,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
144
161
  return data
145
162
  }}
146
163
 
147
- static __initStatic11() {this.create = async (payload) => {
164
+ static __initStatic12() {this.create = async (payload) => {
148
165
  const { data } = await _request2.default.call(void 0, {
149
166
  method: "POST",
150
167
  url: `/posts/new`,
@@ -154,7 +171,7 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
154
171
  return data
155
172
  }}
156
173
 
157
- static __initStatic12() {this.deletePost = async ({ post_id }) => {
174
+ static __initStatic13() {this.deletePost = async ({ post_id }) => {
158
175
  if (!post_id) {
159
176
  throw new Error("Post ID is required")
160
177
  }
@@ -166,4 +183,4 @@ var _withSettings = require('../../helpers/withSettings'); var _withSettings2 =
166
183
 
167
184
  return data
168
185
  }}
169
- } Post.__initStatic(); Post.__initStatic2(); Post.__initStatic3(); Post.__initStatic4(); Post.__initStatic5(); Post.__initStatic6(); Post.__initStatic7(); Post.__initStatic8(); Post.__initStatic9(); Post.__initStatic10(); Post.__initStatic11(); Post.__initStatic12(); exports.default = Post;
186
+ } Post.__initStatic(); Post.__initStatic2(); Post.__initStatic3(); Post.__initStatic4(); Post.__initStatic5(); Post.__initStatic6(); Post.__initStatic7(); Post.__initStatic8(); Post.__initStatic9(); Post.__initStatic10(); Post.__initStatic11(); Post.__initStatic12(); Post.__initStatic13(); exports.default = Post;
@@ -1,24 +1,30 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _spotify = require('./services/spotify'); var _spotify2 = _interopRequireDefault(_spotify);
2
2
  var _tidal = require('./services/tidal'); var _tidal2 = _interopRequireDefault(_tidal);
3
+ var _vrc = require('./services/vrc'); var _vrc2 = _interopRequireDefault(_vrc);
3
4
 
4
5
  var _request = require('../../handlers/request'); var _request2 = _interopRequireDefault(_request);
5
6
 
6
- const namespacesServices = {
7
+ const sync_services = {
7
8
  spotify: _spotify2.default,
8
- tidal: _tidal2.default
9
+ tidal: _tidal2.default,
10
+ vrc: _vrc2.default,
9
11
  }
10
12
 
11
13
  class SyncModel {
12
14
  static get spotifyCore() {
13
- return namespacesServices.spotify
15
+ return sync_services.spotify
14
16
  }
15
17
 
16
18
  static get tidalCore() {
17
- return namespacesServices.tidal
19
+ return sync_services.tidal
20
+ }
21
+
22
+ static get vrcCore() {
23
+ return sync_services.vrc
18
24
  }
19
25
 
20
26
  static async linkService(namespace) {
21
- const service = namespacesServices[namespace]
27
+ const service = sync_services[namespace]
22
28
 
23
29
  if (!service || typeof service.linkAccount !== "function") {
24
30
  throw new Error(`Service ${namespace} not found or not accepting linking.`)
@@ -28,7 +34,7 @@ const namespacesServices = {
28
34
  }
29
35
 
30
36
  static async unlinkService(namespace) {
31
- const service = namespacesServices[namespace]
37
+ const service = sync_services[namespace]
32
38
 
33
39
  if (!service || typeof service.unlinkAccount !== "function") {
34
40
  throw new Error(`Service ${namespace} not found or not accepting unlinking.`)
@@ -38,7 +44,7 @@ const namespacesServices = {
38
44
  }
39
45
 
40
46
  static async hasServiceLinked(namespace) {
41
- const service = namespacesServices[namespace]
47
+ const service = sync_services[namespace]
42
48
 
43
49
  if (!service || typeof service.isActive !== "function") {
44
50
  throw new Error(`Service ${namespace} not found or not accepting linking.`)
@@ -49,7 +55,7 @@ const namespacesServices = {
49
55
 
50
56
  static async getLinkedServices() {
51
57
  const response = await _request2.default.call(void 0, {
52
- instance: globalThis.__comty_shared_state.instances["sync"],
58
+ instance: globalThis.__comty_shared_state.instances["sync"],
53
59
  method: "GET",
54
60
  url: "/active_services",
55
61
  })
@@ -156,4 +156,17 @@
156
156
 
157
157
  return data
158
158
  }
159
+
160
+ static async toggleTrackLike({
161
+ track_id,
162
+ to,
163
+ }) {
164
+ const { data } = await _request2.default.call(void 0, {
165
+ instance: TidalService.api_instance,
166
+ method: to ? "POST" : "DELETE",
167
+ url: `/services/tidal/track/${track_id}/like`,
168
+ })
169
+
170
+ return data
171
+ }
159
172
  } exports.default = TidalService;
@@ -0,0 +1,121 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _request = require('../../../handlers/request'); var _request2 = _interopRequireDefault(_request);
2
+
3
+ class VRCService {
4
+ static __initStatic() {this.base_api_hostname = "https://api.vrchat.cloud/api/1"}
5
+
6
+ static get sync_interface() {
7
+ return globalThis.__comty_shared_state.instances["sync"]
8
+ }
9
+
10
+ static get vrc_interface() {
11
+ return globalThis.__comty_shared_state.instances["vrc"]
12
+ }
13
+
14
+ /**
15
+ * Retrieves the current session data if it exists.
16
+ *
17
+ * @return {Promise<Object>} The session data.
18
+ */
19
+ static async get_session() {
20
+ const response = await _request2.default.call(void 0, {
21
+ instance: VRCService.sync_interface,
22
+ method: "GET",
23
+ url: "/services/vrc/session",
24
+ })
25
+
26
+ return response.data
27
+ }
28
+
29
+ /**
30
+ * Authenticates the user with the provided username and password.
31
+ * This will store the session data in the server.
32
+ *
33
+ * @param {string} username - The username of the user.
34
+ * @param {string} password - The password of the user.
35
+ * @return {Promise<Object>} A promise that resolves to the data returned by the authentication API.
36
+ */
37
+ static async auth(username, password, onOtpRequired) {
38
+ let response = null
39
+
40
+ const makeRequest = async () => {
41
+ response = await _request2.default.call(void 0, {
42
+ instance: VRCService.sync_interface,
43
+ method: "POST",
44
+ url: "/services/vrc/auth",
45
+ data: {
46
+ username,
47
+ password,
48
+ },
49
+ })
50
+
51
+ if (response.data.requiresTwoFactorAuth) {
52
+ if (typeof onOtpRequired !== "function") {
53
+ throw new Error("2FA is required, but no (onOtpRequired) was provided")
54
+ }
55
+
56
+ console.log(`2FA Required, invoking onOtpRequired`)
57
+
58
+ return await makeOTPRequest()
59
+ }
60
+
61
+ return response.data
62
+ }
63
+
64
+ const makeOTPRequest = async () => {
65
+ const otpType = response.data.requiresTwoFactorAuth[0]
66
+
67
+ const otpInput = await onOtpRequired(otpType)
68
+
69
+ console.log(`OTP Result = ${otpInput}`)
70
+
71
+ if (!otpInput) {
72
+ console.error("OTP input was empty, requesting again")
73
+
74
+ return await makeOTPRequest()
75
+ }
76
+
77
+ const otpResponse = await _request2.default.call(void 0, {
78
+ instance: VRCService.sync_interface,
79
+ method: "POST",
80
+ url: "/services/vrc/otp",
81
+ data: {
82
+ type: otpType,
83
+ code: otpInput,
84
+ },
85
+ }).catch((err) => {
86
+ console.error(err)
87
+
88
+ return {
89
+ verified: false,
90
+ }
91
+ })
92
+
93
+ console.log(`OTP Response >`, otpResponse.data)
94
+
95
+ if (otpResponse.data.verified) {
96
+ console.log("OTP Verified")
97
+ return await makeRequest()
98
+ } else {
99
+ console.log("OTP Failed")
100
+ return await makeOTPRequest()
101
+ }
102
+ }
103
+
104
+ return await makeRequest()
105
+ }
106
+
107
+ /**
108
+ * Logout the current stored session from the server.
109
+ *
110
+ * @return {Promise<Object>} A Promise that resolves to the response data from the logout request.
111
+ */
112
+ static async logout() {
113
+ const response = await _request2.default.call(void 0, {
114
+ instance: VRCService.sync_interface,
115
+ method: "POST",
116
+ url: "/services/vrc/logout",
117
+ })
118
+
119
+ return response.data
120
+ }
121
+ } VRCService.__initStatic(); exports.default = VRCService;
package/dist/remotes.js CHANGED
@@ -50,8 +50,6 @@ exports. default = {
50
50
  default: {
51
51
  origin: composeRemote("default"),
52
52
  hasWebsocket: true,
53
- useClassicAuth: true,
54
- autoconnect: true,
55
53
  },
56
54
  chat: {
57
55
  origin: composeRemote("chat"),
@@ -63,9 +61,11 @@ exports. default = {
63
61
  },
64
62
  livestreaming: {
65
63
  origin: composeRemote("livestreaming"),
64
+ hasWebsocket: false,
66
65
  },
67
66
  marketplace: {
68
67
  origin: composeRemote("marketplace"),
68
+ hasWebsocket: false,
69
69
  },
70
70
  files: {
71
71
  origin: composeRemote("files"),
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "comty.js",
3
- "version": "0.58.0",
3
+ "version": "0.59.1",
4
4
  "main": "./dist/index.js",
5
5
  "author": "RageStudio <support@ragestudio.net>",
6
6
  "scripts": {
7
- "build": "corenode-cli build"
7
+ "build": "hermes build"
8
8
  },
9
9
  "files": [
10
10
  "dist"
@@ -20,6 +20,7 @@
20
20
  "socket.io-client": "^4.6.1"
21
21
  },
22
22
  "devDependencies": {
23
+ "@ragestudio/hermes": "^0.1.0",
23
24
  "corenode": "^0.28.26"
24
25
  }
25
26
  }