Calling support (1)
This commit is contained in:
parent
cc9c4f3145
commit
f9ec41c9b6
83
package-lock.json
generated
83
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^0.13.0",
|
"@discordjs/builders": "^0.13.0",
|
||||||
"@discordjs/collection": "^0.6.0",
|
"@discordjs/collection": "^0.6.0",
|
||||||
|
"@discordjs/voice": "^0.9.0",
|
||||||
"@sapphire/async-queue": "^1.3.1",
|
"@sapphire/async-queue": "^1.3.1",
|
||||||
"@sapphire/snowflake": "^3.2.2",
|
"@sapphire/snowflake": "^3.2.2",
|
||||||
"@types/node-fetch": "^2.6.1",
|
"@types/node-fetch": "^2.6.1",
|
||||||
@ -1665,6 +1666,27 @@
|
|||||||
"decamelize": "^1.2.0"
|
"decamelize": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@discordjs/voice": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-fSAYtPCEfIyG56hC2cRJuyfvQGr+aawSssLCqYg70vZ51dKO4spEKOB8V6vNMP5HnEplbhmxkB3YbshFKtnCQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/ws": "^8.5.3",
|
||||||
|
"discord-api-types": "^0.29.0",
|
||||||
|
"prism-media": "^1.3.2",
|
||||||
|
"tiny-typed-emitter": "^2.1.0",
|
||||||
|
"tslib": "^2.3.1",
|
||||||
|
"ws": "^8.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/voice/node_modules/discord-api-types": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-Ekq1ICNpOTVajXKZguNFrsDeTmam+ZeA38txsNLZnANdXUjU6QBPIZLUQTC6MzigFGb0Tt8vk4xLnXmzv0shNg=="
|
||||||
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
||||||
@ -12067,6 +12089,31 @@
|
|||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prism-media": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@discordjs/opus": "^0.5.0",
|
||||||
|
"ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0",
|
||||||
|
"node-opus": "^0.3.3",
|
||||||
|
"opusscript": "^0.0.8"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@discordjs/opus": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"ffmpeg-static": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node-opus": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"opusscript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
@ -13562,6 +13609,11 @@
|
|||||||
"readable-stream": "3"
|
"readable-stream": "3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-typed-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
|
||||||
|
},
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||||
@ -15910,6 +15962,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@discordjs/voice": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-fSAYtPCEfIyG56hC2cRJuyfvQGr+aawSssLCqYg70vZ51dKO4spEKOB8V6vNMP5HnEplbhmxkB3YbshFKtnCQQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/ws": "^8.5.3",
|
||||||
|
"discord-api-types": "^0.29.0",
|
||||||
|
"prism-media": "^1.3.2",
|
||||||
|
"tiny-typed-emitter": "^2.1.0",
|
||||||
|
"tslib": "^2.3.1",
|
||||||
|
"ws": "^8.5.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"discord-api-types": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-Ekq1ICNpOTVajXKZguNFrsDeTmam+ZeA38txsNLZnANdXUjU6QBPIZLUQTC6MzigFGb0Tt8vk4xLnXmzv0shNg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@eslint/eslintrc": {
|
"@eslint/eslintrc": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
||||||
@ -23716,6 +23788,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"prism-media": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
@ -24856,6 +24934,11 @@
|
|||||||
"readable-stream": "3"
|
"readable-stream": "3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tiny-typed-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
|
||||||
|
},
|
||||||
"tmp": {
|
"tmp": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^0.13.0",
|
"@discordjs/builders": "^0.13.0",
|
||||||
"@discordjs/collection": "^0.6.0",
|
"@discordjs/collection": "^0.6.0",
|
||||||
|
"@discordjs/voice": "^0.9.0",
|
||||||
"@sapphire/async-queue": "^1.3.1",
|
"@sapphire/async-queue": "^1.3.1",
|
||||||
"@sapphire/snowflake": "^3.2.2",
|
"@sapphire/snowflake": "^3.2.2",
|
||||||
"@types/node-fetch": "^2.6.1",
|
"@types/node-fetch": "^2.6.1",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const process = require('node:process');
|
const process = require('node:process');
|
||||||
const { setInterval, setTimeout } = require('node:timers');
|
const { setInterval, setTimeout } = require('node:timers');
|
||||||
const { Collection } = require('@discordjs/collection');
|
const { Collection } = require('@discordjs/collection');
|
||||||
|
const { getVoiceConnection } = require('@discordjs/voice');
|
||||||
const RichPresence = require('discord-rpc-contructor');
|
const RichPresence = require('discord-rpc-contructor');
|
||||||
const BaseClient = require('./BaseClient');
|
const BaseClient = require('./BaseClient');
|
||||||
const ActionsManager = require('./actions/ActionsManager');
|
const ActionsManager = require('./actions/ActionsManager');
|
||||||
@ -15,6 +16,7 @@ const ClientUserSettingManager = require('../managers/ClientUserSettingManager')
|
|||||||
const GuildManager = require('../managers/GuildManager');
|
const GuildManager = require('../managers/GuildManager');
|
||||||
const RelationshipsManager = require('../managers/RelationshipsManager');
|
const RelationshipsManager = require('../managers/RelationshipsManager');
|
||||||
const UserManager = require('../managers/UserManager');
|
const UserManager = require('../managers/UserManager');
|
||||||
|
const VoiceStateManager = require('../managers/VoiceStateManager');
|
||||||
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
||||||
const ClientPresence = require('../structures/ClientPresence');
|
const ClientPresence = require('../structures/ClientPresence');
|
||||||
const GuildPreview = require('../structures/GuildPreview');
|
const GuildPreview = require('../structures/GuildPreview');
|
||||||
@ -113,6 +115,8 @@ class Client extends BaseClient {
|
|||||||
*/
|
*/
|
||||||
this.voice = new ClientVoiceManager(this);
|
this.voice = new ClientVoiceManager(this);
|
||||||
|
|
||||||
|
this.voiceStates = new VoiceStateManager({ client: this });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shard helpers for the client (only if the process was spawned from a {@link ShardingManager})
|
* Shard helpers for the client (only if the process was spawned from a {@link ShardingManager})
|
||||||
* @type {?ShardClientUtil}
|
* @type {?ShardClientUtil}
|
||||||
@ -248,6 +252,15 @@ class Client extends BaseClient {
|
|||||||
return this.readyAt ? Date.now() - this.readyAt : null;
|
return this.readyAt ? Date.now() - this.readyAt : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get connection to current call
|
||||||
|
* @type {?VoiceConnection}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get callVoice() {
|
||||||
|
return getVoiceConnection(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update Cloudflare Cookie and Discord Fingerprint
|
* Update Cloudflare Cookie and Discord Fingerprint
|
||||||
*/
|
*/
|
||||||
@ -335,7 +348,6 @@ class Client extends BaseClient {
|
|||||||
* client.QRLogin();
|
* client.QRLogin();
|
||||||
*/
|
*/
|
||||||
QRLogin(debug = false) {
|
QRLogin(debug = false) {
|
||||||
console.log(this.options);
|
|
||||||
const QR = new DiscordAuthWebsocket(this, debug);
|
const QR = new DiscordAuthWebsocket(this, debug);
|
||||||
this.emit(Events.DEBUG, `Preparing to connect to the gateway`, QR);
|
this.emit(Events.DEBUG, `Preparing to connect to the gateway`, QR);
|
||||||
return QR;
|
return QR;
|
||||||
|
@ -29,6 +29,26 @@ class VoiceStateUpdate extends Action {
|
|||||||
client.voice.onVoiceStateUpdate(data);
|
client.voice.onVoiceStateUpdate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
|
||||||
|
* @event Client#voiceStateUpdate
|
||||||
|
* @param {VoiceState} oldState The voice state before the update
|
||||||
|
* @param {VoiceState} newState The voice state after the update
|
||||||
|
*/
|
||||||
|
client.emit(Events.VOICE_STATE_UPDATE, oldState, newState);
|
||||||
|
} else {
|
||||||
|
// Update the state
|
||||||
|
const oldState =
|
||||||
|
client.voiceStates.cache.get(data.user_id)?._clone() ?? new VoiceState({ client }, { user_id: data.user_id });
|
||||||
|
|
||||||
|
const newState = client.voiceStates._add(data);
|
||||||
|
|
||||||
|
// Emit event
|
||||||
|
if (data.user_id === client.user.id) {
|
||||||
|
client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`);
|
||||||
|
client.voice.onVoiceStateUpdate(data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
|
* Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
|
||||||
* @event Client#voiceStateUpdate
|
* @event Client#voiceStateUpdate
|
||||||
|
@ -24,19 +24,26 @@ class ClientVoiceManager {
|
|||||||
client.on(Events.SHARD_DISCONNECT, (_, shardId) => {
|
client.on(Events.SHARD_DISCONNECT, (_, shardId) => {
|
||||||
for (const [guildId, adapter] of this.adapters.entries()) {
|
for (const [guildId, adapter] of this.adapters.entries()) {
|
||||||
if (client.guilds.cache.get(guildId)?.shardId === shardId) {
|
if (client.guilds.cache.get(guildId)?.shardId === shardId) {
|
||||||
adapter.destroy();
|
// Because it has 1 shard => adapter.destroy();
|
||||||
}
|
}
|
||||||
|
adapter.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onVoiceServer(payload) {
|
onVoiceServer(payload) {
|
||||||
|
if (payload.guild_id) {
|
||||||
this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
|
this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
|
||||||
|
} else {
|
||||||
|
this.adapters.get(payload.channel_id)?.onVoiceServerUpdate(payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onVoiceStateUpdate(payload) {
|
onVoiceStateUpdate(payload) {
|
||||||
if (payload.guild_id && payload.session_id && payload.user_id === this.client.user?.id) {
|
if (payload.guild_id && payload.session_id && payload.user_id === this.client.user?.id) {
|
||||||
this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
|
this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
|
||||||
|
} else if (payload.channel_id && payload.session_id && payload.user_id === this.client.user?.id) {
|
||||||
|
this.adapters.get(payload.channel_id)?.onVoiceStateUpdate(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let ClientUser;
|
let ClientUser;
|
||||||
|
const { VoiceConnection, VoiceConnectionStatus } = require('@discordjs/voice');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const Discord = require('../../../index');
|
const Discord = require('../../../index');
|
||||||
const { Events, Opcodes } = require('../../../util/Constants');
|
const { Events, Opcodes } = require('../../../util/Constants');
|
||||||
|
const { Networking } = require('../../../util/Voice');
|
||||||
|
|
||||||
async function checkUpdate() {
|
async function checkUpdate() {
|
||||||
const res_ = await axios.get(`https://registry.npmjs.com/${encodeURIComponent('discord.js-selfbot-v13')}`);
|
const res_ = await axios.get(`https://registry.npmjs.com/${encodeURIComponent('discord.js-selfbot-v13')}`);
|
||||||
@ -29,9 +31,42 @@ module.exports = (client, { d: data }, shard) => {
|
|||||||
try {
|
try {
|
||||||
checkUpdate();
|
checkUpdate();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(`${chalk.redBright('[Fail]')} Check Update error:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client.options.patchVoice) {
|
||||||
|
/* eslint-disable */
|
||||||
|
VoiceConnection.prototype.configureNetworking = function () {
|
||||||
|
const { server, state } = this.packets;
|
||||||
|
if (!server || !state || this.state.status === VoiceConnectionStatus.Destroyed || !server.endpoint) return;
|
||||||
|
const networking = new Networking(
|
||||||
|
{
|
||||||
|
endpoint: server.endpoint,
|
||||||
|
serverId: server.guild_id ?? server.channel_id,
|
||||||
|
token: server.token,
|
||||||
|
sessionId: state.session_id,
|
||||||
|
userId: state.user_id,
|
||||||
|
},
|
||||||
|
Boolean(this.debug),
|
||||||
|
);
|
||||||
|
networking.once('close', this.onNetworkingClose);
|
||||||
|
networking.on('stateChange', this.onNetworkingStateChange);
|
||||||
|
networking.on('error', this.onNetworkingError);
|
||||||
|
networking.on('debug', this.onNetworkingDebug);
|
||||||
|
this.state = {
|
||||||
|
...this.state,
|
||||||
|
status: VoiceConnectionStatus.Connecting,
|
||||||
|
networking,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
client.emit(
|
||||||
|
Events.DEBUG,
|
||||||
|
`${chalk.greenBright('[OK]')} Patched VoiceConnection.prototype.configureNetworking [@discordjs/voice]`,
|
||||||
|
);
|
||||||
|
/* eslint-enable */
|
||||||
|
}
|
||||||
|
|
||||||
client.session_id = data.session_id;
|
client.session_id = data.session_id;
|
||||||
if (client.user) {
|
if (client.user) {
|
||||||
client.user._patch(data.user);
|
client.user._patch(data.user);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const { joinVoiceChannel, entersState, VoiceConnectionStatus } = require('@discordjs/voice');
|
||||||
const { Channel } = require('./Channel');
|
const { Channel } = require('./Channel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
|
const { Status } = require('../util/Constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a direct message channel between two users.
|
* Represents a direct message channel between two users.
|
||||||
@ -97,17 +99,57 @@ class DMChannel extends Channel {
|
|||||||
// Testing feature: Call
|
// Testing feature: Call
|
||||||
// URL: https://discord.com/api/v9/channels/DMchannelId/call/ring
|
// URL: https://discord.com/api/v9/channels/DMchannelId/call/ring
|
||||||
/**
|
/**
|
||||||
* Call this DMChannel. [TEST only]
|
* Call this DMChannel. Return discordjs/voice VoiceConnection
|
||||||
* @returns {Promise<void>}
|
* @param {Object} options Options for the call (selfDeaf, selfMute: Boolean)
|
||||||
|
* @returns {Promise<VoiceConnection>}
|
||||||
*/
|
*/
|
||||||
call() {
|
call(options = {}) {
|
||||||
console.log('TEST only, and not working !');
|
return new Promise((resolve, reject) => {
|
||||||
return this.client.api.channels(this.id).call.ring.post({
|
this.client.api.channels(this.id).call.ring.post({
|
||||||
usingApplicationJson: true,
|
usingApplicationJson: true,
|
||||||
data: {
|
data: {
|
||||||
recipients: null,
|
recipients: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const connection = joinVoiceChannel({
|
||||||
|
channelId: this.id,
|
||||||
|
guildId: null,
|
||||||
|
adapterCreator: this.voiceAdapterCreator,
|
||||||
|
selfDeaf: options.selfDeaf ?? false,
|
||||||
|
selfMute: options.selfMute ?? false,
|
||||||
|
});
|
||||||
|
entersState(connection, VoiceConnectionStatus.Ready, 30000)
|
||||||
|
.then(connection => {
|
||||||
|
resolve(connection);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
connection.destroy();
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
get shard() {
|
||||||
|
return this.client.ws.shards.first();
|
||||||
|
}
|
||||||
|
get voiceAdapterCreator() {
|
||||||
|
return methods => {
|
||||||
|
this.client.voice.adapters.set(this.id, methods);
|
||||||
|
return {
|
||||||
|
sendPayload: data => {
|
||||||
|
data.d = {
|
||||||
|
...data.d,
|
||||||
|
self_video: false,
|
||||||
|
};
|
||||||
|
if (this.shard.status !== Status.READY) return false;
|
||||||
|
console.log('DM channel send payload', data);
|
||||||
|
this.shard.send(data);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
destroy: () => {
|
||||||
|
this.client.voice.adapters.delete(this.id);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Collection } = require('@discordjs/collection');
|
const { Collection } = require('@discordjs/collection');
|
||||||
|
const { joinVoiceChannel, entersState, VoiceConnectionStatus } = require('@discordjs/voice');
|
||||||
const { Channel } = require('./Channel');
|
const { Channel } = require('./Channel');
|
||||||
const Invite = require('./Invite');
|
const Invite = require('./Invite');
|
||||||
const User = require('./User');
|
const User = require('./User');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const { Error } = require('../errors');
|
const { Error } = require('../errors');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
|
const { Status } = require('../util/Constants');
|
||||||
const DataResolver = require('../util/DataResolver');
|
const DataResolver = require('../util/DataResolver');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,17 +206,57 @@ class PartialGroupDMChannel extends Channel {
|
|||||||
// Testing feature: Call
|
// Testing feature: Call
|
||||||
// URL: https://discord.com/api/v9/channels/DMchannelId/call/ring
|
// URL: https://discord.com/api/v9/channels/DMchannelId/call/ring
|
||||||
/**
|
/**
|
||||||
* Call this DMChannel. [TEST only]
|
* Call this Group DMChannel. Return discordjs/voice VoiceConnection
|
||||||
* @returns {Promise<void>}
|
* @param {Object} options Options for the call (selfDeaf, selfMute: Boolean)
|
||||||
|
* @returns {Promise<VoiceConnection>}
|
||||||
*/
|
*/
|
||||||
call() {
|
call(options = {}) {
|
||||||
console.log('TEST only, and not working !');
|
return new Promise((resolve, reject) => {
|
||||||
return this.client.api.channels(this.id).call.ring.post({
|
this.client.api.channels(this.id).call.ring.post({
|
||||||
usingApplicationJson: true,
|
usingApplicationJson: true,
|
||||||
data: {
|
data: {
|
||||||
recipients: null,
|
recipients: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const connection = joinVoiceChannel({
|
||||||
|
channelId: this.id,
|
||||||
|
guildId: null,
|
||||||
|
adapterCreator: this.voiceAdapterCreator,
|
||||||
|
selfDeaf: options.selfDeaf ?? false,
|
||||||
|
selfMute: options.selfMute ?? false,
|
||||||
|
});
|
||||||
|
entersState(connection, VoiceConnectionStatus.Ready, 30000)
|
||||||
|
.then(connection => {
|
||||||
|
resolve(connection);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
connection.destroy();
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
get shard() {
|
||||||
|
return this.client.ws.shards.first();
|
||||||
|
}
|
||||||
|
get voiceAdapterCreator() {
|
||||||
|
return methods => {
|
||||||
|
this.client.voice.adapters.set(this.id, methods);
|
||||||
|
return {
|
||||||
|
sendPayload: data => {
|
||||||
|
data.d = {
|
||||||
|
...data.d,
|
||||||
|
self_video: false,
|
||||||
|
};
|
||||||
|
if (this.shard.status !== Status.READY) return false;
|
||||||
|
console.log('DM channel send payload', data);
|
||||||
|
this.shard.send(data);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
destroy: () => {
|
||||||
|
this.client.voice.adapters.delete(this.id);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ class VoiceState extends Base {
|
|||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get member() {
|
get member() {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
return this.guild.members.cache.get(this.id) ?? null;
|
return this.guild.members.cache.get(this.id) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ class VoiceState extends Base {
|
|||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get channel() {
|
get channel() {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
return this.guild.channels.cache.get(this.channelId) ?? null;
|
return this.guild.channels.cache.get(this.channelId) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +171,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
setMute(mute = true, reason) {
|
setMute(mute = true, reason) {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
return this.guild.members.edit(this.id, { mute }, reason);
|
return this.guild.members.edit(this.id, { mute }, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +182,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
setDeaf(deaf = true, reason) {
|
setDeaf(deaf = true, reason) {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
return this.guild.members.edit(this.id, { deaf }, reason);
|
return this.guild.members.edit(this.id, { deaf }, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +192,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
disconnect(reason) {
|
disconnect(reason) {
|
||||||
|
if (!this.guild?.id) return this.callVoice?.disconnect();
|
||||||
return this.setChannel(null, reason);
|
return this.setChannel(null, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +204,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
setChannel(channel, reason) {
|
setChannel(channel, reason) {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
return this.guild.members.edit(this.id, { channel }, reason);
|
return this.guild.members.edit(this.id, { channel }, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +221,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async setRequestToSpeak(request = true) {
|
async setRequestToSpeak(request = true) {
|
||||||
|
if (this.guild?.id) {
|
||||||
if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
|
if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
|
||||||
|
|
||||||
if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN');
|
if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN');
|
||||||
@ -226,6 +233,7 @@ class VoiceState extends Base {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Suppress/unsuppress the user. Only applicable for stage channels.
|
* Suppress/unsuppress the user. Only applicable for stage channels.
|
||||||
@ -245,6 +253,7 @@ class VoiceState extends Base {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async setSuppressed(suppressed = true) {
|
async setSuppressed(suppressed = true) {
|
||||||
|
if (this.guild?.id) {
|
||||||
if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed');
|
if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed');
|
||||||
|
|
||||||
if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
|
if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL');
|
||||||
@ -258,12 +267,15 @@ class VoiceState extends Base {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get URL Image of the user's streaming video (NOT STREAMING !!!)
|
* Get URL Image of the user's streaming video (NOT STREAMING !!!)
|
||||||
* @returns {string} URL Image of the user's streaming video
|
* @returns {string} URL Image of the user's streaming video
|
||||||
*/
|
*/
|
||||||
async getPreview() {
|
async getPreview() {
|
||||||
|
if (!this.guild?.id) return null;
|
||||||
|
|
||||||
if (!this.streaming) throw new Error('USER_NOT_STREAMING');
|
if (!this.streaming) throw new Error('USER_NOT_STREAMING');
|
||||||
// URL: https://discord.com/api/v9/streams/guild:guildid:voicechannelid:userid/preview
|
// URL: https://discord.com/api/v9/streams/guild:guildid:voicechannelid:userid/preview
|
||||||
const data = await this.client.api.streams[
|
const data = await this.client.api.streams[
|
||||||
|
@ -37,6 +37,7 @@ const JSONBig = require('json-bigint');
|
|||||||
* @property {boolean} [checkUpdate=true] Check for module updates at startup
|
* @property {boolean} [checkUpdate=true] Check for module updates at startup
|
||||||
* @property {boolean} [readyStatus=true] Sync state with Discord Client
|
* @property {boolean} [readyStatus=true] Sync state with Discord Client
|
||||||
* @property {boolean} [autoCookie=true] Automatically add Cookies to Request on startup
|
* @property {boolean} [autoCookie=true] Automatically add Cookies to Request on startup
|
||||||
|
* @property {boolean} [patchVoice=true] Automatically patch @discordjs/voice module (support for call)
|
||||||
* @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
|
* @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
|
||||||
* (e.g. recommended shard count, shard count of the ShardingManager)
|
* (e.g. recommended shard count, shard count of the ShardingManager)
|
||||||
* @property {CacheFactory} [makeCache] Function to create a cache.
|
* @property {CacheFactory} [makeCache] Function to create a cache.
|
||||||
@ -140,6 +141,7 @@ class Options extends null {
|
|||||||
checkUpdate: true,
|
checkUpdate: true,
|
||||||
readyStatus: true,
|
readyStatus: true,
|
||||||
autoCookie: true,
|
autoCookie: true,
|
||||||
|
patchVoice: true,
|
||||||
waitGuildTimeout: 15_000,
|
waitGuildTimeout: 15_000,
|
||||||
shardCount: 1,
|
shardCount: 1,
|
||||||
makeCache: this.cacheWithLimits(this.defaultMakeCacheSettings),
|
makeCache: this.cacheWithLimits(this.defaultMakeCacheSettings),
|
||||||
|
8
typings/index.d.ts
vendored
8
typings/index.d.ts
vendored
@ -625,6 +625,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
public generateInvite(options?: InviteGenerationOptions): string;
|
public generateInvite(options?: InviteGenerationOptions): string;
|
||||||
public login(token?: string): Promise<string>;
|
public login(token?: string): Promise<string>;
|
||||||
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
||||||
|
public readonly callVoice: VoiceConnection | undefined;
|
||||||
public isReady(): this is Client<true>;
|
public isReady(): this is Client<true>;
|
||||||
/** @deprecated Use {@link Sweepers#sweepMessages} instead */
|
/** @deprecated Use {@link Sweepers#sweepMessages} instead */
|
||||||
public sweepMessages(lifetime?: number): number;
|
public sweepMessages(lifetime?: number): number;
|
||||||
@ -940,6 +941,9 @@ export class DMChannel extends TextBasedChannelMixin(Channel, ['bulkDelete']) {
|
|||||||
public recipient: User;
|
public recipient: User;
|
||||||
public type: 'DM';
|
public type: 'DM';
|
||||||
public fetch(force?: boolean): Promise<this>;
|
public fetch(force?: boolean): Promise<this>;
|
||||||
|
public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator;
|
||||||
|
public call(options?: object): Promise<VoiceConnection>;
|
||||||
|
public readonly shard: WebSocketShard;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Emoji extends Base {
|
export class Emoji extends Base {
|
||||||
@ -2068,6 +2072,9 @@ export class PartialGroupDMChannel extends TextBasedChannelMixin(Channel, ['bulk
|
|||||||
public getInvite(): Promise<Invite>;
|
public getInvite(): Promise<Invite>;
|
||||||
public fetchInvite(force: boolean): Promise<PartialGroupDMChannel.invites>;
|
public fetchInvite(force: boolean): Promise<PartialGroupDMChannel.invites>;
|
||||||
public removeInvite(invite: Invite): Promise<PartialGroupDMChannel>;
|
public removeInvite(invite: Invite): Promise<PartialGroupDMChannel>;
|
||||||
|
public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator;
|
||||||
|
public call(options?: object): Promise<VoiceConnection>;
|
||||||
|
public readonly shard: WebSocketShard;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PermissionOverwrites extends Base {
|
export class PermissionOverwrites extends Base {
|
||||||
@ -4208,6 +4215,7 @@ export interface ClientOptions {
|
|||||||
checkUpdate?: boolean;
|
checkUpdate?: boolean;
|
||||||
readyStatus?: boolean;
|
readyStatus?: boolean;
|
||||||
autoCookie?: boolean;
|
autoCookie?: boolean;
|
||||||
|
patchVoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end copy
|
// end copy
|
||||||
|
Loading…
Reference in New Issue
Block a user