Discord: Get User by Id - javascript

I'm trying to create a web application to manage the users of my Discord server. In my database, I have stored only the users' ids.
I tried to use the discord.js API, but from what I've understood it requires a discord bot to do that. That's not what I want. I would like to retrieve the user's information from my frontend, even by calling a backend function, but without having a discord bot which is always online. In other words, I need something simpler.
I would like to request users' information by using only the id. Which is the best way to do that in JavaScript?

You can use the Discord API.
First, create a Discord application here. Once you've done that, click 'Bot' on the sidebar and create a bot for that application. There, you'll see a section called 'Token' under the bot username. Copy this and store it somewhere secure. It is important to never share your token. If you do, you should regenerate it to prevent abuse.
You can then use the Get User endpoint (/users/{user.id}/) to retrieve the user for an ID. This should be done by the backend as it involves authenticating with the bot token.
Using the API directly
Here is a minimal example of how you would fetch a user by their ID using the Discord API using Node.js:
const fetch = require('node-fetch')
// You might want to store this in an environment variable or something
const token = 'YOUR_TOKEN'
const fetchUser = async id => {
const response = await fetch(`https://discord.com/api/v9/users/${id}`, {
headers: {
Authorization: `Bot ${token}`
}
})
if (!response.ok) throw new Error(`Error status code: ${response.status}`)
return JSON.parse(await response.json())
}
The response would be something like this:
{
"id": "123456789012345678",
"username": "some username",
"avatar": null,
"discriminator": "1234",
"public_flags": 0,
"banner": null,
"banner_color": null,
"accent_color": null
}
Using a library
Alternatively, you may be able to use a Discord library to do this instead. The following examples also handle rate limits.
#discordjs/rest + discord-api-types
const {REST} = require('#discordjs/rest')
const {Routes} = require('discord-api-types/v9')
const token = 'YOUR_TOKEN'
const rest = new REST().setToken(token)
const fetchUser = async id => rest.get(Routes.user(id))
The result would be the same JSON as described above.
For TypeScript users:
import type {RESTGetAPIUserResult, Snowflake} from 'discord-api-types/v9'
const fetchUser = async (id: Snowflake): Promise<RESTGetAPIUserResult> =>
rest.get(Routes.user(id)) as Promise<RESTGetAPIUserResult>
discord.js
When I first posted this answer, #discordjs/rest didn't exist yet.
const {Client} = require('discord.js')
const token = 'YOUR_TOKEN'
const client = new Client({intents: []})
client.token = token
const fetchUser = async id => client.users.fetch(id)
The result of fetchUser would be a discord.js User object.

Something you can do is
let user = message.guild.cache.get('id');
(modified by #cherryblossom)

Related

Initialise Azure Application Client in TypeScript

New to Typescript and still getting used to Microsoft Azure so please excuse the basic question.
I have created an Enterprise Application which should be able to log into the Graph API and read a user profile. I have the client id/secret , tenant id but I need to know how to initialise this client within TypeScript.
Am i supposed to initialise a GraphClient or is there a a generic Client I can use?
A link to a tutorial/example or documentation on how to do this would be amazing.
For context I want to be able to write one function to initialise the client and subsequently write the query- all the docs talk about multiple files which I cannot utilise because I am writing this as a third party integration.
I have found this but it seems very complex and I can't really follow it.
Is there a typescript equivalent of
client_credential = ClientSecretCredential(tenant_id, client_id, client_secret)
client = GraphClient(credential=self.client_credential,
scopes=['https://graph.microsoft.com/.default']
)
This is the way I've managed to do it. I'm bounded by using an extremely old version of the microsoft graph module unfortunately.
const qs = require('qs');
const MicrosoftGraphClient = require('#microsoft/microsoft-graph-client#1.0.0');
const axios = require('axios#0.27.2');
const getToken = async () => {
try{
const response = await axios.post(
`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`,
qs.stringify(
{
client_id : clientId,
client_secret: clientSecret,
scope: 'https://graph.microsoft.com/.default',
grant_type: 'client_credentials'
}
))
let tokenSet = response.data;
return tokenSet.access_token;
} catch (error){
console.log(error)
};
}
var client = MicrosoftGraphClient.Client.init({
authProvider: async (done) => {
const token = await getToken()
done(null, token);
}
});

How to fetch discord member list

I'm trying to fetch the member list of a discord server. The Discord bot is inside the server and has admin permission. I'm referring to this part of the documentation Discord Docs.
const response = await fetch(`https://discord.com/api/guilds/685509789178003502/members`, {
headers: {
Authorization: `Bot ${botToken}`
}
})
var currentUser = await response.json()
This is the response I'm getting
{"message":"Missing Access","code":50001}
I checked it like a million times and the bot has admin perms 100%.
Enable Members Intent
Further Reading: https://gist.github.com/advaith1/e69bcc1cdd6d0087322734451f15aa2f

Most ideal way to call firebase getIdToken

i am implementing user authentication with the help of firebase in my React project. So, I am confused over something.
I am verifying the user from firebase and then getting a token on frontend which is sent to backend via headers and verfied there once.
I read the docs and came to know that firebase token gets expired after 1 hr by default so we have to use "getIdToken" like
firebase.auth().onAuthStateChanged(async user => {
if (user) {
console.log(user, 'user123 inside firebaseAuth')
const token = await user.getIdToken()
Cookies.set('my_token', token, { domain: domain })
}
})
but how do i manage this function , do i have to call it everytime the component updates or everytime before hitting api or first time the component renders ?
The thing is i do not want this token to get expire until the user logs out himself / herself even if he is in a different component and sitting ideal for too long.
You can get the Firebase ID Token every time you are making an API call to your server:
async function callAPI() {
const user = firebase.auth().currentUser
if (user) {
const token = await user.getIdToken()
const res = await fetch("url", {
headers: {authorization: `Bearer ${token}`}
})
} else {
console.log("No user is logged in")
}
}
You could get the ID token once when the component mounts but then you'll have to deal with onIdTokenChanged to keep it updated in your state. Using the method above you'll get a valid token always.

Sending FCM messages to web apps through firebase cloud functions

Is it possible to send FCM notifications through Firebase Cloud Functions, when a Firestore data field changes, but for a website, not an app. There is lots of guidance out there for Android and iOS but nothing for simply web apps, outside of sending notifications from the Firebase Console).
I've been trying to find out how to trigger a notification from Cloud Functions but can't find anything useful.
As an example, my database has the following structure:
Collection: users
Documents: documents named using userID
Data Fields: Fields 1 through 5. Field 5 stores the FCM Token. Field 1 stores their status (online, offline, offline pending messages).
I would like to ensure that when Data Field 1 changes (to 'offline pending messages), that the relevant user gets notified (based on the Doc ID).
Edit: adding code below for reference
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users/{doc}/{Hears}')
.onUpdate(async (change, context) => {
const db = admin.firestore();
db.collection('users').doc(context.params.userId) // get userId
.get()
.then(doc => {
//this is intended to get the FCM token stored in the user's document
const fcmToken = doc.data().usrTkn;
// Notification details
const payload = {
notification: {
title: 'You have a new message.',
body: 'Open your app'
}
};
})
//This should send a notification to the user's device when web app is not in focus.
//FCM is set up in service worker
const response = await admin.messaging().sendToDevice(fcmToken, payload);
console.log(response);
});
Sending messages to a web app is no different from sending it to a native mobile app, so the sending part of guidance you've found is equally applicable. The Firebase documentation even contains an example of sending notifications on a Realtime Database trigger, and doing the same for Firestore would not be much different.
If you're having a specific problem sending messages, I recommend showing what you tried, and what isn't working about it.
Update: your code doesn't work (no matter what sort of device you send the notification to), because you're not handling the asynchronous nature of get() in your code.
The simplest way to fix that is to use await there too, just like you do when calling sendToDevice. So:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users/{doc}/{Hears}')
.onUpdate(async (change, context) => {
const db = admin.firestore();
const doc = await db.collection('users').doc(context.params.userId).get();
const fcmToken = doc.data().usrTkn;
const payload = {
notification: {
title: 'You have a new message.',
body: 'Open your app'
}
};
const response = await admin.messaging().sendToDevice(fcmToken, payload);
console.log(response);
})
I highly recommend spending some time on learning about asynchronous calls, closures, async/await, and how to debug something like this by adding logging.

How to integrate Discord.js and twit with each other for a live Twitter feed on a specified channel

Is it possible to make a crawler with Twit and is it also possible to output the received data in a Discord channel? Currently I have made a script with both modules and it's working fine. The console output works for Discord.js and Twit at the same time. I have entered the token for Discord and the several keys for the Twitter API. But my goal is a bit more complex. With twit I need to make a crawler that crawls tweets from twitter accounts in real-time and Discord.js is supposed to output this data in a Discord channel. Does anyone have any idea how to do this? I tried to experiment with the stream function of Twit but couldn't figure out how it works exactly. It crawled random tweets from any time span. I'm not sure how to configure it. And even if I figured that out I still need to integrate it with Discord.js
The simplest way is as follows:
const Discord = require('discord.js');
const Twitter = require('twit');
const twitterConf = {
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token: process.env.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
}
const client = new Discord.Client();
const twitterClient = new Twitter(twitterConf);
// Specify destination channel ID below
const dest = '11111111111111111111';
// Create a stream to follow tweets
const stream = twitterClient.stream('statuses/filter', {
follow: '2899773086', // #Every3Minutes, specify whichever Twitter ID you want to follow
});
stream.on('tweet', tweet => {
const twitterMessage = `${tweet.user.name} (#${tweet.user.screen_name}) tweeted this: https://twitter.com/${tweet.user.screen_name}/status/${tweet.id_str}`
client.channels.get(dest).send(twitterMessage);
return false;
});
client.on('ready', () => {
console.log(`I'm in`);
});
client.login(process.env.DISCORD_TOKEN);
Of course the following assumes that you have Discord and Twitter keys specified in proper environment variables.
NOTE: By default, stream will contains more than user's own tweets: retweets, replies. You can easily filter them using the following function (not mine, source noted):
// SOURCE:
// https://github.com/ttezel/twit/issues/286#issuecomment-236315960
function isReply(tweet) {
if (tweet.retweeted_status
|| tweet.in_reply_to_status_id
|| tweet.in_reply_to_status_id_str
|| tweet.in_reply_to_user_id
|| tweet.in_reply_to_user_id_str
|| tweet.in_reply_to_screen_name) return true;
return false;
}
For testing purposes I used #Every3Minutes here, as it tweets every 3 minutes, which was nice for my testing.
I would do it this way :
Create a stream for each user you want to track. (this may help you to target a user)
Then link each stream.on('tweet' to a response of your discord bot.

Categories

Resources