Twilio channel already exists - twilio

How can I fix this porblem:
Channel with provided unique name already exists
Here is the code for creating channel:
tc.joinGeneralChannel = function () {
console.log('Attempting to join ' + $channelName + 'chat channel...');
if (!tc.generalChannel) {
console.log('Channel doesn\'t exists');
// If it doesn't exist, let's create it
tc.messagingClient.createChannel({
uniqueName: $channelName,
friendlyName: $channelName
}).then(function (channel) {
tc.generalChannel = channel;
tc.loadChannelList(tc.joinGeneralChannel);
});
} else {
setupChannel(tc.generalChannel);
}
};
The behavior is weird because the issue is not consistent.
Most of my code are the same with the tutorial twilio provided for laravel framework Twilio Docs
Is there a way to check if the unique name is already exists and then just join in there?

Related

"Failed to issue Dequeue" when using Twilio Task Router for non-phone related tasks

NOTE: Code snippets below are functional. The "dequeue" error mentioned in this post was based on an existing Assignment Callback external to these scripts. Once the URL was removed and the reservation.dequeue moved to this code, the error was resolved.
We are in the process of developing a chat application using Conversations between two people. I currently have it "wired" up with the following steps when a user initiates the chat:
Conversation is created.
User is created.
User is added to the conversation.
Task is created with conversation meta-data in attributes.
(followed by steps on the other user's session to accept the reservation, etc.)
These steps work as expected, but a "40140 - Failed to issue Dequeue instruction due to missing 'call_sid' property" is generated since the task isn't an incoming phone call. I tried putting the task into the "SMS" Task Channel, but that didn't stop the error.
I couldn't find any specific documentation on creating non-phone call-based tasks so I might be setting up the task routing incorrectly.
Here are code snippets showing how I create (in .NET) the conversation, user, and task, and how I accept (in TaskRouter.js) the reservation.
/***********************************************************************************************************
This code is server-side in .NET
***********************************************************************************************************/
public ConversationCredentials CreateConversation( string program, string name )
{
var memberId = DateTime.Now.ToString( "yyyyMMdd" ); // Temporary
TwilioClient.Init( _twilioAccountSid,_twilioAuthToken );
// If we decide to keep conversations on Twilio, we should replace the memberid with phiid, since member id might change
var conversation = ConversationResource.Create(
friendlyName: memberId + "_" + DateTime.Now.ToString( "HHmmss" )
);
var conversationCredentials = JoinConversation( conversation.Sid, name );
var taskSid = CreateTask( program, conversation.Sid, memberId );
conversationCredentials.taskSid = taskSid;
return conversationCredentials;
}
public ConversationCredentials JoinConversation( string conversationSid, string name )
{
var identity = name + "_" + DateTime.Now.ToString( "HHmmss" ); // Makes sure the user is unique, in case it's an employee joining more than one chat session)
TwilioClient.Init( _twilioAccountSid,_twilioAuthToken );
var participant = ParticipantResource.Create(
pathConversationSid: conversationSid,
identity: identity
);
var user = UserResource.Update(
pathSid: identity,
friendlyName: name
);
var token = GetJWT( _twilioConversationServiceSid, name ); // Conversation Service Sid
var conversationCredentials = new ConversationCredentials();
conversationCredentials.token = token;
conversationCredentials.conversationSid = conversationSid;
conversationCredentials.participantSid = participant.Sid;
conversationCredentials.participantName = name;
conversationCredentials.participantIdentity = participant.Identity;
return conversationCredentials;
}
public string CreateTask( string program, string conversationSid, string memberId )
{
TwilioClient.Init( _twilioAccountSid, _twilioAuthToken );
var attributes = JsonConvert.SerializeObject( new Dictionary<string,Object>()
{
{"conversationSid", conversationSid },
{"memberId", memberId },
{"program", program },
{"call_sid", "CHAT" }
}, Formatting.Indented);
var task = TaskResource.Create(
attributes: attributes,
workflowSid: _twilioWorkflowSid,
pathWorkspaceSid: _twilioWorkspaceSid_Nurses,
taskChannel: "Default"
);
return task.Sid;
}
/***********************************************************************************************************
This code is browser-side using TaskRouter.js
NOTE: This handles both voice (works fine) and conversations (the part in question)
***********************************************************************************************************/
registerTaskRouterCallbacks( _this ) : void {
this.worker.on('ready', function(worker) {
_this.updateButton( worker.activityName, "" );
});
this.worker.on("reservation.created", function(reservation) {
if ( reservation.task.attributes.type != "CHAT" )
{
_this.updateButton( "Call", reservation.task.attributes.from.replace( "+1", "" ) );
reservation.dequeue();
} else {
_this.updateButton( "Chat", reservation.task.attributes.memberId );
confirm("You have an incoming chat!");
reservation.accept();
// This is where the chat window would pop-up
}
});
this.worker.on("reservation.accepted", function(reservation) {
_this.worker.update({"ActivitySid": _this.activitySids["Busy"][0].sid});
_this.updateButton( "Busy", "" );
});
The "dequeue" error mentioned in this post was based on an existing Assignment Callback external to these scripts. Once the URL was removed and the reservation.dequeue moved to this code, the error was resolved.

How can I access a Teams user's email address?

I'm trying to build a Microsoft Teams integration for an app, but I'm having some trouble getting a user's email address.
I used the Microsoft Teams extension for VS Code to scaffold a basic app. I'm using the BotFramework v4 (NodeJS) on my server. I'm able to receive requests from Teams and respond to them as well.
To get an user's email address, I am using the TeamsInfo.getMember(context, id) method, where the id is obtained from context.activity.from object. Unfortunately, calling this method results in a RestError: Unknown with a status code of 400.
I'm not sure what I'm missing here. My app is registered with the Azure Active Directory and has the User.Read.All permission. Am I missing something here?
Any help would be appreciated!
For some context, I'm trying to build a Messaging Extension Action Command.
Code:
import {
TurnContext,
TeamsActivityHandler,
CardFactory,
MessagingExtensionAction,
TeamsInfo,
} from 'botbuilder';
export default class TeamsMessagingExtensionsActionBot extends TeamsActivityHandler {
constructor() {
super();
}
// #ts-ignore
handleTeamsMessagingExtensionSubmitAction(
context: TurnContext,
action: MessagingExtensionAction,
) {
switch (action.commandId) {
case 'someCommand':
return handleCommand(context, action);
default:
throw new Error('NotImplemented');
}
}
}
async function handleCommand(
context: TurnContext,
action: MessagingExtensionAction,
) {
const card = CardFactory.heroCard(
'Some Command',
'We have received your command!',
);
const user = await TeamsInfo.getMember(context, context.activity.from.id);
console.log('User:', user);
const attachment = {
contentType: card.contentType,
content: card.content,
preview: card,
};
return {
composeExtension: {
type: 'result',
attachmentLayout: 'list',
attachments: [attachment],
},
};
}
This is the error I get when calling TeamsInfo.getMember(): JSON

Unable to join chat channel

When trying to join a channel in the twilio code I've been working with, it comes up with the error saying that it "Cannot read property 'getChannelByUniqueName' of null". The chat works but when I try to open it up on a different browser, like firefox instead of chrome, it says the error "Channel with provided unique name already exist". Can anyone help with this problem?
// Initialize the Chat client
chatClient = new Twilio.Chat.Client(data.token);
joinChannels(chatClient);
});
function joinChannels(chatClient) {
chatClient.getSubscribedChannels();
joinChannel('generalss','Generals Chat Channel');
}
function joinChannel(channelName, channelFriendlyName) {
console.log(channelName);
console.log(chatClient);
print('Attempting to join "' + channelName + '" chat channel...');
var promise = chatClient.getChannelByUniqueName(channelName);
promise.then(function(channel) {
console.log('Found ' + channelName + ' channel:');
channels[channelName] = channel;
console.log(channels);
setupChannel();
}).catch(function() {
// If it doesn't exist, let's create it
chatClient.createChannel({
uniqueName: channelName,
friendlyName: channelFriendlyName
}).then(function(channel) {
channels[channelName] = channel;
setupChannel(channelName);
});
});
}
Twilio developer evangelist here.
It looks to me like you aren't passing the chatClient to your joinChannel method (and secondly that the client might not be fully initialised yet).
I would initialise the client with the following, which uses the create method that returns a promise that resolves when the Client is ready.
// Initialize the Chat client
new Twilio.Chat.Client.create(data.token).then(function(chatClient) {
joinChannels(chatClient);
});
});
Then, make sure you pass the client through to the joinChannel method:
function joinChannels(chatClient) {
chatClient.getSubscribedChannels();
joinChannel(chatClient, 'generalss','Generals Chat Channel');
}
function joinChannel(chatClient, channelName, channelFriendlyName) {
// the rest...
}
Let me know if that helps at all.

Subscribe to YouTube channel button

I want to add to my site "Subscribe to channel" button which would subscribe the user who browses my site to the YouTube channel with given (fixed) ID.
How to make such a button?
Straight from the source:
/**
* This sample subscribes the active user to the GoogleDevelopers
* YouTube channel, specified by the channelId.
*/
function addSubscription() {
// Replace this channel ID with the channel ID you want to subscribe to
var channelId = 'UC9gFih9rw0zNCK3ZtoKQQyA';
var resource = {
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelId
}
}
};
try {
var response = YouTube.Subscriptions.insert(resource, 'snippet');
Logger.log(response);
} catch (e) {
if(e.message.match('subscriptionDuplicate')) {
Logger.log('Cannot subscribe; already subscribed to channel: ' + channelId);
} else {
Logger.log('Error adding subscription: ' + e.message);
}
}
}
... redirects to my channel at YouTube and asks subscription confirmation.
It is exactly what I need. And this does not require API key (stroring which in a publicly accessible HTML or JavaScript file would be a big security hole).

google adwords api + getting all keywords

I'm using the google adwords api, I can retrieve all campaigns, group ads, ads,
but I have no idea on how to retrieve keywords related to an "group ads".
In the google adwords interface, when we select a group ads, we have two tabs, one for ads related to that group ads, and the second for keywords.
but programatily, right now I can only retrieve ads.
I'm using PHP, if some one knew how to do that in php or others programming languages or even a soap call.
To get the details of all the keywords of an adgroup you need the following to get the details of all the keywords.
require_once dirname(dirname(__FILE__)) . '/init.php';
// Enter parameters required by the code example.
$adGroupId = 'Enter your adgroup id';
/**
* Runs the example.
* #param AdWordsUser $user the user to run the example with
* #param string $adGroupId the id of the parent ad group
*/
function GetKeywordsExample(AdWordsUser $user, $adGroupId) {
// Get the service, which loads the required classes.
$adGroupCriterionService =
$user->GetService('AdGroupCriterionService', ADWORDS_VERSION);
// Create selector.
$selector = new Selector();
$selector->fields = array('KeywordText', 'KeywordMatchType', 'Id');
$selector->ordering[] = new OrderBy('KeywordText', 'ASCENDING');
// Create predicates.
$selector->predicates[] = new Predicate('AdGroupId', 'IN', array($adGroupId));
$selector->predicates[] =
new Predicate('CriteriaType', 'IN', array('KEYWORD'));
// Create paging controls.
$selector->paging = new Paging(0, AdWordsConstants::RECOMMENDED_PAGE_SIZE);
do {
// Make the get request.
$page = $adGroupCriterionService->get($selector);
// Display results.
if (isset($page->entries)) {
foreach ($page->entries as $adGroupCriterion) {
printf("Keyword with text '%s', match type '%s', and ID '%s' was "
. "found.\n", $adGroupCriterion->criterion->text,
$adGroupCriterion->criterion->matchType,
$adGroupCriterion->criterion->id);
}
} else {
print "No keywords were found.\n";
}
// Advance the paging index.
$selector->paging->startIndex += AdWordsConstants::RECOMMENDED_PAGE_SIZE;
} while ($page->totalNumEntries > $selector->paging->startIndex);
}
// Don't run the example if the file is being included.
if (__FILE__ != realpath($_SERVER['PHP_SELF'])) {
return;
}
try {
// Get AdWordsUser from credentials in "../auth.ini"
// relative to the AdWordsUser.php file's directory.
$user = new AdWordsUser();
// Log every SOAP XML request and response.
$user->LogAll();
// Run the example.
GetKeywordsExample($user, $adGroupId);
} catch (Exception $e) {
printf("An error has occurred: %s\n", $e->getMessage());
}
In the Adwords API Keywords are dubbed as AdGroup Criteria. You can add or retrieve the keywords for a certain AdGroup by using the AdGroupCriterionService.
If you're using the PHP client library of the Adwords API check out GetAllAdGroupCriteria.php in the example files. (don't forget to enter the AdGroupId you want to get the keywords for first)

Resources