How to share uploaded image in a channel? - slack-api

I upload an image to slack using https://slack.com/api/files.upload
not specifying channels field in the request.
I can see the image in the web interface. What the api call should be to share the uploaded image in some channel at some point in the future?
I tried to upload an image and response from slack was:
{
"ok": true,
"file": {
"id": "FHJ9QTX1V",
"created": 1554115093,
"timestamp": 1554115093,
"name": "scaled_IMG-20190324-WA0002.jpg",
"title": "scaled IMG-20190324-WA0002",
"mimetype": "image/jpeg",
"filetype": "jpg",
"pretty_type": "JPEG",
"user": "UGRR6FCF7",
"editable": false,
"size": 217356,
"mode": "hosted",
"is_external": false,
"external_type": "",
"is_public": false,
"public_url_shared": false,
"display_as_bot": false,
"username": "",
"url_private": "https://files.slack.com/files-pri/TGQU3SCHF-FHJ9QTX1V/scaled_img-20190324-wa0002.jpg",
"url_private_download": "https://files.slack.com/files-pri/TGQU3SCHF-FHJ9QTX1V/download/scaled_img-20190324-wa0002.jpg",
"thumb_64": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_64.jpg",
"thumb_80": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_80.jpg",
"thumb_360": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_360.jpg",
"thumb_360_w": 360,
"thumb_360_h": 270,
"thumb_480": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_480.jpg",
"thumb_480_w": 480,
"thumb_480_h": 360,
"thumb_160": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_160.jpg",
"thumb_720": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_720.jpg",
"thumb_720_w": 720,
"thumb_720_h": 540,
"thumb_800": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_800.jpg",
"thumb_800_w": 800,
"thumb_800_h": 600,
"thumb_960": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_960.jpg",
"thumb_960_w": 960,
"thumb_960_h": 720,
"thumb_1024": "https://files.slack.com/files-tmb/TGQU3SCHF-FHJ9QTX1V-fa34003fce/scaled_img-20190324-wa0002_1024.jpg",
"thumb_1024_w": 1024,
"thumb_1024_h": 768,
"image_exif_rotation": 1,
"original_w": 1040,
"original_h": 780,
"permalink": "https://autolainen.slack.com/files/UGRR6FCF7/FHJ9QTX1V/scaled_img-20190324-wa0002.jpg",
"permalink_public": "https://slack-files.com/TGQU3SCHF-FHJ9QTX1V-3366c52c9c",
"comments_count": 0,
"is_starred": false,
"shares": {},
"channels": [],
"groups": [],
"ims": [],
"has_rich_preview": false
}
}
And then tried to share the image using /api/chat.postMessage:
{
"channel": "CH68ZSHFA",
"text": "test",
"blocks": [
{
"type": "section",
"text": {
"type": "plain_text",
"text": "test"
}
},
{
"type": "image",
"image_url": "https://autolainen.slack.com/files/UGRR6FCF7/FHJ9QTX1V/scaled_img-20190324-wa0002.jpg",
"alt_text": "attachment"
}
],
"as_user": false,
"username": "Client name"
}
I used url from url_private, url_private_download, permalink, permalink_public fields of the file description but got the same response:
{
"ok": false,
"error": "invalid_blocks",
"response_metadata": {
"messages": [
"[ERROR] downloading image failed [json-pointer:/1/image_url]"
]
}
}

Unfortunately there is no official API method to share a file on your workspace after it has been uppladed. So if you don't include the channel(s) in your initial files.upload request there is no official way to share that file later on.
But there is an unofficial API method called files.share, which has that very functionality. It works perfectly, but you will need a legacy token to use it, so this might not be a solution for you.
Another way to use an image on Slack is to include it in a message (as you are trying in your code example). Technically speaking that is not the same as sharing a file on Slack, since it only works for images and provide limited functionality for users.
It will work though, but only if your image URL is public, because chat.postMessage only works with public URLs to images and files on Slack are private by default (which means you need to provide authorization in any request to access that file from outside of Slack).
To get a public URL for your file you can call the API method files.sharedPublicURL after you uploaded it. You will get a public URL as response, which you can then use to include that image in your message.

Related

Unable to add Teams/SharePoint file attachment in a task to ' Tasks by Planner and To Do '

I have a fully built API, that creates tasks into MS Teams "Tasks by Planner and To Do".
MS actual graph API used POST https://graph.microsoft.com/v1.0/planner/tasks
Sample API:
{
"routeId": "7fcxxxxx-xxxx-xxxx-xxxx-5d35838xxxxx",
"userId": "77cxxxxx-xxxx-xxxx-xxxx-5f09858xxxxx",
"tenantId": "dcdxxxxx-xxxx-xxxx-xxxx-31002a1xxxxx",
"title": "Task: Add you task title",
"hospitalAssignment": null,
"percentComplete": 0,
"createdTimestamp": "2021-04-20T01:51:49Z",
"startDateTimestamp": "2021-04-20T18:10:15Z",
"dueDate": "2021-11-20T11:47:33.000Z",
"Notes": "Add some useful notes here",
"checklistItems": [
{
"title": "itema"
},
{
"title": "itemb"
}
],
"attachments": [
{
"url": "https://www.google.com",
"alias": "link"
},
{
"url": "https://teams.microsoft.com/file/....",
"alias": "Test Document 1"
},
{
"url": "https://random.sharepoint.com/sites/...",
"alias": "Test Document 2"
},
],
"comments": "null,",
"priority": null
}
Hitting the above API creates a task in the planner as seen below
So, here is an issue - when I try to click on link it took me to the browser and opens up google which is fine. Now, when I click on Test Document 1 or Test Document 2 it throws an unknown error and Sorry, something went wrong respectively.
After that, I created the task manually and adding the attachments from Add Attachment and paste the links to the file there, then click the files works and opens up the documents.
Assuming you are referring to adding / updating the Planner Task Details for a PlannerTask;
there is a sample provided of adding (PATCH) a pptx file using a 'teams path' as you referred to it.
Note that the path must be (url)encoded.
Tasks - plannerTaskDetail < references
https://learn.microsoft.com/en-us/graph/api/resources/plannerexternalreferences?view=graph-rest-1.0
{
"https%3A//contoso%2Esharepoint%2Ecom/teams/agile/documents/AnnualReport%2Epptx":
{
"#odata.type": "microsoft.graph.externalReference", // required in PATCH requests to edit the references on a task
"alias": "Agile Team Annual Report",
"lastModifiedBy": {
"user": {
"id": "ebf3b108-5234-4e22-b93d-656d7dae5874"
}
},
"lastModifiedDateTime": "2015-09-21T17:45:12.039Z",
"previewPriority": "0009005756397228702",
"type": "PowerPoint"
}
}

Apache Ranger REST API addUsersAndGroups returns 404 not found

We have installed Apache Ranger and the Web UI works fine, most of the REST API method works fine on both PublicAPIsv2 and RoleREST as per https://ranger.apache.org/apidocs/ui/index.html.
I can get “test_role” id by calling GET /public/v2/api/roles/name/test_role which returns the id 409.
I can get test_role content by calling GET /public/v2/api/roles/409
I can change test_role users list by editing the response I get from GET /public/v2/api/roles/409 and submitting it through PUT /public/v2/api/roles/409
The body is:
{
"id": 409,
"isEnabled": true,
"createdBy": "admin",
"updatedBy": "admin",
"createTime": 1598241102841,
"updateTime": 1601975068428,
"name": "test_role",
"options": {},
"users": [
{
"name": "test_user1”,
"isAdmin": true
},
{
"name": “test_user2”,
"isAdmin": true
},
{
"name": “test_user3”,
"isAdmin": false
}
],
"groups": [
{
"name": "test_group”,
"isAdmin": false
}
],
"roles": []
}
But calling PUT /public/v2/api/roles/409/addUsersAndGroups returns “404 not found”.
I tried with the same body as above as parameter, and also with:
{
"users": [
{
"name": “test_user4”,
"isAdmin": true
}
]
}
Would anybody know what is the correct body to send as parameter to:
/public/v2/api/roles/409/addUsersAndGroups?
Also, making a wrong call such as GET /public/v2/api/roles/409/addUsersAndGroups returns “405 method not allowed”. So I believe it shows the end point does exist. I’m not sure why calling PUT public/v2/api/roles/409/addUsersAndGroups with (probably) incorrect body returns “404 not found” and not an error message related to the wrong parameter.
It happens because Apache Ranger API documentation is wrong, remove the suffix /addUsersAndGroups of your endpoint and it will work.
Example: https://ranger_url/service/roles/roles/409
Where 409 is the role ID, as you're using on your example.
The body that is needed:
{
"name": "test_role",
"users": [
{
"name": "test_user1",
"isAdmin": true
}
]
}

Cant create proper OpenID Connect configuration endpoint (v2)

I want to have an application in azure (simple asp.net mvc application) that keeps users in azure, I want to have that done by azure b2c.
I registered application in azure and put all configurations into appsettings.json what I notice is that the url generated by application does not match the one from azure:
Here's from application:
'https://isthereanynewscodeblast.b2clogin.com/isthereanynewscodeblast.onmicrosoft.com/B2C_1_eclaims_login/v2.0/.well-known/openid-configuration'
Here's from B2C:
'https://isthereanynewscodeblast.b2clogin.com/isthereanynewscodeblast.onmicrosoft.com//v2.0/.well-known/openid-configuration'
Similar but not the same. What I have found is that the url is being generated by AzureADB2COpenIdConnectOptionsConfiguration in this method:
internal static string BuildAuthority(AzureADB2COptions AzureADB2COptions)
{
var baseUri = new Uri(AzureADB2COptions.Instance);
var pathBase = baseUri.PathAndQuery.TrimEnd('/');
var domain = AzureADB2COptions.Domain;
var policy = AzureADB2COptions.DefaultPolicy;
return new Uri(baseUri, new PathString($"{pathBase}/{domain}/{policy}/v2.0")).ToString();
}
And here's my .json
"AzureAdB2C": {
"Instance": "https://isthereanynewscodeblast.b2clogin.com",
"Domain": "isthereanynewscodeblast.onmicrosoft.com",
"ClientId": "guid-of-client",
"CallbackPath": "/signin-oidc",
"SignUpSignInPolicyId": "B2C_1_eclaims_login ",
"ResetPasswordPolicyId": "B2C_1_eclaims_reset",
"EditProfilePolicyId": "B2C_1_eclaims_edit"
},
Which does not match the one from AAD :(
Code is from a nuget: Microsoft.AspNetCore.Authorization
It's not protected nor virtual, so I don't see any option to override it.
So my questions are:
is there a way to handle this somehow, so that application can communicate with azure
is there other way to register app, easy like this:
services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
.AddAzureADB2C(options =>
{
Configuration.Bind("AzureAdB2C", options);
});
//EDIT:
Here's manifest from application registration:
{
"id": "438a430b-4e80-4c6c-8f45-dfca460b2e03",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "44234136-6eee-431f-98ea-668343d7a3fd",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-08-18T22:32:28Z",
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "user-log-test",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "isthereanynewscodeblast.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://localhost:44395/signin-oidc",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null
}
Can you please try using this b2c sample app which will give you an idea how to use b2c points. It comes with pre-configured endpoints (below), which you can replace with your tenant and policy later for testing.
{
"AzureAdB2C": {
"Instance": "https://fabrikamb2c.b2clogin.com",
"ClientId": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6",
"Domain": "fabrikamb2c.onmicrosoft.com",
"SignedOutCallbackPath": "/signout/B2C_1_susi",
"SignUpSignInPolicyId": "b2c_1_susi",
"ResetPasswordPolicyId": "b2c_1_reset",
"EditProfilePolicyId": "b2c_1_edit_profile"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
I saw your app manifest file and found that you have not enabled implicit flow. Please Select the app and go to Authentication and select ID Tokens and Access Tokens.
I tried on the sample shared by #Razi and it is working fine end-to-end.

How to delete message replies using Slack API?

I'm getting an error when I try to use Slack API to remove the replies saying the channel doesn't exists.
To validate it, I'm calling the:
https://slack.com/api/channels.history?token={token}&channel={channel}&count=1&inclusive=true&latest={ts}&oldest={ts}
Then I get the message back.
The message I'm getting back is this one:
{
"ok": true,
"latest": "1540555927.024300",
"oldest": "1540555927.024300",
"messages": [
{
"text": "This message was deleted.",
"edited": {
"user": "UD6SLKGEP",
"ts": "1540555928.000000"
},
"type": "message",
"subtype": "tombstone",
"user": "USLACKBOT",
"hidden": true,
"thread_ts": "1540555927.024300",
"reply_count": 1,
"replies": [
{
"user": "UD6SLKGEP",
"ts": "1540555928.024401"
}
],
"subscribed": false,
"unread_count": 1,
"ts": "1540555927.024300"
}
],
"has_more": false,
"is_limited": true
}
As you can see, there is this "This message was deleted." that seems to be generated automatically and keep showing up because I still have replies associated to it.
If I call the same endpoint passing the reply ts (1540555928.024401), for the same channel I get this:
{
"ok": true,
"latest": "1540555928.024401",
"oldest": "1540555928.024401",
"messages": [
{
"type": "message",
"user": "UD6SLKGEP",
"text": "45d7bc14a6fa03 23456789 abcdefghijklmnop",
"bot_id": "BD6AJUY8G",
"thread_ts": "1540555927.024300",
"ts": "1540555928.024401"
}
],
"has_more": false,
"is_limited": true
}
Which means that there is a message there, which is a reply from another message.
The problem starts when I try to remove this reply message.
I call this endpoint:
https://slack.com/api/chat.delete?token={token}
Passing the channel and the reply ts as the payload:
{
"channel": "CD65XB2D7",
"message_ts": "1540555928.024401"
}
Now instead of having the message removed, I get this response:
{
"ok": false,
"error": "channel_not_found",
"warning": "missing_charset",
"response_metadata": {
"warnings": [
"missing_charset"
]
}
}
But the channel exists and I'm using it to remove other messages as well. That happens when I try to remove the reply from a message only.
Is there something special about removing reply messages?
I just found out the problem here:
https://api.slack.com/changelog/2017-10-keeping-up-with-the-jsons#methods
For some reason on my side it's working for messages, but not for replies. I had to move the token to the "Authorization" on header with the Bearer as suggested on this link.

Getting the IoT Edge Module Settings

In the Azure portal, you can see the "IoT Edge Module Settings" :
How do I access this programatically from C#?
When I get the list of modules on the edge device, there doesn't appear to be an option to get the settings?
You use the Microsoft Azure Devices Client SDK/package and attack it this way:
var registryManager = RegistryManager.CreateFromConnectionString(connString); //the connection string for your IOT Hub
var moduleTwins= new List<Twin>();
//var query = registryManager.CreateQuery($"SELECT * FROM devices", 100);
var query = registryManager.CreateQuery("SELECT * FROM devices.modules WHERE deviceId='MyEdgeDevice'",100);
while (query.HasMoreResults) {
var page = await query.GetNextAsTwinAsync();
moduleTwins.AddRange(page);
}
// this gets rid of all that version/metadata noise in a module/device twin
foreach (var module in moduleTwins) {
module.Properties.Reported.ClearMetadata();
module.Properties.Desired.ClearMetadata();
}
Now moduleTwins is now an enumerable list of the Twin object (which is a direct representation of module/device twins). As a fun aside, in there will also be $edgeAgent and $edgeHub twins -- which contain everything - and in the list of modules for edgeAgent, you'll see more of that information for each module (the image, create options, restart policy, etc), which is found in $edgeAgent's properties.desired.modules area
"modules": {
"MyNeatModule": {
"type": "docker",
"settings": {
"image": "myAzureContainerRegistry.io/myneatmodule:amd64.debug",
"createOptions": "{}"
},
"status": "running",
"restartPolicy": "always",
"version": "1.0"
},
and everything you're looking for is in $edgeAgent's properties.reported area:
"modules": {
"SuperNeatAwesomeModule": {
"exitCode": 0,
"statusDescription": "running",
"lastStartTimeUtc": "2018-11-01T18:39:09.8814806Z",
"lastExitTimeUtc": "2018-11-01T18:05:40.8350456Z",
"restartCount": 0,
"lastRestartTimeUtc": "2018-11-01T18:05:40.8350456Z",
"runtimeStatus": "running",
"version": "1.0",
"status": "running",
"restartPolicy": "always",
"type": "docker",
"settings": {
"image": "blahblahblah.azurecr.io/superneatmodule:0.0.2-amd64.debug",
"imageHash": "sha256:ladkjsfaldkjfasdflkjasdfljasfljkasflja4",
"createOptions": "{}",
"env":{}

Resources