I am in the progress of making a discord bot. This is one of the commands that auto-does itself.
What it is supposed to do it's if someone type .team buy 1, save the data that comes out of another bot.
I would like to whitelist this command to 2 specific channels, identified by their channel id, and just ignore the message if it is not in the 2 channels.
How can I edit the code to do it?
const fs = require("fs");
module.exports.run = (client, message) => {
if ([509042284793430032, 501784044649054231].includes(message.channel.id)) return;
try {
//check if it's a different message //like when a user enters "team buy 234"
if (message.embeds[0].description.indexOf("❓") === 0) return;
//retrieve the team data
var teamData = JSON.parse(fs.readFileSync(client.config.dataFolder + "/teamUpgrades.json", "utf8"));
//get the current purchases data from the message
var arr = message.embeds[0].description.split("\n");
//loop and save the data in "items" object
for (var i = 0; i < arr.length; i++) {
if (arr[i] == "") continue;
if (arr[i].indexOf("Unlocks") > -1) continue; //skip locked items
var opt = arr[i].split("|"); //item's info
var name = opt[0].trim();
if (name.indexOf("**") > -1)
name = name.substring(name.indexOf("**") + 2, name.length - 2).trim(); //bold
else
name = name.split(" ")[1]; //not bold
var price = opt[1].trim();
price = price.substring(3, price.length - 1);
price = parseInt(price.split(",").join(""));
var count = opt[2].trim();
count = parseInt(count.substring(1, count.length - 2).split(",").join(""));
var eps = opt[3].trim();
eps = parseFloat(eps.split(" ")[0].substring(1));
//if the item doesn't exist, create it
if (!teamData.items[name]) teamData.items[name] = {};
teamData.items[name].price = price;
teamData.items[name].eps = eps;
teamData.items[name].count = count;
}
//the best item to buy, let's give it a very high number first
var minItem = {
name: "",
min: Number.MAX_SAFE_INTEGER
};
for (var name in teamData.items) {
//The average price/eps
var average = Number(teamData.items[name].price) / Number(teamData.items[name].eps);
//if the current item is less than the minimum item, replace it.
if (average < minItem.min) {
minItem.name = name;
minItem.min = average;
}
}
//write the current data into the json file
fs.writeFileSync(client.config.dataFolder + "/teamUpgrades.json", JSON.stringify(teamData));
message.channel.send(minItem.name);
} catch (err) {
console.log(err);
}
}
You can check if message.channel.id is equal to one of your IDs and if not, ignore it.
module.exports.run = (client, message) => {
if (['ID 1 here', 'ID 2 here'].includes(message.channel.id)) return;
};
Related
At the moment, I manually create code then manually ask the user to set the trigger for the said function in order for the said user to receive a task and update task.
Heres an example of my coding:
User's Function
function Person1Variables () {
taskedPerson = assignedPerson.filter(x => x == "Person1 (assigned by Somebody)").length
taskReceiver = "Person1 (assigned by Somebody)"
taskReceived = "Person1 (Sent)"
functionCaller = "Person1 "
myTask = "My Tasks"
}
function taskSendPerson1() {
Person1Variables()
if (taskedPerson + 1 > 1){taskSending(taskTitle(myTask)); console.log("Snag")}
}
function updateTaskPerson1() {
Person1Variables()
taskComplete(taskTitle(myTask));
}
Task Creation and Update
function taskTitle(titleTasksList) {
if (typeof titleTasksList === 'undefined') { titleTasksList = 'default'; }
var rezultId = 0;
var response = Tasks.Tasklists.list();
var taskLists = response.items;
if (taskLists && taskLists.length > 0) {
for (var i = 0; i < taskLists.length; i++) {
var taskList = taskLists[i];
if (titleTasksList == 'default') {
rezultId = taskList.id; //return first item
break;
} else {
Logger.log('%s (%s)', taskList.title, taskList.id);
if (titleTasksList == taskList.title) {
rezultId = taskList.id;
break;
}
}
}
} else {
Logger.log('No task lists found.');
}
return rezultId;
}
function taskSending(taskListId) {
// Task details with title and notes for inserting new task
var currentResult = 1
var nextResult = 1
for (var resultsFound = 0; resultsFound < taskedPerson; resultsFound++){
console.log("pong")
var searchEngine = "Assigned Person"
var searchRange = sheet.getRange(nextResult,(lastColumn[0].indexOf(searchEngine) + 1),
sheet.getLastRow(), 1)
var searchRangeValues= searchRange.getValues()
currentResult = searchRangeValues.map(String).indexOf(taskReceiver) + nextResult
var resultTitle = responseNumber[currentResult -1]
var resultNote = typeSupport[currentResult - 1] + " = " + typeRequest[currentResult - 1]
let task = {
title: String(resultTitle),
notes: resultNote,
};
// Call insert method with taskDetails and taskListId to insert Task to specified tasklist.
console.log(task)
console.log(taskListId)
task = Tasks.Tasks.insert(task, taskListId);
// Print the Task ID of created task.
Logger.log('Task with ID "%s" was created.', task.id);
sheet.getRange(currentResult,2).setValue (taskReceived)
nextResult = currentResult + 1
console.log(nextResult + " " + "processed")
}
}
function newTask(taskListId) {
// Task details with title and notes for inserting new task
var allResults = [];
var allTitles = [];
for (var j = 0; j < itemResponses.length + 1; j++) {
var itemResponse = itemResponses[j];
for (var g = 0; g < 30; g++){ try {allResults [g] = String(itemResponses[g].getResponse()); allTitles [g] = itemResponses[g].getItem().getTitle();var lastResponse = g} catch(err) {}}
}
console.log("PING")
var refNumber = new Date().getFullYear().toString().substr(-2) + String(("00000000" + (formResponses.length))).substr(String(("00000000" + (formResponses.length))).length - 8);
let task = {
title: refNumber,
notes: allTitles [3] + " = " + allResults [3],
};
try {
// Call insert method with taskDetails and taskListId to insert Task to specified tasklist.
task = Tasks.Tasks.insert(task, taskListId);
// Print the Task ID of created task.
Logger.log('Task with ID "%s" was created.', task.id);
} catch (err) {
// TODO (developer) - Handle exception from Tasks.insert() of Task API
Logger.log('Failed with an error %s', err.message);
}
}
function taskComplete(taskListId) {
var optionalArgs = {
maxResults: 100,
showHidden: true
};
var tasks = Tasks.Tasks.list(taskListId, optionalArgs);
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
for (var x = 0; x < responseNumber.length; x++){
if (responseNumber[x] == task.title){sheet.getRange(x + 1,lastColumn[0].indexOf("Status")+1).setValue(task.status); }
}
}
var dataFound = 0
//Tasks.Tasks.remove(taskListId,tasks.items[dataFound].id)
for (var x = 0; x < responseNumber.length; x++)
{try{if (tasks.items[dataFound].status == "completed" && (responseNumber.map(String).indexOf(String(tasks.items[dataFound].title))) > 1){Tasks.Tasks.remove(taskListId,tasks.items[dataFound].id); sheet.getRange(responseNumber.map(String).indexOf(String(tasks.items[dataFound].title)) + 1,lastColumn[0].indexOf("Assigned Person")+1).setValue(functionCaller)}; dataFound++} catch(err){}}
}
}
My plan was to create a button that can detect if that user has or has not created a function. If the user does not have dedicated function, then this button will create a function and assigned the trigger.
You don't need another function. The typical way to handle per user data is to store it in propertiesService and link it to triggerUid of the installed trigger.
Related:
Best way to create and manage someone's triggers (GAS)
Can the function called by ScriptApp.newTrigger identify the triggerID?
Is it possible to create a function on the fly and create triggers though? Maybe as a two step process through google-apps-script-api, but it's unnecessarily complicated for your case.
for the last 3 days (my first 3 days of coding) i've been trying to code an script to get my google contacts that have certain keyword, it being "Catamarca", on their name and also to delete that keyword after they've been added to the spreadsheet leaving only their name.
I've been succesfull in all of this. But now i want to only run the script on an existing database, and only run it if the new contacts are not on the sheet already, and not write over the existing ones.
Here is my code so far:
function impContacts() {
// variables
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GContacts");
var grupo = ContactsApp.getContactGroupById("http://www.google.com/m8/feeds/groups/email#gmail.com/base/6")
const contactos = grupo.getContacts();
const arraycontacts = [];
// get the last row on B with data on it
const lastRow = sheet.getLastRow();
const Avals = sheet.getRange("B2:B" + lastRow).getValues();
const Alast = lastRow - Avals.reverse().findIndex(c => c[0] != '');
Logger.log(Alast);
var rangeInteres = sheet.getRange(2, 1, Alast, sheet.getLastColumn()).getValues();
// look for contacts that has in their name the word "Catamarca", and save them with their id, name and phone.
contactos.forEach(contacto => {
var phone = ""
if (contacto.getPhones()[0]) {
phone = contacto.getPhones()[0].getPhoneNumber()
};
var name = ""
if (contacto.getFullName().match("Catamarca")){
name = contacto.getFullName();
};
var idcont = ""
if (name == rangeInteres.forEach(namme =>
{
oldName = namme[1];
Logger.log(oldName);}))
{
idcont =
rangeInteres.forEach(id => {
oldId= id[0];
Logger.log(oldId);})
}
else
{
idcont = contacto.getId().replace(/\D/g, '')
};
const datoscont = [idcont, name, phone];
arraycontacts.push(datoscont);
})
// save new contact
sheet.getRange(2, 1, arraycontacts.length, 3).setValues(arraycontacts);
// look for "catamarca"
range = sheet.getRange("B2:B")
var textFind = range.createTextFinder("Catamarca");
textFind.matchEntireCell(false);
textFind.ignoreDiacritics(true);
textFind.matchCase(false);
var textFound = textFind.findNext();
// Si encuentra coincidencia reemplazar por ""
if (textFound !== null) {
var vals = textFound.getValues();
textFind.replaceAllWith("");
}
}
What i need to keep the most is the ID of the existing contacts (the IDs are different from the ones coming from google contacts but the names are the same), because they are linked to an app created using AppSheet.
I believe there should be a way to accomplish this by editing this part of the code
var idcont = ""
if (name == rangeInteres.forEach(namme =>
{
oldName = namme[1];
Logger.log(oldName);}))
{
idcont =
rangeInteres.forEach(id => {
oldId= id[0];
Logger.log(oldId);})
}
else
{
idcont = contacto.getId().replace(/\D/g, '')
};
In my head and with my current knowledge, the code should be working, but it's not, I mean, it runs, but overwrites everything.
I have this script below, that emails the person a copy of all of their assigned tasks that are not complete.
However, I would like it to skip all Tasks where the Main Projects status is "backlog"
Here is my current code, and a link to a copy of the tables:
function sendEmails() {
// Retrieve Project IDs, Project names and Project Status
const project = sheetITPM.getRange("A2:J" + sheetITPM.getLastRow()).getValues().map(r => ({ id: r[0], name: r[1], status: r[2]}));
//get Tasks Sheet and all rows needed
let s = '';
const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ITPM_Tasks");
const lastRow = sh.getLastRow();
const startRow = 2; // First row of data to process
const numRows = lastRow - 1; // Number of rows to process
const rg = sh.getRange(startRow, 3, numRows, 6);
const vs = rg.getValues();
let oners = {pA:[]};
//function to NOT include projects with status: "backlog"
//dont include tasks with status "Complete"
vs.forEach((r,i) => {
let [name,desc,status,owner,due] = r;
if(status != 'Complete') {
if(!oners.hasOwnProperty(owner)) {
oners[owner]=[];
oners[owner].push(r);
oners.pA.push(owner)
} else {
oners[owner].push(r);
}
}
});
//email subject and start message
let subject = 'IT Board - Weekly Reminder: The following tasks are assigned to you.';
oners.pA.forEach(p => {
let msg = `These Tasks below are assigned to you:\n`
//task array
oners[p].forEach((r,i) => {
let [name,desc,status,owner,due] = r;
msg += `Task - ${i+1}\n`;
msg += `Description: ${desc}\n`;
msg += `Due Date: ${due}\n\n`
});
msg += `notify the IT Project Management Team of any updates\n\nThank You`;
//send email to the task owner with their task array + subject + our message
MailApp.sendEmail(oners[p][0][3], subject, msg);
});
}
Link to sheet:
https://docs.google.com/spreadsheets/d/1aGojtDy9sDpGexiT_ixF_H_95GG_uiYeAkNUWzYkKSE/edit?usp=sharing
You can try getting the list of IDs for backlog projects first and then using includes to check if the project name of the task belongs to the list of IDs. See code below:
Script:
let oners = {pA:[]};
// get backlog projects, then create an array containing the ids of those projects
const backlogProjects = project.filter(x => x.status == 'Backlog').map(x => x.id);
// dont include tasks with status "Complete"
vs.forEach((r,i) => {
let [name,desc,status,owner,due] = r;
// check if project name matches the IDs present in the generated array above
if(status != 'Complete' && !backlogProjects.includes(name)) {
if(!oners.hasOwnProperty(owner)) {
oners[owner]=[];
oners[owner].push(r);
oners.pA.push(owner)
} else {
oners[owner].push(r);
}
}
});
Output:
Output shows no nl7k28t in the tasks as that project is still in Backlog status.
I am trying to write an Appscript/Javascript that can match a project to its tasks and notes relationship. Grab all the tasks + notes for each project and email the owner of the project. Im not sure how to do this at all. Since they are in three diffrent sheets.
Right now I have a script to send Weekly emails for each persons tasks assigned to them that works becasue it only requires the single IPTM_Task sheet.
My spreadsheet looks like this Tasks:
Task Sheet
SubTasks:
Subtasks
Notes:
Notes
Script to email task owners
function sendEmails() {
let s = '';
const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ITPM_Tasks");
const lastRow = sh.getLastRow();
const startRow = 2; // First row of data to process
const numRows = lastRow - 1; // Number of rows to process
const rg = sh.getRange(startRow, 3, numRows, 6);
const vs = rg.getValues();
let oners = {pA:[]};
vs.forEach((r,i) => {
let [name,desc,status,owner,due] = r;
if(status != 'Complete') {
if(!oners.hasOwnProperty(owner)) {
oners[owner]=[];
oners[owner].push(r);
oners.pA.push(owner)
} else {
oners[owner].push(r);
}
}
});
let subject = 'Weekly Reminder: The following tasks are assigned to you.';
oners.pA.forEach(p => {
let msg = `These Tasks below are assigned to you:\n`
oners[p].forEach((r,i) => {
let [name,desc,status,owner,due] = r;
msg += `Task - ${i+1}\n`;
msg += `Description: ${desc}\n`;
msg += `Due Date: ${due.toDateString()}\n\n`
});
msg += `some message to task owners`;
MailApp.sendEmail(oners[p][0][3], subject, msg);
});
}
EDIT:
Basically, I would like the script to see the Project ID on the Task Sheet grab the project name (Project) and the Owner
Then find the related "SubTask" Project Names" and related "Notes" to that project name
and send the Project owner an email with
Project Name
Subtask 1
subtask 2...
Note 1
Note 2
idealoutput
Makes sense to break it down, e.g.like this:
const ss = SpreadsheetApp.getActive()
const projects = ss.getSheetByName("Task Sheet").getDataRange().getValues()
projects.forEach( project => {
const projectId = project[0]
const status = project[2]
if( status.toLowerCase() == "completed") return
const notes = getNotesByProjectId(projectId)
const subtasks = getSubtasksByProjectId(projectId)
// here you can build your message
let message = ""
notes.forEach( note => {
// add conditions here
message += note[2] + "\n"
})
subtasks.forEach( subtask => {
// add conditions here
message += subtask[3] + "\n"
})
// and then send it
})
function getNotesByProjectId( projectId ){
const allNotes = ss.getSheetByName("Notes").getDataRange().getValues()
// Filter where Column 2 (index 1) is the project
const filteredNotes = allNotes.filter( note => note[1] == projectId )
return filteredNotes
}
function getSubtasksByProjectId( projectId ){
const allNotes = ss.getSheetByName("Subtasks").getDataRange().getValues()
// Filter where Column 3 (index 2) is the project
const filteredNotes = allNotes.filter( note => note[2] == projectId )
return filteredNotes
}
Reference
Sheet.getDataRange
I'm creating a guest list program that stores the guest list in Firebase RTDB and when I check people in and out my function runs several times more than it is supposed to. I've sent alerts to the console so I know how many times it has run. I have separate functions for both check in and check out operations so it may be that I am calling my db too many times?
//-------------------- Check In and Check In Helper Functions -------------------------
//Helper Function to Grab current List index
function printArray() {
var ref = database.ref('guestList')
ref.on('value', readData, errData);
}
function readData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkIn(guestList);
}
function errData(err){
console.log('Error!');
console.log(err);
}
//Helper Function to set text box to selected name
function checkInn(name){
console.log(name)
document.getElementById('checkIn').value = name;
}
//Check in
function checkIn(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkIn').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "Yes",
TimeIn: getTime(),
})
guestsRef.off();
document.getElementById('checkIn').value = "";
alerts(name, true)
}
})
}
//------------------------- Check Out ------------------------------------------------------------
//Helper Function to Grab current List index
function printArrayy() {
var ref = database.ref('guestList')
ref.on('value', readOutData, errData);
}
function readOutData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkOut(guestList);
}
//Helper Function to set text box to selected name
function checkOutt(name){
console.log(name);
document.getElementById('checkOut').value = name;
}
//Check Out
function checkOut(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkOut').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "No",
TimeOut: getTime(),
})
document.getElementById('checkOut').value = "";
guestsRef.off();
alerts(name, false)
}
})
}
//Placeholder to alert user when a succesful check in or check out function runs
function alerts(name, Boolean){
if(Boolean){
console.log(name + " has been checked in!")
}
else{
console.log(name + " has been checked out!")
}
}
Here is the screenshot of my output. Thanks in advance!
Edit: Forgot to mention and apologize for my excessive use of helper functions! My HTML form calls printArrayy() and printArray first for each function!
have you tried once instep on, i mean:
ref.once('value', readOutData, errData); }