Slack API - How to get bot_id when bot has no conversation history? - slack

I am trying to get the bot_id value for a bot when it has no conversation history.
According to the documentation:
the bot_id fields appear in bot_message message event subtypes and in
the response of methods like conversations.history.
This makes sense and works.
But is it possible to get this bot_id value, when a bot has no conversation history?
For example, say the channel between Slackbot and my bot has no conversation history. The response of a conversations.history request to this channel is the following, which does not include the bot_id value.
{
"ok": true,
"channel": {
"id": "DC6N8Q1BK",
"created": 1534129098,
"is_im": true,
"is_org_shared": false,
"user": "USLACKBOT",
"last_read": "0000000000.000000",
"latest": null,
"unread_count": 0,
"unread_count_display": 0,
"is_open": true,
"priority": 0
}
}
Any other way to get the bot_id value?

If there is a bot user, you can get it from the normal userlist with users.list. But that will not include other apps.
Then there is the unofficial API method bots.list. That will give you a list of all bots, but its not officially supported and you will need a legacy token to use as with many undocumented methods.

Related

Teams Graph API, how to place an outgoing call on Hold

I am using the graph API to place an outgoing call from a BOT to a Teams user, with this API :
ret = await graphServiceClient.Communications.Calls
.Request()
.AddAsync(call);
This works OK, and I receive callbacks to say the call is a) establishing and then b) established.
However, if I wish to place this call on Hold from the BOT using the "Participant.StartHoldMusic" call, (see https://learn.microsoft.com/en-us/graph/api/participant-startholdmusic?view=graph-rest-1.0&tabs=csharp#request)
this does not appear possible, because the participant id is needed and this is not being passed with either of the two callbacks mentioned :
Establishing
{
"#odata.type": "#microsoft.graph.commsNotifications",
"value": [
{
"#odata.type": "#microsoft.graph.commsNotification",
"changeType": "updated",
"resource": "/app/calls/a41f5d00-0825-4221-9fd2-2924e62e55a3",
"resourceUrl": "/communications/calls/a41f5d00-0825-4221-9fd2-2924e62e55a3",
"resourceData": {
"#odata.type": "#microsoft.graph.call",
"state": "establishing",
"callChainId": "fe6f4ad4-2187-45d0-967a-af93b0d9bca6"
}
}
]
}
Established:
{
"#odata.type": "#microsoft.graph.commsNotifications",
"value": [
{
"#odata.type": "#microsoft.graph.commsNotification",
"changeType": "updated",
"resource": "/app/calls/a41f5d00-0825-4221-9fd2-2924e62e55a3",
"resourceUrl": "/communications/calls/a41f5d00-0825-4221-9fd2-2924e62e55a3",
"resourceData": {
"#odata.type": "#microsoft.graph.call",
"state": "established",
"mediaState": {
"#odata.type": "#microsoft.graph.callMediaState",
"audio": "active"
},
"callChainId": "fe6f4ad4-2187-45d0-967a-af93b0d9bca6"
}
}
]
}
Also if I look at the object returned from the API to create the call (ret) it shows :
i.e. the target participant id is null.
Furthermore if I try to poll the call object to obtain the participants using the API
graphServiceClient.Communications.Calls[callid].Participants
.Request()
.GetAsync();
The participants collection comes back as null.
How can I place a call on hold using the graph API, if I have no Participant id ?
Update:
It was suggested that I treat the "MyParticipantId" as the participantid of the external party. After establishing a call to a user I tried to hold the call using the MyParticipantId field of the call, with
This results in an exception, code 8522 "Participant not found"
This startHoldMusic API only supports group call.
For P2P call (bot calling a Teams user) its not supported.
For group call, roster update will always happen so that bot is able to get participant id for any of the participants in the call.
This hold music feature is not to put user's Teams client on hold. The target Teams user will still be "active" in the call, but start hearing music instead of others talking.
To make P2P working in this way, bot can just call PlayPrompt API to play audio, since there is no other people in the call.

Google Play Developer API cancelSurveyResult missing from SubscriptionPurchase.Get response

We are implementing server to server notifications for Android in-app purchases.
For each of the user-generated events (purchase, cancellation, etc.), we receive and parse real-time developer notifications, according to Google Play's rtdn reference.
After parsing each notification, we submit the subscription to the play store for verification, according to Google Play Developer API purchases.subscriptions.
The JSON responses we expect back should correspond to the action that the user has taken. For example, after the SUBSCRIPTION_PURCHASED notification was received, the verification response looks like this:
{
"startTimeMillis": "1615196368232",
"expiryTimeMillis": "1615196783756",
"autoRenewing": true,
"priceCurrencyCode": "EUR",
"priceAmountMicros": "3990000",
"countryCode": "DE",
"developerPayload": "",
"paymentState": 1,
"orderId": "GPA.3391-4718-6063-47314",
"purchaseType": 0,
"acknowledgementState": 1,
"kind": "androidpublisher#subscriptionPurchase"
}
Now, the headaches start when the user cancels their subscription (via the Play Store app), thus generating a SUBSCRIPTION_CANCELED notification. The verification response looks like this:
{
"startTimeMillis": "1615196368232",
"expiryTimeMillis": "1615196664327",
"autoRenewing": false,
"priceCurrencyCode": "EUR",
"priceAmountMicros": "3990000",
"countryCode": "DE",
"developerPayload": "",
"cancelReason": 0,
"userCancellationTimeMillis": "1615196648401",
"orderId": "GPA.3391-4718-6063-47314",
"purchaseType": 0,
"acknowledgementState": 1,
"kind": "androidpublisher#subscriptionPurchase"
}
There are some new fields present, defining the cancellation:
"cancelReason": integer,
"userCancellationTimeMillis": string,
This is great and works as expected. However, there are still some cancellation fields missing. Namely, the SubscriptionCancelSurveyResult, defined as:
"cancelSurveyResult": {
"cancelSurveyReason": integer,
"userInputCancelReason": string
}
The documentation mentions for both userInputCancelReason and userCancellationTimeMillis:
Only present if cancelReason is 0.
cancelReason is already 0, as it can be seen in the screenshot attached. However, only userCancellationTimeMillis is present. Why is there no cancelSurveyResult and no userInputCancelReason?
You app can look at the cancelReason in the subscription resource returned from the Google Play Developer API to learn why the subscription was cancelled (e.g. the customer cancelled or had billing issues). If the subscription was cancelled by the user, your app can look at the cancelSurveyResult field to learn why the user cancelled the subscription.
Source: https://developer.android.com/google/play/billing/subscriptions#cancel

Unable to delete a message sent via Incoming Webhooks

I am using Slack Incoming Webhooks requests to post messages to a Slack channel from an app. I love it since I can send messages directly from shell scripts.
However going further I stumble into the problem that I seem to be unable to delete messages.
The app has two access tokens:
An OAuth access token xoxp-012345678901-012345678901-012345678901-0123456789abcdef0123456789abcdef (this is a fictitious token but the length is the same as the actual token).
Bot User OAuth access token xoxb-012345678901-012345678901-0123456789abcdef01234567.
Using the xoxp- OAuth access token I can retrieve channel history.
curl "https://slack.com/api/channels.history?token=xoxp-012345678901-012345678901-012345678901-0123456789abcdef0123456789abcdef&channel=CABCDABCD&count=20&pretty=1"
With the xoxb- token the channels.history request fails with
{
"ok": false,
"error": "not_in_channel"
}
In chat history I have a message that I would like to delete. The message was posted using Incoming Webhooks associated with the App.
{
"type": "message",
"subtype": "bot_message",
"text": ":heavy_check_mark:",
"ts": "1580968882.000800",
"bot_id": "BABCDABCD",
"blocks": [
{
"type": "section",
"block_id": "5Ov",
"text": {
"type": "mrkdwn",
"text": "text of the message to delete",
"verbatim": false
}
}
]
}
However neither token works with chat.delete. Both
curl "https://slack.com/api/chat.delete?token=xoxb-012345678901-012345678901-0123456789abcdef01234567&channel=CABCDABCD&ts=1580968882.000800&pretty=1"
and
curl "https://slack.com/api/chat.delete?token=xoxp-012345678901-012345678901-012345678901-0123456789abcdef0123456789abcdef&channel=CABCDABCD&ts=1580968882.000800&pretty=1"
fail with
{
"ok": false,
"error": "cant_delete_message"
}
And the question is: Is there a way to delete a message posted by an app via Incoming Webhooks requests?
PS. Both chat:write:bot and chat:write:user permissions are granted.
Yes, but the token owner needs to be admin in order to have the right to delete message of other users / apps.
To clarify: This has nothing to do with OAuth scopes, but with the Slack role of the user who owns the token.

Microsoft botframework and slack channel

How do I get the url/team name from a bot framework activity/context? Currently I can get the TeamId but can that be translated into the text string for the teams name?
For example testteam.slack.com, how can I extract the "testteam" part from bot framework messages?
As already mentioned you can call the Slack API method team.info to get the domain name for a team. However, that requires your token to have specific scopes, which you might not have.
It's therefore better to call auth.test, because it does not require any special scopes (except the bot scope for a bot token, but that is implicit). This API method will return the full URL of the Slack team along with other basic info for the provided Slack token.
Note that you need a Slack token corresponding with the team you want to get the info for. The team ID alone is not sufficient to get info about a team. (same for team.info btw). I am not familiar with the botframework, but since it works with Slack it must have a method to retrieve the current Slack token.
Example output:
{
"ok": true,
"url": "https:\/\/subarachnoid.slack.com\/",
"team": "Subarachnoid Workspace",
"user": "grace",
"team_id": "T12345678",
"user_id": "W12345678"
}
You are looking for team.info method in Slack API, that you can query with your Bot User OAuth Access Token (visible in OAuth & Permissions menu, and also available in each bot message in the ChannelData, property named ApiToken).
You can get details about this method here: https://api.slack.com/methods/team.info
In particular, have a look to domain field in the response sample:
{
"ok": true,
"team": {
"id": "Txxxxxx",
"name": "BotDemoCompany",
"domain": "botdemocompany",
"email_domain": "xxxxxxx.com",
"icon": {
"image_34": "https:\/\/a.slack-edge.com\/xxx.png",
"image_44": "https:\/\/a.slack-edge.com\/xxx.png",
"image_68": "https:\/\/a.slack-edge.com\xxx.png",
"image_88": "https:\/\/a.slack-edge.com\/xxx.png",
"image_102": "https:\/\/a.slack-edge.com\/xxx.png",
"image_132": "https:\/\/a.slack-edge.com\/xxx.png",
"image_230": "https:\/\/a.slack-edge.com\/xxx.png",
"image_default": true
}
}
}

Is botId that bot scoped? Is it permanent?

Is the botId that I receive in the webhook only bot scope or is it unique across all the bots found?
Is it permanent or can it be changed?
By botId I mean the id in recipient.id and replyToId that you fill in send message request to endpoint https://smba.trafficmanager.net/apis/v3/conversations/{{skype.idRecipient}}/activities:
{
"text": "God help us!",
"type": "message",
"from": {
"id": "{{skype.idBot}}",
"name": "bot"
},
"recipient": {
"id": "{{skype.idRecipient}}",
"name": "user"
},
"replyToId": "{{skype.idBot}}"
}
The ID you are talking about is unique only in the current channel (Skype/Facebook/Slack...) as it is the ID of ChannelAccount.
Here are some statements from documentation:
Every bot and user has an account within each channel. The account
contains an identifier (id) and other informative bot non-structural
data, like an optional name.
Also
Channel accounts have meaning only within their associated channel
So it's not excluded that id may be repeated on another channels.
And what about permanency, it depends on the channel you use as stated in documentation again:
The stability of associations between IDs, accounts, mailboxes, and
people depends on the channel
But if you want it to be "unique across all the bots found" then you can create an id by combining AppID, ChannelID and User ID.
Also here is a quite informative guide about IDs in Bot Framework which may be helpful to you

Resources