I am trying to block spam and 800#s in one shot using a twilio function, but it's not working...
You could modify the function as below:
exports.handler = function(context, event, callback) {
// set-up the variables that this Function will use to forward a phone call using TwiML
// REQUIRED - you must set this to the number you want calls forwarded to
let phoneNumber = event.PhoneNumber || "+16787801234";
// OPTIONAL
let callerId = event.CallerId || null;
// OPTIONAL
let timeout = event.Timeout || null;
// OPTIONAL +266696687 = ANONYMOUS Callers
let blacklistedCallers = event.blacklistedCallers || ["+14073601234","+15185001234", "+266696687"];
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
console.log(event.From.substring(0,5));
let allowedThrough = false;
if (blacklistedCallers.length > 0) {
if ((blacklistedCallers.indexOf(event.From) === -1) && (event.From.substring(0,5) != "+1800")) {
allowedThrough = true;
}
}
let dialParams = {};
if (callerId) {
dialParams.callerId = callerId;
}
if (timeout) {
dialParams.timeout = timeout;
}
if (allowedThrough) {
twiml.dial(dialParams, phoneNumber);
}
else {
twiml.reject({reason: 'rejected'});
}
// return the TwiML
callback(null, twiml);
};
Related
Is there some one who can really help here?
I can't get anything from sso.getGraphData in the office addin generated from Yeoman generator.
Here is my code in ssoauthhelper.js:
export async function getGraphData() {
try {
let bootstrapToken = await OfficeRuntime.auth.getAccessToken({ allowSignInPrompt: true });
let exchangeResponse = await sso.getGraphToken(bootstrapToken);
if (exchangeResponse.claims) {
// Microsoft Graph requires an additional form of authentication. Have the Office host
// get a new token using the Claims string, which tells AAD to prompt the user for all
// required forms of authentication.
let mfaBootstrapToken = await OfficeRuntime.auth.getAccessToken({ authChallenge: exchangeResponse.claims });
exchangeResponse = sso.getGraphToken(mfaBootstrapToken);
}
if (exchangeResponse.error) {
// AAD errors are returned to the client with HTTP code 200, so they do not trigger
// the catch block below.
documentHelper.writeDataToOfficeDocument("response");
handleAADErrors(exchangeResponse);
} else {
/*const response = await sso.makeGraphApiCall(exchangeResponse.access_token);
documentHelper.writeDataToOfficeDocument(response);*/
const _EndPoint = "/me/messages";
const _UrlParams = "?$select=receivedDateTime,subject,isRead&$orderby=receivedDateTime&$top=10";
const response = await sso.getGraphData(exchangeResponse.access_token, _EndPoint, _UrlParams);
documentHelper.writeDataToOfficeDocument(response);
sso.showMessage("Your data has been added to the document.");
}
} catch (exception) {
if (exception.code) {
if (sso.handleClientSideErrors(exception)) {
fallbackAuthHelper.dialogFallback();
}
} else {
sso.showMessage("EXCEPTION: " + JSON.stringify(exception));
}
}
}
the code in documentHelper.js:
function writeDataToExcel(result) {
/*return Excel.run(function (context) {
const sheet = context.workbook.worksheets.getActiveWorksheet();
let data = [];
let userProfileInfo = filterUserProfileInfo(result);
for (let i = 0; i < userProfileInfo.length; i++) {
if (userProfileInfo[i] !== null) {
let innerArray = [];
innerArray.push(userProfileInfo[i]);
data.push(innerArray);
}
}
const rangeAddress = `B5:B${5 + (data.length - 1)}`;
const range = sheet.getRange(rangeAddress);
range.values = data;
range.format.autofitColumns();
return context.sync();
});*/
return Excel.run(function (context) {
const sheet = context.workbook.worksheets.getActiveWorksheet();
const rangeHeadings = sheet.getRange("A1:D1");
rangeHeadings.valueTypes = [["ReceivedDateTime", "subject", "Read?", "ID"]];
const _Contents = result.value;
for (let i = 0; i < _Contents.length; i++) {
if (_Contents !== null) {
let _TempArr = [];
_TempArr.push(_Contents[i].receivedDateTime);
_TempArr.push(_Contents[i].subject);
_TempArr.push(_Contents[i].isRead);
_TempArr.push(_Contents[i].id);
let _Data = [];
_Data.push(_TempArr);
const _rangeaddress = `A${2 + i}:D${2 + i}`;
const _rangedata = sheet.getRange(_rangeaddress);
_rangedata.values = _Data;
}
}
rangeHeadings.format.autofitColumns();
return context.sync();
});
}
When i run the add-in, it does not proceed after GET/ auth? as shown in below image.
Here are my permission in the Azure APP Registration:
I can't understand what is really happening. When i click on the button in the sideloaded task pane, nothing is sent from the Graph API as shown in the command prompt image. I am really grateful, if someone could point out where the error is.
I have defined the scopes in my manifiest file as well.
Please help.
I am new to Twilio and want to include a kind of switch in my Studio Flow Chart that checks if we are in the defined business hours. If yes (success), it forwards to the number, if no (fail), it forwards to voicemail.
I tried to build a function, somewhat derived from this twilio git: https://github.com/twilio-labs/function-templates/tree/main/voicemail.
const moment = require('moment');
const DEFAULT_UTC_OFFSET = 0;
const DEFAULT_WORK_WEEK_START = 1; // Monday
const DEFAULT_WORK_WEEK_END = 5; // Friday
const DEFAULT_WORK_HOUR_START = 8; // 8:00, 8AM
const DEFAULT_WORK_HOUR_END = 18; // 18:59, 6:59PM
function getInteger(stringValue, defaultValue) {
const parsedNumber = parseInt(stringValue, 10);
if (isNaN(parsedNumber)) {
return defaultValue;
}
return parsedNumber;
}
exports.handler = function(context, event, callback) {
const timezone = getInteger(context.TIMEZONE_OFFSET, DEFAULT_UTC_OFFSET);
const workWeek = {
start: getInteger(context.WORK_WEEK_START, DEFAULT_WORK_WEEK_START),
end: getInteger(context.WORK_WEEK_END, DEFAULT_WORK_WEEK_END),
};
const workHour = {
start: getInteger(context.WORK_HOUR_START, DEFAULT_WORK_HOUR_START),
end: getInteger(context.WORK_HOUR_END, DEFAULT_WORK_HOUR_END),
};
const currentTime = moment().utcOffset(timezone);
const hour = currentTime.hour();
const day = currentTime.day();
// between monday and friday
const isWorkingDay = day <= workWeek.end && day >= workWeek.start;
// between 8am and 7pm
const isWorkingHour = hour <= workHour.end && hour >= workHour.start;
if (isWorkingDay && isWorkingHour) {
return true;
} else {
return false;
}
};
From the error I get (82002 – runtime application timed out), the callback must be different. What is the correct way for callback(err, response)?
Thanks.
Twilio developer evangelist here.
In a Twilio Function, in order to return a result you must call the callback function that is passed in as the third parameter to your handler function. You are getting a timeout here because you never call the callback so the function runs for 10 seconds then times out.
I'd try returning the data like this:
if (isWorkingDay && isWorkingHour) {
return callback(null, true);
} else {
return callback(null, false);
}
};
Note that it might not like primitive boolean values, so if that doesn't work, try a JavaScript object like:
if (isWorkingDay && isWorkingHour) {
return callback(null, { inWorkingTime: true });
} else {
return callback(null, { inWorkingTime: false });
}
};
I am using twilio voice-quickstart-ios. Currently i am trying to make call from subaccount using twilio REST API. Here is my makeCall endpoint
exports.handler = function(context, event, callback) {
console.log("event :" + JSON.stringify(event));
var to = event.to;
var from = event.from;
let subaccountSid = event.sid;
let subaccountAuthToken = event.token;
const accountSid = context.ACCOUNT_SID;
const authToken = context.AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken, {
accountSid: subaccountSid
});
client.calls
.create({
url: 'http://twimlets.com/message?Message%5B0%5D=Hello%20from%20your%20subaccount',
to: to,
from: from
}, function(err, call) {
if (err) {
console.log("err : " + err);
callback(null, JSON.stringify(err));
} else {
console.log("call Sid " + call.sid);
callback(null, call);
}
});
};
And bellow is the code to perform a voice call from my app.
func performVoiceCall(uuid: UUID, client: String?, completionHandler: #escaping (Bool) -> Swift.Void) {
guard let accessToken = fetchAccessToken() else {
completionHandler(false)
return
}
let dictionary = userdefaults.getSelectedNumbersSidAndAuth()
let sid = dictionary["sid"]!
let token = dictionary["token"]!
let from = self.dialView.selectedNumberInDropdown
let connectOptions: TVOConnectOptions = TVOConnectOptions(accessToken: accessToken) { (builder) in
builder.params = [twimlParamTo : self.outgoingValue!, "sid" : sid, "from" : from, "token": token]
builder.uuid = uuid
}
let call = TwilioVoice.connect(with: connectOptions, delegate: self)
self.activeCall = call
self.activeCalls[call.uuid.uuidString] = call
self.callKitCompletionCallback = completionHandler
}
Now the problem is none of twilio's callback function get called. (eg: if callee or caller disconnects the call, delegates are not called). If i call from master account using Twml everything works fine. but i must have to call from sub account.
How can i be able to fix this? do i need to call makeCall endpoint from performVoiceCall function? If so how can i call this? please let me know.
Im looking to invoke a twilio function and obtain a count of available workers.
I have a feeling it might be related to TaskQueues and the Matching Workers who are available?
Ive come up with the following. However, users are still listed as available when they are interacting with a task, which means this wont work necessarily.
exports.handler = function (context, event, callback) {
const client = require('twilio')(context.ACCOUNT_SID, context.AUTH_TOKEN);
client.taskrouter
.workspaces('eee')
.workers.list()
.then(workers => {
data = {
availWorkersCount: Object.keys(workers.filter(x=> x.available === true && x.attributes.includes("sales"))).length
};
const response = new Twilio.Response();
response.appendHeader('Access-Control-Allow-Origin', '*');
response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS POST GET');
response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
response.appendHeader('Content-Type', 'application/json');
response.setBody(data);
callback(null, response);
});
};
I know this is a bit late, but this is the chunk of code I use in a twilio function to do just this. We call the function from the studio flow and use the results to decide if I am going to route the call into voicemail or play some IVR options for picking what queue they should be put in. To use it you can pass in an optional skill to filter down the agents even more. We grab all available workers then filter down to only the ones that have the needed skill.
You could then take this and check if any of the agents that are available also have a task assigned to them then remove them from the count.
const fetch = require("node-fetch");
exports.handler = function(context, event, callback) {
let response = new Twilio.Response();
// Set the status code to 200 OK
response.setStatusCode(200);
// Set the Content-Type Header
response.appendHeader('Access-Control-Allow-Origin', '*');
response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS, POST, GET');
response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
response.appendHeader('Content-Type', 'application/json');
let body = {
TotalAvailable: 0
};
let client = context.getTwilioClient();
client.taskrouter.workspaces(context.WorkspaceSid)
.workers
.list({
available: 'true',
limit: 50
})
.then((workers) => {
let agents = [];
let i = 0;
if(workers){
for(i = 0; i < workers.length; i++){
let worker = workers[i];
let item = {};
let attributes = JSON.parse(worker.attributes);
if(attributes && attributes.routing && attributes.routing.skills && attributes.routing.skills.length > 0){
item.skills = attributes.routing.skills;
item.nid = attributes.nid;
item.first_name = attributes.first_name;
item.last_name = attributes.last_name;
if(event.skill){
if(item.skills.includes(event.skill)){
// TODO: filter here
agents.push(item);
}
}else{
agents.push(item);
}
}
}
}
body.TotalAvailable = agents.length;
body.Agents = agents;
response.setBody(body);
callback(null, response);
})
.catch((ex) => {
body.error = true;
body.message = ex;
response.setBody(body);
callback(null, response);
});
};
For example, I have a car1 that was first owner by the manufacturer and then it was transferred over to the retailer and then to the user
In the fabcar example, I can know who is its current owner by i don't know who is the previous owner.
Is there a way to do it?
Here is the http://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html example I was following
Is not implemented in the chaincode. To do this you could implement a new method which returns the history of the asset.
Here the link to the official documentation for nodeJS (you can find it also for GoLang):
https://fabric-shim.github.io/ChaincodeStub.html#getHistoryForKey__anchor
Here an example:
async queryValueHistory(stub,args){
if (args.length != 1) {
throw new Error('Incorrect number of arguments. Expecting identifier ex: CAR01');
}
let carId = args[0];
let iterator = await stub.getHistoryForKey(carId);
let allResults = [];
while (true) {
let res = await iterator.next();
if (res.value && res.value.value.toString()) {
let jsonRes = {};
console.log(res.value.value.toString('utf8'));
jsonRes.TxId = res.value.tx_id;
jsonRes.Timestamp = res.value.timestamp;
jsonRes.IsDelete = res.value.is_delete.toString();
try {
jsonRes.Value = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Value = res.value.value.toString('utf8');
}
console.info(jsonRes);
allResults.push(jsonRes);
}
if (res.done) {
console.log('end of data');
try{
await iterator.close();
}catch(err){
console.log(err);
}
console.info(allResults);
return Buffer.from(JSON.stringify(allResults));
}
}
}