How do I post multiline message using Teams Webhooks? - json

I have a webhook setup to post a message to one of our Teams Team channels. I'm using one of the teams webhook examples given here: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference#hero-card .
The problem I have is that I am unable to display multiple lines. In the example below, I'd like to separate out 'Test1' and 'Test2' on separate lines. However, using \n or \n in the JSON didn't translate to multi line format in Teams. Screenshot outcome attached below.
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.hero",
"content": {
"title": "Alerts",
"text": "*Test1 \n *Test\n",
"buttons": [
{
"type": "openUrl",
"title": "Open in SumoLogic",
"value": ""
}
]
}
}
]
}
What is the way to send a multi-line message to Teams using webhook? Any guidance here is appreciated.

Please try using \n\n and check.

I know this is an old post, but if anyone still needs this you can use AdaptiveCards
$ using AdaptiveCards;
AdaptiveCard card = new AdaptiveCard("1.5");
card.AdditionalProperties.Add("$schema", "http://adaptivecards.io/schemas/adaptive-card.json");
var msTeamsWidthOption = new { width = "Full" };
card.AdditionalProperties.Add("msteams", msTeamsWidthOption);
AdaptiveTextBlock titleBlock = new AdaptiveTextBlock
{
Size = AdaptiveTextSize.Large,
Weight = AdaptiveTextWeight.Bolder,
Wrap = true,
Text = title
};
AdaptiveTextBlock messageBlock = new AdaptiveTextBlock
{
Wrap = true,
Text = message
};
card.Body.Add(titleBlock);
card.Body.Add(messageBlock);
AdaptiveCardWrapper adaptiveCardWrapper = new AdaptiveCardWrapper
{
attachments = new List<Attachments> { new Attachments { content = card} }
};
var address = Environment.GetEnvironmentVariable("WebhookUrl");
var content = new StringContent(JsonConvert.SerializeObject(adaptiveCardWrapper), Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(address, content);
You can use line breaks within a string with "Wrap = true", or you can add multiple cards to a single message. Or both.
https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using?tabs=cURL#send-adaptive-cards-using-an-incoming-webhook

Related

How to check if the response includes specified value and if so - end test in Postman

I'm learning Postman test scripts and I am stuck with one exercise. I need to check if the response includes specified value (one of the planet from array is called Tatooine). Body response:
"results": [
{
"name": "Tatooine",
"rotation_period": "23",
"orbital_period": "304",
"diameter": "10465",
{
"name": "Alderaan",
"rotation_period": "24",
"orbital_period": "364",
"diameter": "12500",
},
I created this script:
const jsonData = pm.response.json();
pm.test("Your test name", function () {
for (let i = 0; i <= jsonData.results.length; i++) {
pm.expect(jsonData.results[i].name).to.include("Tatooine")};
});
But I don't know how to get out of the loop and mark test as "passed" after finding searched value.
I assume you want to verify that at least there is a name Tatooine.
Step 1: Get all names
const jsonData = pm.response.json();
let names = _.map(jsonData.results, "name");
Step 2: Validate the array names contains Tatooine
pm.test("Your test name", function () {
pm.expect(names).to.include("Tatooine")
});

discord.js 12 any way to send data from json file to channel?

I have json file, that contains info about some players, that looks like this
{
"208505383361314816": {
"warns": 8,
"reason": "test"
},
"776387838350196756": {
"warns": 99,
"reason": ""
}
}
Then I sort the information by the number of warns. It works perfectly, but i have no idea, how to send a message.
client.on('message', message => {
if (message.content.startsWith('>topw')) {
const sorted = [];
const keys = Object.keys(warns)
for (let user in warns) {
const warny = warn[user].warns;
const entry = {
[keys[sorted.length]]: warns[user]
}
if (sorted.length === 0) {
sorted.push(entry);
continue;
}
let i = 0;
while (sorted[i] !== undefined && sorted[i][Object.keys(sorted[i])].warns > warny) {
i++;
}
sorted.splice(i, 0, entry)
}
console.log(sorted)
}
})
It should look like a "leaderboard", but with amount of warns
e.g:
name: Bob
warns: 20
reason: test
Welcome to StackOverflow! :)
About your JSON file
First of all, quick advice regarding the way you store data: you really, really should store the user info in an array, it would look like that:
[
{
"id": "00000000",
"warns": 10,
"reason": "test"
}
]
Getting your data ready
That being said, let's answer your question.
I guess that you'd love to use MessageEmbeds, take a look at the docs before reading the code, it might help. I will also rewrite a little bit of your code.
Reformating it
To make our life easier, we'll reformat the data so we can sort it.
// It's just your JSON file here
const oldWarns = {
"208505383361314816": {
"warns": 8,
"reason": "test"
},
"776387838350196756": {
"warns": 99,
"reason": ""
}
}
let newWarns = Object.keys(oldWarns).map((e) => ({
id: e,
warns: oldWarns[e].warns,
reason: oldWarns[e].reason
}))
console.log(newWarns)
Sorting it
Now that we've got this beautiful array, let's sort it. It's much simpler than you think!
// Precedently generated data
let newWarns = [{
"id": "208505383361314816",
"warns": 8,
"reason": "test"
},
{
"id": "776387838350196756",
"warns": 99,
"reason": ""
}
]
newWarns.sort((a, b) => (a.warns > b.warns ? 1 : -1))
console.log(newWarns)
Sending the data
What you actually asked for.
Rendering it with an embed
Alright, everything is set so we can send the data. Here's how to use embeds in Discord.js.
const warnBoard = new Discord.MessageEmbed()
.setTitle("Warnboard")
.setColor("#FF0000")
.addFields(newWarns.flatMap((e, i) => ( // flatMap will delete all the [] of the array after mapping it
i >= 25 ? [] : { // the max number of fields in embeds is 25
name: e.id,
value: e.warns,
inline: true // changes the layout
}
)))
I just used a few of MessageEmbed's features. They can be really nice looking, so feel free to mess around with its props!
Making it as simple as it can get
Embeds are too much? You can also just send a string.
const stringifiedData = JSON.stringify(newWarns, null, 4)
const warnBoard = "```json\n"+ stringifiedData +"\n```"
Send it
Whether the solution you chose is the string or the embed, this is the way you're gonna send the data.
message.channel.send(warnBoard)

Update TFS Web with a Python script

How can I update a certain field in tfs web with Python?
I have connected to tfs and have received an HTML response.
I have a json with the data that I would like to insert to tfs testCases field.
JSON:
data = json.loads(url.read().decode()) (Json external data)
HTML:
tfsResponse = requests.get(tfsApi, auth=HttpNtlmAuth(username, password))
if tfsResponse.ok:
print(tfsResponse)
soup = BeautifulSoup(tfsResponse.text, 'lxml')
How can I do it?
It's not able to directly use Jenkins automation tests results to update TFS test case.
You need use Rest API to handle this. You need to extract the test results fist then update them to TFS server.
With using below Rest API:
PATCH https://dev.azure.com/{organization}/{project}/_apis/test/Runs/{runId}/results?api-version=5.1
Sample body
[
{
"state": "Completed",
"testPoint": {
"id": 10
},
"outcome": "Passed",
"testCase": {
"id": 4567
}
}
]
If you want to use code, a code snippet for your reference, should similar to Python:
try
{
var u = new Uri("https://{My Account}.visualstudio.com");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "PAT"));
var connection = new VssConnection(u, c);
var testClient = connection.GetClient<TestManagementHttpClient>();
int testpointid = 1;
string teamProject = "MyProjectName";
RunCreateModel run = new RunCreateModel(name: "TestCase Name", plan: new Microsoft.TeamFoundation.TestManagement.WebApi.ShallowReference("TestPlan Id"), pointIds: new int[] { testpointid });
TestRun testrun = testClient.CreateTestRunAsync(run, teamProject).Result;
TestCaseResult caseResult = new TestCaseResult() { State = "Completed", Outcome = "passed", Id = 100000 };
var testResults = testClient.UpdateTestResultsAsync(new TestCaseResult[] { caseResult }, teamProject, testrun.Id).Result;
RunUpdateModel runmodel = new RunUpdateModel(state: "Completed");
TestRun testRunResult = testClient.UpdateTestRunAsync(runmodel, teamProject, testrun.Id, runmodel).Result;
}
catch (AggregateException e)
{
Console.WriteLine(e.InnerException.Message);
}

Add new attribute to JSON

Using Node js and Sequelize ORM, i'm getting a data set. I need to add a new attribute to received data and send it to client side. This is what i tried.
Code Block 1
var varAddOns = { "id" : 5, "Name" : "Cheese"};
global.meal.findOne(
{
where: { id: 5 }
}).then(varMeal => {
var obj = {};
obj = varMeal;
obj.addons = varAddOns;
res.send(obj);
});
It returns a json like below. (Actually it does not contain "addons" data)
Code Block 2
{
"id": 12,
"mealName": "Burger",
"description": "Oily food",
}
but actually what i want is,
Code Block 3
{
"id": 12,
"mealName": "Burger",
"description": "Oily food",
"addons" : {
"id" : 5,
"Name" : "Cheese"
}
}
I tried something like below and it also wont work. (It returns same json as "Code Block 2'.)
Code Block 4
var newJson = {};
newJson = JSON.stringify(varMeal);
newJson['addons'] = varAddOns;
var retVal = JSON.parse(newJson);
res.send(retVal);
Can you help me to figure out, where the issue is?
EDIT
Code Block 5
var newJson = {};
newJson = varMeal;
newJson['addons'] = varAddOn;
var retVal = newJson;// JSON.parse(newJson);
res.send(retVal);
I tried 'Code block 5' as well. Same result comes out as 'Code block 2'. When I use JSON.parse(newJson), it was thrown an error. (Error is Unexpected token o in JSON at position 1)
You need to call .get on your model instance, and then attach extra properties to it:
var varAddOns = { "id" : 5, "Name" : "Cheese"};
global.meal.findOne(
{
where: { id: 5 }
}).then(varMeal => {
var obj = {};
obj = varMeal.get();
obj.addons = varAddOns;
res.send(obj);
});
A few things:
When you call findOne, Sequelize return a model instance, not a plain JS object with your data.
If you want to add extra properties to send to your user, you will first need to convert your model instance to a JS object with your data. You can do this by calling varMeal.get(). From there, you can add extra properties to it.
There is no need to prepend your variables with "var". It would be better to simply name your variable meal
you need the JSON to be an object when you are declaring newJson['addons'] as a nested object
Have you tried (in code block 4) not stringifying varMeal?

Bitly, Json, and C#

I'm working on something that involved using the Bit.ly API, and allow the user to select theformat (Text, XML, Json) the text & XML are completed. This is the Json result that is returned when you shorten a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"url": "http:\/\/rlm.cc\/gtYUEd",
"hash": "gtYUEd",
"global_hash": "evz3Za",
"new_hash": 0
}
}
And this C# code works just fine to parse it and get the short URL:
var serializer2 = new JavaScriptSerializer();
var values2 = serializer2.Deserialize<IDictionary<string, object>>(json);
var results2 = values2["data"] as IDictionary<string, object>;
var shortUrl2 = results2["url"];
expandedUrl = results2["url"].ToString();
return results2["url"].ToString();
Now here's the Json sent back when expanding a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"expand":
[
{
"short_url": "http:\/\/rlm.cc\/gtYUEd",
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"user_hash": "gtYUEd",
"global_hash": "evz3Za"
}
]
}
}
Ad that's where my problem begins, how can I change my current C# to be able to handle both scenarios, because as you can see their vastly different from each other. Any ideas?
I usually use Json.NET to cherrypick values out of JSON documents. The syntax is very concise. If you reference NewtonSoft.Json.dll and use Newtonsoft.Json.Linq, you can write the following:
var job = JObject.Parse(jsonString);
if (job["data"]["expand"] == null)
{
Console.WriteLine((string)job["data"]["url"]);
}
else
{
Console.WriteLine((string)job["data"]["expand"][0]["long_url"]);
}
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": {""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""url"": ""http:\/\/rlm.cc\/gtYUEd"", ""hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"", ""new_hash"": 0 }}";
the routine will display http://rlm.cc/gtYUEd.
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": { ""expand"": [ { ""short_url"": ""http:\/\/rlm.cc\/gtYUEd"", ""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""user_hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"" } ] } }";
the routine will display http://panel.aspnix.com/Default.aspx?pid={Removed}.
Not sure I got your problem. Why aren't you testing, if you got a shortening result or a expanding result? Since they are different, this could easily be done via simple 'if ()' statements:
if (results2.ContainsKey("expand")) {
// handle the expand part
} else {
// handle the shorten part
}
Assuming that the provider is consistent with which form it sends, do you need to have code that handles both? It should be direct to handle each individually.
If you can't know ahead of time which format you will get back, you can do the following:
if (results2.ContainsKey("expand"))
{
//Second example
}
else
{
//First example
}