In Twilio Programmable Chat, in Laravel backend, how to get members of a channel, given the channel code - channel

How can I get the list of Twilio members of a channel, on my Laravel backend? I am using Programmable Chat API of Twilio. I tried using ChannelInstance members method or property, but I am not getting the list of members correctly. Is there a way to do this, from inside Laravel? I need it to be consumed by the iOS app on the other side (iOS app being the client). Ios app asks from Laravel the list of users that the user has chatted to, so I first get all channels:
$params = $request->all();
$username = $params["username"];
$unl = strlen($username);
$twilio = new Client($this->sid, $this->authToken);
// Get all user's channels
$ucs = $twilio->chat->v2->services($this->serviceId)
->users($username)
->userChannels
->read(50);
// Try to find members of each channel
foreach ($ucs as $uc) {
$channel = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->fetch();
print_r($channel->toArray());
}
in the print_r - ed array, I have uniqueName and friendlyName, which are concatenated two participants of the channel. But I would prefer to just have two objects, or two strings that would tell me which are the members participants of that channel. Is there a way to do this?

Twilio developer evangelist here.
In this case you're just reading the information about the channel. Instead, you should fetch the members from the channel.
foreach ($ucs as $uc) {
$channel_members = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->members
->read([], 20);
print_r($channel_members);
}

To get members, I needed to do this:
$ucs = $twilio->chat->v2->services($this->serviceId)
->users($username)
->userChannels
->read(50);
foreach ($ucs as $uc) {
$channel_members = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->members
->read([], 20);
foreach ($channel_members as $record) {
print($record->sid . "\n");
}
}

Related

What happens when flux is returned from spring web controller?

I am comparatively new to reactive APIs and was curious about what was happening behind the scenes when we return a Flux from a web controller.
According to spring-web documentation
Reactive return values are handled as follows:
A single-value promise is adapted to, similar to using DeferredResult. Examples include Mono (Reactor) or Single (RxJava).
A multi-value stream with a streaming media type (such as application/stream+json or text/event-stream) is adapted to, similar to using ResponseBodyEmitter or SseEmitter. Examples include Flux (Reactor) or Observable (RxJava). Applications can also return Flux or Observable.
A multi-value stream with any other media type (such as application/json) is adapted to, similar to using DeferredResult<List<?>>.
I created two APIs as below:
#GetMapping("/async-deferredresult")
public DeferredResult<List<String>> handleReqDefResult(Model model) {
LOGGER.info("Received async-deferredresult request");
DeferredResult<List<String>> output = new DeferredResult<>();
ForkJoinPool.commonPool().submit(() -> {
LOGGER.info("Processing in separate thread");
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000 ; i++) {
list.add(String.valueOf(i));
}
output.setResult(list);
});
LOGGER.info("servlet thread freed");
return output;
}
#GetMapping(value = "/async-flux",produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
LOGGER.info("Received async-deferredresult request");
List<String> list = new ArrayList<>();
list.stream();
for (int i = 0; i < 10000 ; i++) {
list.add(String.valueOf(i));
}
return Flux.fromIterable(list);
}
So the exception was that both APIs should behave same as multi-value stream(Flux) should have similar behavior to that of a returning a DeferredResult. But in API where deferred result was returned, whole list was printed in one go on browser where as in API where Flux was returned the numbers where printed sequentially(one by one).
What exactly is happening when I am returning Flux from controller ?
When we return a Flux from a service endpoint many things can happen. But I assume you want to know what is happening when Flux observed as stream of events from client of this endpoint.
Scenario One: By adding 'application/json' as the content type of the endpoint Spring will communicate to the client to expect JSON body.
#GetMapping(value = "/async-flux", produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(String.valueOf(i));
}
return Flux.fromIterable(list);
}
The output at the client will be the whole set of numbers in one go. And once the response delivered the connection will be closed. Even though you have used Flux as the response type, you are still bound the laws of how HTTP over TCP/IP works. The endpoint got a HTTP request, execute the logic and respond with HTTP response containing final result.
As a result, you do not see the real value of a reactive api.
Scenario Two: By adding 'application/stream+json' as the content type of the endpoint, Spring starts to treat the resulting events of the Flux stream as individual JSON items. When an item is emitted is gets serialised, the HTTP response buffer is flushed, and the connection from the server to client keep open up until the event sequence get completed.
To get that working we can slightly modify your original code as follows.
#GetMapping(value = "/async-flux",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000 ; i++) {
list.add(String.valueOf(i));
}
return Flux.fromIterable(list)
// we have 1 sec delay to demonstrate the difference of behaviour.
.delayElements(Duration.ofSeconds(1));
}
This time we can see the real value of reactive api endpoint where it is able to deliver results to it's client as date get available.
You can find more details about how to build reactive REST APIs at
https://medium.com/#senanayake.kalpa/building-reactive-rest-apis-in-java-part-1-cd2c34af55c6
https://medium.com/#senanayake.kalpa/building-reactive-rest-apis-in-java-part-2-bd270d4cdf3f

How to get the number of individual unread messages of PubNub?

I'm using pubnub Services to add chat functionality to my App but i'm wondering if there is a way to get the individual number of unread messages. i'm using this link -> https://www.pubnub.com/docs/swift/data-streams-publish-and-subscribe
This can be accomplished using PubNub Functions. Functions are your own scripts that run automatically in the cloud when a message is published on one or many PubNub Channels.
It has a key-value store with increment, decrement, and retrieve functionality. This can be used very intuitively with an unread message pattern on PubNub.
Channel: room.*
Event: On-Before Publish
// Access to Distributed Database
const db = require('kvstore');
export default (request) => {
// Conventionally build the Key ID based on the request parameters and channel name.
let counterId = request.channels[0] + '/' + request.params.uuid;
// Increment or Decrement the unread message counter
let method = request.message.read ? -1 : 1;
// Increment/Decrement and read the unread message counter
return db.incrCounter( counterId, method ).then(()=>{
return db.getCounter(counterId).then((counter) => {
request.message.unread = counter || 0;
return request.ok();
});
});
}
Following this official guide you can integrate this new functionality into an existing app.

Node.js client for wit.ai calls multiple custom actions

I'm trying to write an example app in wit.ai. I followed the quickstart app using node.js client that is shown at https://wit.ai/docs/quickstart.
The example shown there has only one custom action. But when I try to add a new story and a new action, I see that the context is being shared between the stories. This is causing wrong behaviour(a custom action from another story is being executed).
I cannot find any example with multiple custom actions and stories. Are there any node.js or python examples other than the ones from wit.ai websites?
You need to create a context for each session, and this is a quick example (from https://github.com/wit-ai/node-wit/blob/master/examples/messenger.js):
const findOrCreateSession = (fbid) => {
let sessionId;
// Let's see if we already have a session for the user fbid
Object.keys(sessions).forEach(k => {
if (sessions[k].fbid === fbid) {
// Yep, got it!
sessionId = k;
}
});
if (!sessionId) {
// No session found for user fbid, let's create a new one
sessionId = new Date().toISOString();
sessions[sessionId] = {
fbid: fbid,
context: { // New context per session id.
_fbid_: fbid
}
}; // set context, _fid_
}
return sessionId;
};
You can find a working example at https://github.com/hunkim/Wit-Facebook.
I suppose wit engine don't store context on their side.
You 'merge' function must merge entities in different ways, depending on your app logic.
But if you story is completed, you need to clear context for next stories.
I added a built-in function clear-context and call this function from wit as action.
Check out my example.
It's not an official api, but you can understand how wit http api works.

Stripe, is it possible to search a customer by their email?

Update: Since around January 2018, it is now possible to search using the email parameter on Stripe. See the accepted answer.
I was wondering if it was possible to search a customer only by their email address when using the Stripe API.
The documentation only indicates searching by:
created,
ending_before,
limit,
starting_after
But not email.
I'd like to avoid having to list over all my customers to find which ones have the same email addresses.
Stripe now allows you to filter customers by email.
https://stripe.com/docs/api#list_customers
Map<String, Object> options = new HashMap<>();
options.put("email", email);
List<Customer> customers = Customer.list(options).getData();
if (customers.size() > 0) {
Customer customer = customers.get(0);
...
This is important to help ensure you don't create duplicate customers. Because you can't put creating a customer in Stripe and the storage of the Stripe customer ID in your system inside a single transaction you need to build in some fail safes that check to see if a particular customer exists before you create a new one. Searching customers by email is important in that regard.
I did this by using the following API request. This was not available in stripe docs.I got this by tracking down their search in the dashboard area using Browser Developer Tools.
url :https://api.stripe.com/v1/search?query="+email+"&prefix=false",
method: GET
headers: {
"authorization": "Bearer Your_seceret Key",
"content-type": "application/x-www-form-urlencoded",
}
Warning This uses an undocumented API that is specific to the dashboard. While it might work today, there is no guarantee it will continue to work in the future.
You need to retrieve and store the Stripe customer ID along with the other customer details in your database. You can then search for the email address in your database and retrieve the customer record from Stripe by using the Stripe customer ID.
UPDATE: Stripe now allows searching via email
https://stripe.com/docs/api/php#list_customers
/**
* Remember that Stripe unfortunately allows multiple customers to have the same email address.
* #see https://stackoverflow.com/a/38492724/470749
*
* #param string $emailAddress
* #return array
*/
public function getCustomersByEmailAddress($emailAddress) {
try {
$matchingCustomers = [];
$lastResult = null;
$hasMoreResults = true;
while ($hasMoreResults) {
$searchResults = \Stripe\Customer::all([
"email" => $emailAddress,
"limit" => 100,
"starting_after" => $lastResult
]);
$hasMoreResults = $searchResults->has_more;
foreach ($searchResults->autoPagingIterator() as $customer) {
$matchingCustomers[] = $customer;
}
$lastResult = end($searchResults->data);
}
return $matchingCustomers;
} catch (\Exception $e) {
Log::error($e);
return [];
}
}
You can't directly search by email.
However, you can hack a little bit to list all users, and look after your email.
Here's my code (PHP) :
$last_customer = NULL;
$email = "EmailYou#AreLooking.for";
while (true) {
$customers = \Stripe\Customer::all(array("limit" => 100, "starting_after" => $last_customer));
foreach ($customers->autoPagingIterator() as $customer) {
if ($customer->email == $email) {
$customerIamLookingFor = $customer;
break 2;
}
}
if (!$customers->has_more) {
break;
}
$last_customer = end($customers->data);
}
You only need to write this line
\Stripe\Customer::all(["email" => "YourDesiredEmail"]);
In NodeJs we can search for our desired customer with their email address like the following:
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
const stripe = require('stripe')(stripeSecretKey);
const findCustomerByEmail = async (email) => {
try {
const customer = await stripe.customers.list( {
email: email,
limit: 1
});
if(customer.data.length !== 0){
return customer.data[0].id;
}
} catch (e) {
return (e);
}
};
The actual call to stripe is using the stripe.customers.list. If the email exists in our stripe account then the returned object will contain an element called data.
Using "list()" and "search()", you can get customers by email with these Python code below:
customers = stripe.Customer.list(
email="example#gmail.com",
)
customer = stripe.Customer.search(
query="email:'example#gmail.com'"
)
You can also limit customers to get with "limit" parameter as shown below:
customers = stripe.Customer.list(
email="example#gmail.com",
limit=3
)
customer = stripe.Customer.search(
query="email:'example#gmail.com'",
limit=3
)
Since you specified that
The documentation only indicate to search by created, ending_before, limit and starting_after, but no "email".
You are right, you can't search using emails.
If you still wish to do that, What you can do instead is to get a list of all the customer and filter on the response you get using email.
For Example, in ruby you can do it as follows:
customers = Stripe::Customer.all
customer_i_need = customers.select do |c|
c.email == "foo#bar.com"
end
PS: Stripe can have multiple customers associated with one email address.
Please bear in mind when using Stripe API that it is case sensitive email (which is a bit stupid). Hopefully they change this.
Stripe API does not supports any search-by-email feature. They have this search in their dashboard but not released any to API; from the architectural concept it seems that there is no possibility or plan from stripe to include this in API; every object in their API is retrievable only by that specific objects id given by stripe while its created. May be, they have kept it as a scope for third party application developers involvement!!
So, the obvious solution is to store the customers in your own database that you want to be searchable in future - as Simeon Visser has said above
btw, for a workaround, if you already have used the stripe API a lot and there are many customer data which you now need to be searchable - the only way is to go thru the 'List all customers' functionality of API & build the database for your own purpose; ofcourse, you've to use pagination shortcut to iterate thru the whole list for doing so.
$customers = \Stripe\Customer::all(array("limit" => 3));
foreach ($customers->autoPagingIterator() as $customer) {
// Do something with $customer
}
You can try this. It worked for me. Below code will return empty list if not found data matching with email.
$stripe = new \Stripe\StripeClient("YOUR_STRIPE_SECRET");
$customers = $stripe->customers->all(['email'=>'jane.doe#example.com',
'limit' => 15,
]);
Stripe Search API Beta now is available
youtube link
Here is The Async- Await Way This Method can Be Used For All Third Party Hits with Nodejs Particularly
const configuration = {
headers: {
"authorization": `Bearer ${Your stripe test key}`,
"content-type": "application/x-www-form-urlencoded",
}
};
const requestUrl = `https://api.stripe.com/v1/search?
query=${'email you are to use'} &prefix=false`
const emailPayment = await axios.get(requestUrl,
configuration)
Axiom is Npm for creating http requests... very cool and dead simple
Stripe allows the ability to have more than once customer with the same email. That said, if you wanted to, you can pass a filters hash param to the list method to return a single customer or array of customers.
Stripe::Customer.list(email: user.email).data
The above will return an array of Stripe::Customer instances with the email

Facebook Application building. How do I do a simple API call?

I have 4.5 years experience as a professional PHP developer, I have loads of experience with session handling, etc.
I am wanting to learn how to build Facebook applications. I have gone through the process of downloading the Facebook Developer application, I have used to it Create an App, I have set the canvas URL to where the app is hosted.
I can successfully "install" the app using a Facebook user account, and I can successfully access it. I have noted that when the app is loaded, a whole string of data gets passed to it, with parameter names like fb_sig_user and fb_sig_session_key. Currently, I am doing nothing with these parameters.
On the application end, obviously I am supposed to create a Facebook object by using my own APP ID key and SECRET key, which I have done.
But I can't seem to figure out how to start making API calls from my application back to Facebook.
How do I, at this point, just do something simple like get the person's name and display it to them?
Eg, how do I:
$first_name = $facebook->getUserFirstName();
.. do something like that?
I just want to do a simple test to ensure the API stuff is working.
Any help would be appreciated. Thanks.
The Facebook PHP SDK would probably be your first stop, with some example code as a close runner up.
Making API calls with the Facebook SDK set up alright is as easy as;
$me = $facebook->api('/me'); // Returns array containing data for currently logged in user depending on given permissions
or
$my_friends = $facebook->api('/me/friends'); // Returns array containing information on friends of currently logged in user
and even
$my_profile_img = $facebook->api('/me/picture'); // Returns a string containing URL to users profile picture.
Also, everything within the open graph has unique id's that you can plug in instead of me in /me.
For further and more in-depth description of the Open Graph, I suggest going to the official Graph API Overview page.
Quite easy and fun to work with once you get it set up - albeit a bit slow.
Update:
In order to get the Facebook cookie and set up a session from it I did:
$cookie = get_facebook_cookie($fbconfig['appid'], $fbconfig['secret']);
function get_facebook_cookie($app_id, $application_secret) {
$args = array();
parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
ksort($args);
$payload = '';
foreach ($args as $key => $value) {
if ($key != 'sig') {
$payload .= $key . '=' . $value;
}
}
if (md5($payload . $application_secret) != $args['sig']) {
return null;
}
return $args;
}
if (isset($cookie)) {
$session = $facebook->getSession($cookie);
}
Then updated Facebook.php line 332 to be
public function getSession($passedCookie) {
and line 373 to be
$this->setSession($passedCookie, $write_cookie);
Lame hacking, but it worked for me at least