How to get my microphone status on discord - discord

I am creating light for desk, this light will be green when my microphone is active on Discord, and red when my microphone is muted. So I want to get my microphone status from discord. But I don't know-how.
How to get my microphone status from discord when I am not in a voice chat too?
I know how to get microphone status when I am sitting on voice chat but I want to get this information the whole time.
Thanks.

You can use Client#voiceStateUpdate to detect when you change if you are muted or not.
client.on('voiceStateUpdate', (oldState, newState) => {
if (oldState.member.user.id !== "youridhere") return // make sure its only checking for your microhpone
if (newState.mute) { // check if mic is muted
setLightColor("red") //if true make light red
} else {
setLightColor("green") //if false make light green
}
})

I finally found a way to do this !
I made a custom Node.js app using rpcord.
It requires a registered discord app (no need to validate it). You will have to manually link it to Discord using the URL Generator with the rpc and rpc.voice.read scopes, then copy/paste the Client ID, Client Secret and Discord Token in the constants.
The app will run a command every time the Discord voice settings change. In my case, it changes the color of a key on my Logitech keyboard, but you can adapt it to your own needs.
const { RPClient, RPCEvent, Presence } = require("rpcord");
const { exec } = require("child_process");
const CLIENT_ID = 'YOUR APP CLIENT ID';
const CLIENT_SECRET = 'YOUR APP CLIENT SECRET';
const DEFAULT_COLOR = '004f8b';
const DISCORD_TOKEN = 'YOUR DISCORD TOKEN';
exec(`g815-led -a ${DEFAULT_COLOR}`);
const rpc = new RPClient(CLIENT_ID, {
secret: CLIENT_SECRET,
scopes: ["rpc", "rpc.voice.read"],
});
function run(cmd) {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) return reject(error)
if (stderr) return reject(stderr)
resolve(stdout)
})
})
}
rpc.on("ready", () => {
console.log("Connected!");
});
rpc.connect().then(() => {
rpc.authenticate(DISCORD_TOKEN).then(() => {
rpc.getVoiceSettings().then(voiceSettings => {
console.log(voiceSettings);
});
rpc.subscribe(RPCEvent.VoiceSettingsUpdate).then((...args) => {
console.log('subscribed !');
rpc.on('voiceSettingsUpdate', async (voiceSettings) => {
console.log('voice update', voiceSettings);
if (voiceSettings.mute) {
await run('g815-led -k g1 ff0000');
}
else {
await run(`g815-led -k g1 ${DEFAULT_COLOR}`);
}
if (voiceSettings.deaf) {
await run('g815-led -k g2 ff0000');
}
else {
await run(`g815-led -k g2 ${DEFAULT_COLOR}`);
}
});
});
});
});

Related

socket.io not working in production mode for IOS?

I'm currently using socket.io for real time alerts in my app. I'm developing it using React Native with Expo.
I import this instance of the socket into required components:
socketInstance.js
import io from 'socket.io-client';
import { url } from './url';
const socket = io(url, { secure: true });
export default socket;
And then use it to emit data to the server, for example, when the payment for an order has been completed:
OrderPurchaseScreen.js
const openPaymentSheet = async () => {
const { error } = await presentPaymentSheet();
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message, [
{
text: "Try Again",
onPress: () => openPaymentSheet(),
},
{
text: "Cancel Order",
onPress: () => handleExit(),
style: "cancel",
},
]);
} else {
Alert.alert(
"Payment Successful",
"Your payment has successfully been processed."
);
socket.emit("order-purchase-complete", Store.getState().orderReducer.orderTicket.restaurantId);
setActive(false);
navigation.navigate('OrderCompleteScreen');
}
In the node server
server.js
io.on('connection', (socket) => {
socket.on("logIn", (userId) => {
console.log("new user logged in. - " + userId.toString());
socket.join(userId.toString());
socket.on("order-cancelled", (userId) => {
console.log("order cancelled");
io.to(userId.toString()).emit("order-cancelled", createNotificationObject("Order Cancelled", "The restaurant has cancelled your order. Your money will be refunded."));
});
socket.on("new-order-completed", (userId) => {
console.log("order completed");
io.to(userId.toString()).emit("new-order-completed", createNotificationObject("Order Completed", "Your order has been completed."));
});
});
socket.on("restaurantLogin", (restaurantId) => {
console.log("new restaurant logging in...");
socket.join(restaurantId.toString());
socket.on("new-order-for-approval", (restaurantId) => {
console.log("New Order For Approval!");
io.to(restaurantId.toString()).emit("new-order-for-approval", createNotificationObject("Order Awaiting Approval", "There is a new order awaiting approval. View it in the Restaurant Manager."));
});
socket.on("order-purchase-complete", (restaurantId) => {
console.log("new order purchase completed");
io.to(restaurantId.toString()).emit("order-purchase-complete", createNotificationObject("Order Completed", "A new order has been placed. View it in the Restaurant Manager."));
});
});
}
I have found that in dev mode, everything works fine and as expected. However when I switch to prod mode for IOS (have not tested Android), it only seems to be able to handle the user logging in. When it comes to emitting data after the order being completed for example, nothing gets emitted. Anyone know what I can do to debug this to help me find out the problem or have a potential solution?
Found the answer while browsing the socket.io documentation:
https://socket.io/blog/socket-io-on-ios/
"A Note About Multitasking in iOS
As you probably know, iOS is very picky about what you can do in the background. As such, dont expect that your socket connection will survive in the background! Youll probably stop receiving events within seconds of the app going into the background. So its better to create a task that will gracefully close the connection when it enters the background (via AppDelegate), and then reconnect the socket when the app comes back into the foreground."
So all I did was use AppState to get the state of the app, and depending on if it was in the foreground or background I would re connect to the socket or disconnect:
App.js
useEffect(async () => {
const subscription = AppState.addEventListener(
"change",
async (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === "active"
) {
if (_userToken !== null && email !== null && password !== null) {
socket.connect();
socket.emit("logIn", Store.getState().userReducer._id);
}
appState.current = nextAppState;
setAppStateVisible(appState.current);
if (appState.current === "background") {
socket.disconnect();
}
//console.log("AppState", appState.current);
}
);

Discordjs: how to listen for messages on a specific channel

I am building a discord bot to listen to messages on a specific channel. The issue is that my code listens to all channels.
Even if I use a condition to check for the channel id before picking the message, it means it will do more work than is necessary.
I want to avoid the case of selecting messages from multiple channels and just concentrate on the messages in the channel I want to listen to.
require('dotenv').config();
const { Client, Intents, Collection } = require('discord.js');
const {TOKEN, CHANNEL_ID} = require('./src/config/index');
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
client.once('ready', (c) => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.on('messageCreate', async (message) => {
console.log(message)
})
client.login(TOKEN);
This code above is the current code I am using
You can check where the message was posted before running any code.
As far as i am aware that is the only way to do this
client.on('messageCreate', async (message) => {
if (message.channel.id === "YOUR CHANNEL ID") {
// run code here
}
})
There are three ways of sending a message to a specific channels.
//1. Single channel listener
client.on('messageCreate', async (message) => {
if (message.channel.id === "channel_id") {
//For a single channel listener.
} else {
//You can send a message if the channel_id is not equal.
}
})
//2. Multiple channel listener / can be use as .json
let channels = [
"channel_id",
"channel_id"
]
if(channels.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
//3. Can be use like using a database such as mongodb / mongoose / etc.
let channels = {
"chan": [
"987627957478637619",
"948780253948575764"
]
}
if(channels?.chan.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
This is my code, pretty simple and it works.
let allowedChannels = [
/*bot-channel*/"1053346645779152993",
/*console*/"1053346646227959900"
];
client.on('messageCreate', msg => {
//VERY important, exit if the message is from a bot to prevent loops
if (msg.author.bot) {
return;
};
//Check if the channel is accepting bot commands
if (allowedChannels.includes(msg.channel.id) === false) {
return;
}
}

How to start WebRTC call with AWS Kinesis as Master

I'm trying to start a WebRTC call with AWS Kinesis, but the demo on The AWS Kinesis Javascript docs only shows how to join the call as a VIEWER not the MASTER.
I can't find a clear example anywhere online, and I've spent hours on it with my teammate.
I can see and hear myself, so I know I'm getting the hardware working correctly, but we can't see or hear each other. I know it's going to be something simple, but I just can't figure out where I'm going wrong with the connection.
const startKinesisCall = async () => {
const coachingSession = new AWS.KinesisVideo({
region,
accessKeyId,
secretAccessKey,
correctClockSkew: true
});
// Get Signaling Channel Endpoints
// Each signaling channel is assigned an HTTPS and WSS endpoint to connect to for
// data-plane operations. These can be discovered using the GetSignalingChannelEndpoint API.
const getSignalingChannelEndpointResponse = await coachingSession.getSignalingChannelEndpoint({
ChannelARN: channelARN,
SingleMasterChannelEndpointConfiguration: {
Protocols: ['WSS', 'HTTPS'],
Role: Role.VIEWER
}
}).promise();
const endpointsByProtocol = getSignalingChannelEndpointResponse?.ResourceEndpointList?.reduce((endpoints, endpoint) => {
endpoints[endpoint.Protocol] = endpoint?.ResourceEndpoint;
return endpoints;
}, {});
// Create KVS Signaling Client
// The HTTPS endpoint from the GetSignalingChannelEndpoint response is used with this client.
// This client is just used for getting ICE servers, not for actual signaling.
const kinesisVideoSignalingChannelsClient = new AWS.KinesisVideoSignalingChannels({
region,
accessKeyId,
secretAccessKey,
endpoint: endpointsByProtocol.HTTPS,
correctClockSkew: true,
});
// Get ICE server configuration
// For best performance, we collect STUN and TURN ICE server configurations.
// The KVS STUN endpoint is always stun:stun.kinesisvideo.${region}.amazonaws.com:443.
// To get TURN servers, the GetIceServerConfig API is used.
const getIceServerConfigResponse = await kinesisVideoSignalingChannelsClient
.getIceServerConfig({
ChannelARN: channelARN,
}).promise();
const iceServers = [{ urls: `stun:stun.kinesisvideo.${region}.amazonaws.com:443` }];
getIceServerConfigResponse.IceServerList.forEach(iceServer =>
iceServers.push({
urls: iceServer.Uris,
username: iceServer.Username,
credential: iceServer.Password,
}),
);
console.log('ICE SERVERS: ', iceServers);
// Create RTCPeerConnection
// The RTCPeerConnection is the primary interface for WebRTC communications in the Web.
const peerConnection = new RTCPeerConnection({ iceServers });
// Create WebRTC Signaling Client
// This is the actual client that is used to send messages over the signaling channel.
const signalingClient = new SignalingClient({
channelARN,
channelEndpoint: endpointsByProtocol.WSS,
role: Role.MASTER,
region,
clientId,
credentials: {
accessKeyId,
secretAccessKey,
},
systemClockOffset: coachingSession.config.systemClockOffset
});
// GET THE USER MEDIA DEVICES
const localStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).catch(e => {
console.log("COULD NOT FIND WEBCAM");
setShowErrorStartingVideoModal(true);
});
// *** AUDIO & VIDEO DEVICE COLLECTION ***
let audioInputDevices: MediaDeviceInfo[];
let audioOutputDevices: MediaDeviceInfo[];
let videoInputDevices: MediaDeviceInfo[];
try {
const mediaDevices = await navigator.mediaDevices.enumerateDevices();
audioInputDevices = mediaDevices.filter(device => device.kind === 'audioinput');
audioOutputDevices = mediaDevices.filter(device => device.kind === 'audiooutput');
videoInputDevices = mediaDevices.filter(device => device.kind === 'videoinput');
setMicrophoneList(audioInputDevices);
setSpeakerList(audioOutputDevices);
setCameraList(videoInputDevices);
} catch (e) {
console.log(e);
console.log("ERROR COLLECTING MEDIA DEVICE INFORMATION: MAKE SURE PERMISSIONS ARE ALLOWED AND TRY AGAIN");
};
// GRAB THE LOCAL PROVIDER AND PATIENT VIDEO TILES
const providerVideoTile: HTMLVideoElement = document.getElementById('provider-video-element') as HTMLVideoElement;
const patientVideoElement = document.getElementById('patient-video-element') as HTMLVideoElement;
// let dataChannel: RTCDataChannel
// Add Signaling Client Event Listeners
signalingClient.on('open', async () => {
if (!localStream || !peerConnection) return;
// Get a stream from the webcam, add it to the peer connection, and display it in the local view
try {
localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
providerVideoTile.srcObject = localStream;
} catch (e) {
// Could not find webcam
console.log(e);
return;
};
// Create an SDP offer and send it to the master
const offer = await peerConnection.createOffer({
offerToReceiveAudio: true,
offerToReceiveVideo: true
});
console.log('CREATED OFFER: ', offer);
await peerConnection.setLocalDescription(offer);
if (peerConnection.localDescription) signalingClient.sendSdpOffer(peerConnection.localDescription, patient.patientID);
});
// When the SDP answer is received back from the master, add it to the peer connection.
signalingClient.on('sdpAnswer', async answer => {
console.log('RECEIVED ANSWER: ', answer);
if (!peerConnection) return;
await peerConnection.setRemoteDescription(answer).catch(e => console.log(e));
});
signalingClient.on('sdpOffer', async (offer, senderClientID) => {
console.log({ offer });
if (!peerConnection) return;
await peerConnection.setRemoteDescription(offer).catch(e => console.log(e));
console.log('REMOTE DESCRIPTION SET: ', peerConnection);
const answer = await peerConnection.createAnswer().catch(e => console.log(e));
console.log({ answer });
if (answer) signalingClient.sendSdpAnswer(answer, senderClientID);
// dataChannel = peerConnection.createDataChannel(`data-channel-of-${senderClientID}`);
// dataChannel.addEventListener("open", (event) => {
// console.log(event);
// dataChannel.send('******HI ALEC*******');
// });
});
// When an ICE candidate is received from the master, add it to the peer connection.
signalingClient.on('iceCandidate', async (candidate, senderClientID) => {
if (!peerConnection) return;
console.log('new iceCandidate received:', candidate);
await peerConnection.addIceCandidate(candidate).catch(e => console.log(e));
console.log("ICE CANDIDATE ADDED: ", candidate);
});
signalingClient.on('close', async () => {
if (!localStream) return;
// Handle client closures
console.log("ENDING THE CALL");
localStream.getTracks().forEach(track => track.stop());
peerConnection.close();
if ('srcObject' in providerVideoTile) providerVideoTile.srcObject = null;
});
signalingClient.on('error', error => {
// Handle client errors
console.log(error);
});
signalingClient.on('chat', (dataMessage: any) => {
const decodedMessage = UTF8Decoder.decode(new Uint8Array(dataMessage.data));
console.log("GOT TEST MESSAGE:", decodedMessage);
});
signalingClient.on('SeriesData', (dataMessage: any) => {
const seriesFromMobile = JSON.parse(UTF8Decoder.decode(new Uint8Array(dataMessage.data)));
console.log("SERIES FROM MOBILE:", seriesFromMobile);
kickOffSeriesCreation(seriesFromMobile);
});
signalingClient.on('EffortMarker', (dataMessage: any) => {
const effortMarker = UTF8Decoder.decode(new Uint8Array(dataMessage.data));
console.log("EFFORT MARKER:", effortMarker);
setEffortMarker(effortMarker);
});
signalingClient.on('CoachingMessage', async (dataMessage: any) => {
const coachingMessage = UTF8Decoder.decode(new Uint8Array(dataMessage.data));
console.log("COACHING MESSAGE FROM MOBILE:", coachingMessage);
if (coachingMessage === 'EndSeries') {
await handleForceEndEffort(signalingClient);
await handleEndSeries(signalingClient);
};
});
// Add Peer Connection Event Listeners
// Send any ICE candidates generated by the peer connection to the other peer
peerConnection.addEventListener('icecandidate', ({ candidate }) => {
if (candidate) {
console.log(candidate);
signalingClient.sendIceCandidate(candidate, patient.patientID);
} else {
// No more ICE candidates will be generated
console.log('NO MORE ICE CANDIDATES WILL BE GENERATED');
}
});
// As remote tracks are received, add them to the remote view
peerConnection.addEventListener('track', event => {
// if (patientVideoElement.srcObject) return;
setNoPatientConnected(false);
console.log({ event });
try {
peerConnection.addTrack(event.track, event.streams[0]);
if (event.track.kind === 'video') patientVideoElement.srcObject = event.streams[0];
} catch (e) {
console.log(e);
}
});
// Open Signaling Connection
signalingClient.open();
};
Try this this page, You can use master on one computer and viewer on other.
https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html
For anyone else with the same issue, I managed to find the master example on this github repo and was able to get it working

Setting a timeout to delete a message embed on discord.js

I have a basic ticketing system for a suggestions channel.
Ideally, when a user does .exesuggest <whatever suggestion they want> (.exe is the bot prefix), I want the bot to reply that the ticket has been sent to staff, i want the bot to delete the user's message, and to delete it's own message after 5 seconds. At the same time, the bot will send a message with the suggestion's author and the suggestion itself into a staff channel.
At the moment everything is working except for the bot deleting it's own message after 5 seconds.
Here is my code:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) {
return
}
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) {
return
}
const { message } = reaction
if (message.channel.id === channelId) {
message.delete()
}
})
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed)
})
}
}
I have a working command base handler in another file that makes the command work.
I just need to know exactly how to make that bot's reply in replyEmbed to be deleted after 5 seconds.
You can use a setTimeout function to delay the <message>.delete() function from executing.
Example:
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
Full example:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) return;
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) return;
const { message } = reaction
if (message.channel.id === channelId)
message.delete()
});
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed);
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
});
}
}
In Discord.js v13 you have to use setTimeout.
You can implement what you want like this:
userMessage.channel.send(replyEmbed).then(msg => {
setTimeout(() => msg.delete(), 5000);
});// It will delete after 5 seconds
It might work.
Message.delete has an options argument which is an object, and you can set the timeout there (v13 doesn’t have this!):
userMessage.delete({timeout: 5000}) //deletes after 5000 ms
v13 must use setTimeout since the feature was removed
setTimeout(() => userMessage.delete(), 5000) //deletes after 5000 ms

Create a channel with discord.js

I am trying to do a discord bot that creates channels among others, but I can't achieve it because my code it's supposed to create a channel but... I tried a lot of things, these are the two that haven't given me error: (I substituted the bot's token with DONOTLOOK, I won't have problems...)
OPTION 1:
const Discord = require('discord.js');
const bot = new Discord.Client();
bot.login('DONOTLOOK');
bot.on('ready', () => {
console.log('Logged in as ${bot.user.tag}!');
});
bot.on('message', msg => {
if (msg.content === 'ping') {
msg.reply('Pong!');
var server = msg.guild;
bot.channels.add("anewchannel", {type: 0});
}
});
OPTION 2:
const Discord = require('discord.js');
const bot = new Discord.Client();
bot.login('DONOTLOOK');
bot.on('ready', () => {
console.log(`Logged in as ${bot.user.tag}!`);
});
bot.on('message', msg => {
if (msg.content === 'ping') {
msg.reply('Pong!');
var server = msg.guild;
const channel = bot.channels.add("newchannel", {type: 0});
}
});
That don't gave me any node.js error on console, the bot answered me but haven't created the channel. I also looked two references(https://discord.com/developers/docs/resources/guild#create-guild-channel, https://discord.js.org/#/docs/main/stable/class/GuildChannelManager?scrollTo=create), no one's solutions worked, the discord.com one gave me node.js error too. The two options above are taken from the discord.js file, they gave no node.js errors but doesn't create the channel. If someone can help me please.
discord.js v13 has changed some stuff.
Updated version:
bot.on("messageCreate", message => { // instead of 'message', it's now 'messageCreate'
if (message.content === "channel") {
message.guild.channels.create("channel name", {
type: "GUILD_TEXT", // syntax has changed a bit
permissionOverwrites: [{ // same as before
id: message.guild.id,
allow: ["VIEW_CHANNEL"],
}]
});
message.channel.send("Channel Created!");
})
I would also recommend using bot.guilds.cache.get(message.guildId). This removes the need to use the API to fetch the user.
The code below explains how to create a text channel from a command.
bot.on('message', msg => { //Message event listener
if (msg.content === 'channel') { //If the message contained the command
message.guild.channels.create('Text', { //Create a channel
type: 'text', //Make sure the channel is a text channel
permissionOverwrites: [{ //Set permission overwrites
id: message.guild.id,
allow: ['VIEW_CHANNEL'],
}]
});
message.channel.send("Channel Created!); //Let the user know that the channel was created
}
});
If you don't want to use messages to create you can use..
var bot = client.guilds.cache.get("<GUILD-ID>");
server.channels.create("<CHANNEL-TEXT>", "<CHANNEL-TYPE>").then(channel => {
var cat = server.channels.cache.find(c => c.name == "BUSINESSES" && c.type == "category");
if (!cat) { console.log("category does not exist"); return; }
channel.setParent(cat.id);
})

Resources