// command for starting request with a simple anti-spam shiet
bot.command('movie', (ctx) => {
let stopSpam = findUserData(ctx);
if (stopSpam) {
ctx.reply(spammerMsg)
} else {
userData.push({id: ctx.message.from.id, msgId: ctx.message.message_id});
ctx.reply('Género',genreMenu);
}
});
// So the issue is right here.
//Right now I'm checking if the user has already used the comand 'movie'.
//If so, he could use its buttons. But he could use the buttons from another user too...
bot.action(/.+/,(ctx) => {
let allowed = findUserCallbackData(ctx);
if (allowed) {
ctx.editMessageReplyMarkup((m) => m.inlineKeyboard([]));
allowed.queryGenre = ctx.update.callback_query.data;
ctx.reply('Época', timeMenu)
.then(() => {
ctx.deleteMessage(ctx.update.callback_query.message.message_id)
})
.catch(e => {
console.log(e)
})
} else {
console.log('noppe')
}
});
findUserData = (ctx) => {
let findCmdUser = userData.find(user => user.id === ctx.message.from.id)
return findCmdUser
}
findUserCallbackData = (ctx) => {
let findUser = userData.find(user => user.id === ctx.update.callback_query.from.id)
return findUser
}
I'm in a cinema telegram group and I'm making a bot for movies recomendations using inline keyboard as data giver.
The issue is inline keyboard is not only visible but interactive for every single group member.
So my question is, can I prevent this from happening somehow? Can I make the inline keyboard only accesible (and visible, if possible) for the user which inserts the proper command?
Sorry for my basic English and thank's for your time.
Inline keyboard is attached directly to message so it's not possible to make it visible for some participants only.
Related
I am trying to build a bot with the discord.js library in node.js that will create a new voice channel in a certain category when a user joins a certain channel. After the creation of the channel, I want the bot to then move the user to the new channel!
I am trying the following code:
var temporary = [];
client.on('voiceStateUpdate', async (oldMember, newMember) => {
const mainCatagory = '815281015207624704';
const mainChannel = '814938402137833484';
if (newMember.voiceChannelID == mainChannel) {
await newMember.guild
.createChannel(`📞 ┋ Support Room`, { type: 'voice', parent: mainCatagory })
.then(async (channel) => {
temporary.push({ newID: channel.id, guild: newMember.guild.id });
await newMember.setVoiceChannel(channel.id);
});
}
if (temporary.length >= 0)
for (let i = 0; i < temporary.length; i++) {
let ch = client.guilds
.find((x) => x.id === temporary[i].guild)
.channels.find((x) => x.id === temporary[i].newID);
if (ch.members.size <= 0) {
await ch.delete();
return temporary.splice(i, 1);
}
}
});
The code comes with no error but doesn't create the voice channel!
The problem is that you are using discord.js v12, but your code is made for v11.
Client#voiceStateUpdate now passes VoiceStates as parameters, not GuildMembers. You should rename newMember and oldMember to newState and oldState respectively.
GuildMember#voiceChannelID is a deprecated property, which is why you don't get any errors. Your code never actually gets past the if statement. It has turned into GuildMember#voice#channelID (newState.channelID).
Guild#createChannel is also deprecated, being replaced with Guild#channels#create. The function still looks and acts the same, so you only need to change the name (newState.guild.channels.create).
GuildMember#setVoiceChannel has turned into GuildMember#voice#setChannel (newState.setChannel)
Client#guilds#find has turned into Client#guilds#cache#find (client.guilds.cache.find)
Guild#channels#find has turned into Guild#channels#cache#find (client.cache.find(...).channels.cache.find)
(As a side note, always use Collection#get instead of Collection#find when searching by IDs. .find((value) => value.id === '...') should always be converted to simply .get('...'). This also applies to switching Collection#some with Collection#has)
Guild#members#size has turned into Guild#members#cache#size (ch.members.cache.size)
Every single one of these deprecations occurred as a result of discord.js switching to a Manager/caching system. For example, Client#guilds now returns a GuildManager instead of a collection.
More information about switching from v11 to v12 (including Managers)
I'm new to Next js and im trying to implement a live search input field, I'm not sure if I have done things right if im violating some principles of next by not using getServerProps for this matter, what I have currently done is simply call an API and save the result in a simple state
const handleInputChange = (event) => {
const query = event.target.value;
setQuery(query);
if (event.target.value.length < 3) {
setResults([]);
return;
}
setLoading(true);
fetchSearchResults(query);
};
const fetchSearchResults = async (paginate = "", query) => {
if (query === "") {
setResults([]);
}
const searchUrl = [uri];
await axios
.get(searchUrl)
.then((res) => setResults(res.data.results))
.catch((error) => setMessage("No data found"));
};
Is there a better way to do such thing in next js(production ready)? Thanks
edit:
I found a way that could probably solve this by using getStaticProps with revalidate, however this is a component in the header that's on all pages and not a page, getStaticProps won't work here, is there a way around this?
To be clear I have a list of products, and the header contains a search bar that would function as an input for live search of these products
So I have a bot, then I want to make the bot can collect a message, then reply if he detect a spesific word, but the problem is my bot keep creating new collector if someone type the tekong, so when the bot detect the word it will gonna respond twice, depend on how many collector are created. How do I make the bot so that 1 person can only create 1
Here's my code
client.on("message", (message) => {
if (message.content.toLowerCase().startsWith('tekong')) {
message.channel.send('Bot is collector messages...')
let filter = m => m.content.includes('test') && m.author.id === '744882468741709824'
let collector = message.channel.createMessageCollector(filter, {max: 1})
collector.on('collect', indonesia => {
console.log(indonesia.content);
})
collector.on('end', m => {
console.log(`Collected ${m.size} items`)
if (m.size === 1) {
message.channel.send('Congratulations your enchantments is works!')
}
})
}
You can just simply make a Set ( Array would also be an option, but I prefer Set as its easier to delete entries):
let blocked = new Set();
Then inside your message event you can use:
if (message.content.toLowerCase().startsWith('tekong')) {
if(blocked.has(message.author.id)) return;
blocked.add(message.author.id);
If you are done and want the user to allow to use the command again, you can simply use:
blocked.delete(message.author.id);
I'm writing a cloud function that uses request-promise and cheerio to scrape a website and then check that information against a user document.
I am not entirely familiar with Javascript and Cloud Functions.
I've come so far that I managed to extract the information I need and navigate to the user's document and compare the data. Now the last piece of this function is to give the user points for each matching data point, so I need to update a map inside the user document.
This function has to loop through all users and change their document if the data point matches. I'm not sure the way I've written the code is the most optimal in terms of performance and billing if the userbase gets huge... Any pointers to how I could minimize the impact on the task would be of great help, as im new with JS.
So this is the code:
exports.getV75Results = functions.pubsub.schedule('every 2 minutes').onRun(async (context) => {
let linkMap = new Map();
const url = `https://www.example.com`
const options = {
uri: url,
headers: { 'User-Agent': 'test' },
transform: (body) => cheerio.load(body)
}
await rp(options)
.then(($) => {
for(let i = 1; i <= 7; i++)
{
//Find player from game
const lopp1 = $(`#mainContentHolder > div > div.mainContentStyleTrot > div > div.panel-body > table:nth-child(1) > tbody > tr:nth-child(${i}) > td:nth-child(2) > span`).text()
const lopp1StrR1 = lopp1.replace("(", "");
const lopp1StrR2 = lopp1StrR1.replace(")", "");
const lopp1StrR3 = lopp1StrR2.replace(" ", "");
linkMap.set(i, lopp1StrR3.toUpperCase());
}
console.log(linkMap);
return linkMap;
}).then(async () => {
//Start lookup users
let usersRef = db.collection('fantasyfotball').doc('users');
usersRef.listCollections().then(collections => {
collections.forEach( collection => {
var user = collection.doc(collection.id);
let batch = new admin.firestore().batch();
user.get().then(function(doc) {
let json = doc.data();
//Look in users collection if players document exist
Object.keys(json).forEach((name) => {
if(name != null) {
//Document with users active fotball players
if(name == 'players') {
let i = 0;
Object.values(json[name]).forEach((value) => {
i++;
if(value.localeCompare(linkMap.get(i)) == 0) {
//Loop through user keys and find owned players if user has the correct player
Object.keys(json).forEach((map) => {
if(map != null)
{
//Document with a map of player owned fotball players, each respective player has a key = 'fotball player' and value = '[price, points]'
if(map == 'ownedplayers')
{
Object.entries(json[map]).forEach((players) => {
if(players[0].localeCompare(value) == 0) {
console.log(players[1][1]);
//Add points to respective player field
//PROBABLY NOT HOW TO CHANGE A DOCUMENT FILED, THIS DOESNT WORK..
players[1][1]++;
}
});
//EACH TIME THIS RUNS IT SAYS: "Cannot modify a WriteBatch that has been committed"
batch.update(user, {'ownedplayers': json[map]});
}
}
});
}
});
}
} else {
console.log('user does not have a playermode document.');
}
});
});
return batch.commit().then(function () {
console.log("Succesfully commited changes.");
return null;
});
});
});
}).catch((err) => {
return err;
});
});
The issues i get in the console are "Cannot modify a WriteBatch that has been committed." and I fail to modify and add points to the player field inside the users document.
This is the console:
This is the firestore document structure:
I'm completely stuck on this.. Feels like I've tried all different approaches, but I think i dont fully understand cloud functions and javascript, so i would gladly recive feedback and help on how to make this work.
Cheers,
Finally.... i managed to update the document successfully. I put the commit outside another ".then()". Thought I tried that, but yay I guess :P
}).then(() => {
return batch.commit().then(function () {
console.log("Succesfully commited changes.");
return null;
});
The problem now is that it commits every loop. I think the most optimal here would be to batch update ALL users before committing?
And again, is there a more optimal way to do this, in terms of minimizing the operation and impact? I'm afraid I go too deep with for loops instead of directly navigating to the document, but haven't found an easier way to do that.
Any thoughts?
I want to add a code to my bot where it will send a message when a specific user plays a specific game (i.e. Left 4 Dead 2). How do I do that? I don't want any commands anymore.
// Game Art Sender //
if (message.channel.id === '573671522116304901') {
if (msg.includes('!L4D2')) { // THIS is what I want to change.
message.channel.send('***[MATURE CONTENT]*** **Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/573671522116304901/573676850920947733/SPOILER_l4d2.png"
]
});
}
});
Try this
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here')
// do whatever here
GuildMember.id could also be used if you know that user's specific id string. I haven't tested this myself and I'd have rather posted this as a comment, but I don't have that permission yet.
To send a message to a specific channel, use this:
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send("MESSAGE GOES HERE")
or
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send(VARIABLE_GOES_HERE)
Summing it up, your code should be something like this:
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here') {
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE)
channel.send("MESSAGE GOES HERE")
}
So I just figured it out. It was a long journey to figuring this one out.
Here's the code:
// Game Detector \\
client.on("presenceUpdate", (oldMember, newMember) => {
if(newMember.id === '406742915352756235') {
if(newMember.presence.game.name === 'ROBLOX') { // New Example: ROBLOX
console.log('ROBLOX detected!');
client.channels.get('573671522116304901').send('**Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/567519197052272692/579177282283896842/rblx1.png"
]
});
}
}
});
However, I need one more problem solved:
It says "null" when I close the application.
How do I fix this?