Posted in
Windows Powershell |
No Comment | 1,026 views | 26/10/2017 13:40
If you need to migrate from Kayako Classic to Freshdesk, you may use following script.
This is just an example script that i wrote in a few minutes.
First create connection to Kayako Classic via API information:
Add-Type -AssemblyName System.Web
$apiKey = "e5b3990a-5c6f-6634-2db3-6ff3f5d5036d";
$secretKey = "ZTBmNTIyNTItZTRhZC00ZDQ0LTY1MTktN2Q5MTFlYTUyNDdmNWZiOTRiNDQtZTNhZC0zOTE0LTBkZmQtMGZkMDY4YTRmMmY1";
$salt = [guid]::NewGuid().ToString();
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($secretKey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($salt))
$signature = [Convert]::ToBase64String($signature)
$encodedSignature = [System.Web.HttpUtility]::UrlEncode($signature) |
Add-Type -AssemblyName System.Web
$apiKey = "e5b3990a-5c6f-6634-2db3-6ff3f5d5036d";
$secretKey = "ZTBmNTIyNTItZTRhZC00ZDQ0LTY1MTktN2Q5MTFlYTUyNDdmNWZiOTRiNDQtZTNhZC0zOTE0LTBkZmQtMGZkMDY4YTRmMmY1";
$salt = [guid]::NewGuid().ToString();
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($secretKey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($salt))
$signature = [Convert]::ToBase64String($signature)
$encodedSignature = [System.Web.HttpUtility]::UrlEncode($signature)
Then get prepare for Freshdesk connection. Type your Freshdesk username and password:
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
$userpassB64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("test@domain.com:myPassword!")) |
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
$userpassB64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("test@domain.com:myPassword!"))
User Migration:
$userLink = "http://domain.kayako.com/api/Base/User/Filter&apikey=$apiKey&salt=$salt&signature=$signature"
[xml]$xml = (Invoke-WebRequest $userLink).Content
foreach ($topic in $xml.users.user) {
$contactJson = @{
name = $topic.fullname.InnerText
email = $topic.email.InnerText
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/contacts `
-ContentType "application/json" -Method Post -Body $contactJson
} |
$userLink = "http://domain.kayako.com/api/Base/User/Filter&apikey=$apiKey&salt=$salt&signature=$signature"
[xml]$xml = (Invoke-WebRequest $userLink).Content
foreach ($topic in $xml.users.user) {
$contactJson = @{
name = $topic.fullname.InnerText
email = $topic.email.InnerText
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/contacts `
-ContentType "application/json" -Method Post -Body $contactJson
}
Getting departments from Kayako:
$departmentLink = "http://domain.kayako.com/api/ `
Base/Department&apikey=$apiKey&salt=$salt&signature=$signature"
[xml]$xml = (Invoke-WebRequest $departmentLink).Content
foreach ($topic in $xml.departments.department) {
write-host ID: $topic.id
write-host Title: $topic.title.InnerText
write-Host Type: $topic.type.InnerText
} |
$departmentLink = "http://domain.kayako.com/api/ `
Base/Department&apikey=$apiKey&salt=$salt&signature=$signature"
[xml]$xml = (Invoke-WebRequest $departmentLink).Content
foreach ($topic in $xml.departments.department) {
write-host ID: $topic.id
write-host Title: $topic.title.InnerText
write-Host Type: $topic.type.InnerText
}
Getting tickets from Kayako:
$departmentId = 1
$ticketLink = "http://domain.kayako.com/api/Tickets/Ticket/ListAll/$departmentId/ `
1,2,3,4,5,6,7,8,9&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketLink).Content
foreach ($topic in $xml.tickets.ticket) {
write-host ID: $topic.id
write-host Subject: $topic.subject.InnerText
write-host FullName: $topic.fullname.InnerText
write-host Email: $topic.email.InnerText
write-host Replies: $topic.replies.InnerText
} |
$departmentId = 1
$ticketLink = "http://domain.kayako.com/api/Tickets/Ticket/ListAll/$departmentId/ `
1,2,3,4,5,6,7,8,9&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketLink).Content
foreach ($topic in $xml.tickets.ticket) {
write-host ID: $topic.id
write-host Subject: $topic.subject.InnerText
write-host FullName: $topic.fullname.InnerText
write-host Email: $topic.email.InnerText
write-host Replies: $topic.replies.InnerText
}
Getting ticket posts from Kayako:
$ticketId = 518
$ticketPostLink = "http://domain.kayako.com/api/Tickets/TicketPost/ListAll/$ticketId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketPostLink).Content
foreach ($topic in $xml.posts.post) {
write-host ID: $topic.id.InnerText
write-host FullName: $topic.fullname.InnerText
write-host Contents: $topic.contents.InnerText
write-host Email: $topic.email.InnerText
} |
$ticketId = 518
$ticketPostLink = "http://domain.kayako.com/api/Tickets/TicketPost/ListAll/$ticketId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketPostLink).Content
foreach ($topic in $xml.posts.post) {
write-host ID: $topic.id.InnerText
write-host FullName: $topic.fullname.InnerText
write-host Contents: $topic.contents.InnerText
write-host Email: $topic.email.InnerText
}
Getting ticket notes from Kayako:
$ticketId = 518
$noteLink = "http://domain.kayako.com/api/Tickets/TicketNote/ListAll/$ticketId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $noteLink).Content
foreach ($topic in $xml.notes.note) {
write-host ID: $topic.id
} |
$ticketId = 518
$noteLink = "http://domain.kayako.com/api/Tickets/TicketNote/ListAll/$ticketId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $noteLink).Content
foreach ($topic in $xml.notes.note) {
write-host ID: $topic.id
}
Migrating tickets from Kayako to Freshdesk:
$departmentId = 1
$ticketLink = "http://domain.kayako.com/api/Tickets/Ticket/ListAll/$departmentId/ `
1,2,3,4,5,6,7,8,9&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketLink).Content
foreach ($topic in $xml.tickets.ticket) {
$topicId = $topic.id
$replyCount = 1;
$ticketId = 0;
$ticketPostLink = "http://domain.freshdesk.com/api/Tickets/TicketPost/ListAll/$topicId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$postXml = (Invoke-WebRequest $ticketPostLink).Content
$postIds = $postXml.posts.post.id.InnerText | Sort-Object
foreach ($postId in $postIds)
{
$post = $postXml.posts.post | where {$_.id.InnerText -eq $postId}
if ($replyCount -eq 1)
{
$ticketJson = @{
description = $post.contents.InnerText
subject = $topic.subject.InnerText
email = $post.email.InnerText
priority = 1
status = 5
}| ConvertTo-Json -Compress
$ticketPost = Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets `
-ContentType "application/json" -Method Post -Body $ticketJson
$ticketPostJson = $ticketPost.Content | ConvertFrom-Json
$ticketId = $ticketPostJson.id
$replyCount++
}
else
{
$ticketNoteJson = @{
body = $post.contents.InnerText
private = $false
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets/$ticketId/notes `
-ContentType "application/json" -Method Post -Body $ticketNoteJson
$replyCount++
}
}
} |
$departmentId = 1
$ticketLink = "http://domain.kayako.com/api/Tickets/Ticket/ListAll/$departmentId/ `
1,2,3,4,5,6,7,8,9&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$xml = (Invoke-WebRequest $ticketLink).Content
foreach ($topic in $xml.tickets.ticket) {
$topicId = $topic.id
$replyCount = 1;
$ticketId = 0;
$ticketPostLink = "http://domain.freshdesk.com/api/Tickets/TicketPost/ListAll/$topicId `
&apikey=$apiKey&salt=$salt&signature=$encodedSignature"
[xml]$postXml = (Invoke-WebRequest $ticketPostLink).Content
$postIds = $postXml.posts.post.id.InnerText | Sort-Object
foreach ($postId in $postIds)
{
$post = $postXml.posts.post | where {$_.id.InnerText -eq $postId}
if ($replyCount -eq 1)
{
$ticketJson = @{
description = $post.contents.InnerText
subject = $topic.subject.InnerText
email = $post.email.InnerText
priority = 1
status = 5
}| ConvertTo-Json -Compress
$ticketPost = Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets `
-ContentType "application/json" -Method Post -Body $ticketJson
$ticketPostJson = $ticketPost.Content | ConvertFrom-Json
$ticketId = $ticketPostJson.id
$replyCount++
}
else
{
$ticketNoteJson = @{
body = $post.contents.InnerText
private = $false
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets/$ticketId/notes `
-ContentType "application/json" -Method Post -Body $ticketNoteJson
$replyCount++
}
}
}
First of all, be aware of “status = 5”. I migrated all tickets in “closed” state. But if you have many open tickets in Kayako, you may set it as parameter so you can set them open/closed etc.
You might see that I added the old ticket replies as “public note” into Freshdesk. Reason of this, because Freshdesk API supports “TicketReply” method (this is a new method that they made it in 5 years i guess, according to their forum) but simply you can not say that, “do not send notification to customer”. So only way to do this is using “public note” method. In that case you can disable customer notifications.
To be honest, there are many lack of features in Freshdesk and i mean the core features, in API and in the software itself. Or these guys are really terrible at API side, or they just don’t give any effort to backend API. This was one of the most premature API i was dealing with after years, and this is in almost 2018 :)
If you need to see “TicketReply” method, here it is:
$ticketId = 25
$ticketReplyJson = @{
body = "Details about the issue"
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets/$ticketId/reply `
-ContentType "application/json" -Method Post -Body $ticketReplyJson |
$ticketId = 25
$ticketReplyJson = @{
body = "Details about the issue"
}| ConvertTo-Json -Compress
Invoke-WebRequest -Headers @{Authorization = "Basic $userpassB64"} `
-Uri https://domain.freshdesk.com/api/v2/tickets/$ticketId/reply `
-ContentType "application/json" -Method Post -Body $ticketReplyJson
But be aware, this will send notification to customer because there is no option to disable notifications.
I hope this would a good guidance for you. This is very simple script meet with my requirements. Please test it before migrating real data.
Posted in
Windows Server |
No Comment | 2,536 views | 31/10/2016 13:35
Nano Server monitoring is kind of a challenge for System Administrators. Even if your current monitoring product supports Nano Server, installing agents on Nano could be a headache.
In this article, I will show you how to monitor your Nano Server with VirtualMetric’s Bare Metal Monitoring feature.
VirtualMetric supports following Windows OS without agent and additional software requirements:
* Windows Server 2003/2003 R2
* Windows Server 2008/2008 R2
* Windows Server 2012/2012 R2
* Windows Server 2016
* Nano Server
* Windows 7/8/10
VirtualMetric Bare Metal Monitoring provides:
* More than 100 Performance Counters (All Customizable)
* Hardware Health (Currently supported hardwares are IBM, Dell, HP, SuperMicro, Fujitsu and Cisco)
* Change Tracking
* Event and Security Log Collection
* TCP Activity for Network Based Attacks like DDoS etc.
* Firewall Log Collection (Dropped & Allowed Packets)
* Assessments like Pending Updates, Hotfixes, Services, Processes etc.
First, lets start installing our Nano Server on Azure.
1. Go to your Azure Dashboard and find Nano server in compute: