Slack API: select conversation members while filtering out bots without n+1 - slack

I need to select all members of a conversation who are not bots. It appears the way to do this is to first call conversations.members and then for each member call users.info. Using the slack ruby client, that boils down to this:
client = Slack::Web::Client.new(token: "MY-OAUTH-TOKEN")
# returns an array of user ids
response = client.conversations_members(channel: "#some-channel", limit: 500)
member_ids = response.members
members = member_ids.reject do |member_id|
# returns a https://api.slack.com/types/user object
user = client.users_info(user: member_id)
user["user"]["is_bot"] == true
end
This obviously presents an n+1 problem. I'm wondering if I've overlooked a better API method to call, or an API method argument that could help with this, whether via slack-ruby-client, or just via the vanilla API methods.

Unfortunately, Currently Slack does not have a single API call solution to your problem statement.

Related

How to send to multiple recipients (WITHOUT LOOPING) while using variable alphanumeric sender ID?

I was wondering if there is a way to set multiple recipients WITHOUT looping over the list of recipients at my end?! Also most importantly while using variable alphanumeric sender ID and NOT buying a twilio number?
I can do all this for single recipient like this:
$twilio_client->messages->create(
'+64*******', //to
[
'from'=> 'foo',
'body' => 'bar'
]);
Works perfectly fine. However, doesnt work with multiple receivers.
Also note, it was bloody-1-step easy to implement smsbroadcast.com.au and pass all this in a simple call (simple call, quick fast, super easy documentation - unlike twilio which has like a billion lines of confusing documentation, 200 similar products and YET no direct api to check balance, or do a simple thing such as multiple recipients!!)
After a lot of back and through with the support, plus reading all the over-written-essay (so-called documentations), finally I found a way to get all that done.
[Step 1: Configuration]
You have to implement Notify product which is a separate product than the Message product.
So from left menu Notify> Service> add New. Here you need to add a Messaging Service and have it selected here for Notify.
On the Messaging Services page, it will ask you to buy a twilio number. Instead just click on Configure from the left menu and put in all the details you need.
Specifically and importantly, make sure you have Alpha Sender ID checked and a default Alpha Sender text entered there. This will be the default fallback in case if your api call fails to accept the from param.
.
[Step 2: API Call]
//$notify_service_SID = the SID from the Notify Service you added in step 1
$client = new Client($this->Account_SID, $this->auth_token);
$notify_obj = $client->notify->services($notify_service_SID);
//you need receivers in a JSON object such as the following, plus make sure numbers are starting with country code to ensure alpha sender works correctly
$receivers_json = [0=>'{"binding_type":"sms","address":"+614********"}']+[1=>'{"binding_type":"sms","address":"+614*******"}']
$call_ret = $notify_obj->notifications->create([
'toBinding'=> $receivers_json,
'body' => $msg, //actual message goes here
'sms' => [
'from'=> $sender //alphanumeric variable sender
],
]);
.
[Step 3: Check for errors]
There is no direct way to check all errors in twilio when implementing Notify. Here is my mixed approach.
Exception handling to the notifications->create call
$call_ret will have err if the Notify fails, but not when the Message fails. because Notify just passes the call to Message and there is no direct way to check Message errors over Notify call. So you would check for $call_ret['err']
Call the Alerts API; fetch all recent alerts, and match against the Notification SID you received from the last call.
--
Here is how to do the Alerts check:
$alerts = #$client->monitor->v1->alerts->read();
if(is_array($alerts))
foreach($alerts as $av)
{
$t = #$av->toArray();
#parse_str($t['alertText'], $alert_details);
if(isset($alert_details['notificationSid']) && $alert_details['notificationSid'] == $call_retx['sid'])
{
$alert_err = $alert_details['description'];
break;
}
}
$alert_err will carry an error if there was an error. Apart from this there is no direct way to do it. You can fetch these Alerts via crons or you can setup a webhook for them to do a call back. Or simply implement a one call simple api that does it all in super simple way such assmsbroadcast.

how can I get ALL records from route53?

how can I get ALL records from route53?
referring code snippet here, which seemed to work for someone, however not clear to me: https://github.com/aws/aws-sdk-ruby/issues/620
Trying to get all (I have about ~7000 records) via resource record sets but can't seem to get the pagination to work with list_resource_record_sets. Here's what I have:
route53 = Aws::Route53::Client.new
response = route53.list_resource_record_sets({
start_record_name: fqdn(name),
start_record_type: type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
})
response.last_page?
response = response.next_page until response.last_page?
I verified I'm hooked into right region, I see the record I'm trying to get (so I can delete later) in aws console, but can't seem to get it through the api. I used this: https://github.com/aws/aws-sdk-ruby/issues/620 as a starting point.
Any ideas on what I'm doing wrong? Or is there an easier way, perhaps another method in the api I'm not finding, for me to get just the record I need given the hosted_zone_id, type and name?
The issue you linked is for the Ruby AWS SDK v2, but the latest is v3. It also looks like things may have changed around a bit since 2014, as I'm not seeing the #next_page or #last_page? methods in the v2 API or the v3 API.
Consider using the #next_record_name and #next_record_type from the response when #is_truncated is true. That's more consistent with how other paginations work in the Ruby AWS SDK, such as with DynamoDB scans for example.
Something like the following should work (though I don't have an AWS account with records to test it out):
route53 = Aws::Route53::Client.new
hosted_zone = ? # Required field according to the API docs
next_name = fqdn(name)
next_type = type
loop do
response = route53.list_resource_record_sets(
hosted_zone_id: hosted_zone,
start_record_name: next_name,
start_record_type: next_type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
)
records = response.resource_record_sets
# Break here if you find the record you want
# Also break if we've run out of pages
break unless response.is_truncated
next_name = response.next_record_name
next_type = response.next_record_type
end

credentials for google knowledge graph

I am trying to use the Google Knowledge graph API. I already have the API key and also use the library instead of the RESTful API.
kgSearch = Kgsearch::KgsearchService.new
response = kgSearch.search_entities(query: query)
I have tried to instantiate the service as below
kgSearch = Kgsearch::KgsearchService.new(api: 'klfkdlfkdlm')
it's rejected because the init expect no arguments.
Any idea, how to add the api_key ??
I try also:
response = kgSearch.search_entities(query: query, api: 'fjfkjfl')
same things
Any ideas?
According to the Ruby Docs for the Google Api Client, key is an instance method where you can assign your api key (http://www.rubydoc.info/github/google/google-api-ruby-client/Google/Apis/KgsearchV1/KgsearchService#key-instance_method).
So I believe you'd do something like the following:
kgSearch = Kgsearch::KgsearchService.new
kgSearch.key = 'your_key_here'
response = kgSearch.search_entities(query: query) # and any other options that are necessary

Lita.io Handler Plugin - How to get a list of all joined rooms

I am in the process of writing a Handler Plugin for lita.io. What I want to do is provide a HTTP POST endpoint and when it is called I want to publish some chat message to all rooms that Lita has joined.
I already succeeded with posting to a specific room that is identified as parameter in the HTTP call doing it like this:
def receive(request, response)
room = request.params['room']
Lita.logger.debug("stash-post-receive: room = #{room}")
target = Source.new(room: room)
json_data = parse_json(request.body.read) or return
message = format_message(json_data)
robot.send_message(target, message)
end
But this requires the caller to already supply which room to post to. Is there a way to retrieve a list of all rooms that Lita has joined so I can post there?
Currently there is not a generic way to do this. The adapter would have to expose an adapter-specific API for it.

How to access Google Contacts API in ruby

I'm struggling to access the Google Contacts API.First I tried the google-api-ruby-client gem but it turned out that it does not support the Contacts API.
Next shot was the google_contacts_api gem. I used oauth2 to access the authentication key(Getting authentication token guide question). But after passing the token correctly to the api it is producing an error.
`<main>': undefined method `[]' for #<GoogleContactsApi::GroupSet:0x000000039fcad8>` (NoMethodError).
Here is my code.
# get token using oauth2 gem, and use it below in the google_contacts_api.
google_contacts_user = GoogleContactsApi::User.new(token)
contacts = google_contacts_user.contacts
groups = google_contacts_user.groups
# group methods
group = groups[0]
group.contacts
puts group.contacts
# contact methods
puts contacts.count
puts groups.count
contact = contacts[0]
contact.primary_email
contact.emails
What am I doing wrong?
UPDATE:
As #alvin suggested it is working now. But the group contacts are not being printed out. Instead it is printing #<GoogleContactsApi::ContactSet:0x000000020e49d8>.Example: here is what is printed by this code
groups = google_contacts_user.groups
# group methods
groups.each do |group|
group_contacts = group.contacts
puts group_contacts
end
Output:
#<GoogleContactsApi::ContactSet:0x000000020e49d8>
#<GoogleContactsApi::ContactSet:0x0000000504aec0>
#<GoogleContactsApi::ContactSet:0x0000000518dfd0>
#<GoogleContactsApi::ContactSet:0x000000052d9290>
#<GoogleContactsApi::ContactSet:0x000000054280d8>
#<GoogleContactsApi::ContactSet:0x0000000558c2f8>
#<GoogleContactsApi::ContactSet:0x00000005746eb8>
#<GoogleContactsApi::ContactSet:0x000000058a3ea0>
How can I print the group contacts?
Edited to add info about the Enumerable implementation
(I wrote the gem.)
There was a bug in the documentation. groups and contacts are instances of classes that implement Enumerable, which doesn't provide the [] method, but does provide the first method.
So, try groups.first instead of groups[0]. Likewise, use contacts.first instead of contacts[0]. My bad! (I probably did a to_a in my head.)
Response to Update
To answer the second half of the question, it looks like you found the relevant convenience methods for Contact and Group, in particular the Contact.primary_email method. See more methods in the (somewhat incomplete, sorry) YARD docs.
To get all the emails, you basically need to iterate over the returned contacts. As I mentioned in the updated response to the first part of your question, groups and contacts have all the methods of Enumerable. (Enumerable documentation). Here are some examples:
# What are all the groups called?
user.groups.map(&:title)
# Find group by title. (Returns nil if no such group.)
group = user.groups.select { |g| g.title = "Group Name" }
# Get all primary emails from a group
group.contacts.map(&:primary_email)
# Get all primary emails from all contacts regardless of group
user.contacts.map(&:primary_email)
You only need to use the Hashie::Mash methods to access data when no convenience accessor is provided (for example, if Google starts returning extra data the gem hasn't accounted for yet). The use case you described doesn't require this.
P.S. In the future, you might want to open a new question instead of editing your existing question.

Resources