Skip to content

Commit

Permalink
Merge pull request #1 from AdhocAdam/dev
Browse files Browse the repository at this point in the history
version two
  • Loading branch information
AdhocAdam authored Nov 28, 2023
2 parents e23dab0 + 7cef1c0 commit e5cb085
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 106 deletions.
7 changes: 4 additions & 3 deletions CareLink.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RootModule = 'CareLink.psm1'

# Version number of this module.
ModuleVersion = '1.0'
ModuleVersion = '2.0'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -74,7 +74,8 @@
'Confirm-CareLinkToken',
'Get-CareLinkAccount',
'Get-CareLinkProfile',
'Get-CareLinkData'
'Get-CareLinkData',
'Set-CareLinkToken'
)

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
Expand All @@ -101,4 +102,4 @@
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}
}
276 changes: 198 additions & 78 deletions CareLink.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ This PowerShell module emulates browser interaction to Minimed CareLink to retri
#>

function Get-CareLinkToken {
param (
<#
param (
#The Carelink username
[parameter(ParameterSetName = 'ManualCred', Mandatory = $true, Position = 0)]
[string]$username,
Expand Down Expand Up @@ -82,125 +83,244 @@ function Get-CareLinkToken {
}
return $token
#>

if ($script:CarelinkToken) {
return $script:CarelinkToken
}
else {
return "Token has not been declared. Use Set-CareLinkToken to define it"
}
}

#retrieve user account information such as their Login Date, Account ID, and User Role
function Get-CareLinkAccount {
param (
#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
<#
param (
#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
#>

if ($script:CareLinkToken) {
#verify the token is still valid before proceding
$token = Confirm-CarelinkToken -Token $token
$token = Confirm-CarelinkToken -Token $script:CareLinkToken

$authHeader = @{
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"Authorization" = "Bearer $($Token.Token.value)"
"Referer" = "https://carelink.minimed.com/app/home"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"Authorization" = "Bearer $($script:CareLinkToken.token)"
"Referer" = "https://carelink.minimed.com/app/home"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}

#call the Me rest endpoint
$me = Invoke-RestMethod -Uri "https://carelink.minimed.com/patient/users/me" -Method "GET" -header $authHeader -UserAgent $token.userAgent -WebSession $token.websession
$me = Invoke-RestMethod -Uri "https://carelink.minimed.com/patient/users/me" -Method "GET" -header $authHeader -UserAgent $token.userAgent #-WebSession $token.websession
return $me
}
else {
Write-Error "Token is not defined. Please retrieve a token, expiration date, and then set it with Set-CareLinkToken"
}
}

#retrieve user profile information, username, phone number, etc.
function Get-CareLinkProfile {
param (
#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
<#
param (
#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
#>

if ($script:CareLinkToken) {
#verify the token is still valid before proceding
$token = Confirm-CarelinkToken -Token $token
$token = Confirm-CarelinkToken -Token $script:CareLinkToken

$authHeader = @{
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"Authorization" = "Bearer $($Token.Token.value)"
"Referer" = "https://carelink.minimed.com/app/home"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"Authorization" = "Bearer $($script:CareLinkToken.token)"
"Referer" = "https://carelink.minimed.com/app/home"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}

#call the Me rest endpoint
$me = Invoke-RestMethod -Uri "https://carelink.minimed.com/patient/users/me/profile" -Method "GET" -header $authHeader -UserAgent $token.userAgent -WebSession $token.websession
$me = Invoke-RestMethod -Uri "https://carelink.minimed.com/patient/users/me/profile" -Method "GET" -header $authHeader -UserAgent $token.userAgent #-WebSession $token.websession
return $me
}
else {
Write-Error "Token is not defined. Please retrieve a token, expiration date, and then set it with Set-CareLinkToken"
}
}

function Get-CareLinkData {
param (
#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token,
#The Carelink Account User
[parameter(Mandatory = $true, Position = 1)]
[PSCustomObject]$CarelinkUserProfile,
#The Carelink User's Profile
[parameter(Mandatory = $true, Position = 2)]
[PSCustomObject]$CarelinkUserAccount
)
<#
.SYNOPSIS
Retrieve's a patient's insulin pump information, blood glucose, etc.
.DESCRIPTION
Used to retrieve information about a patient's insulin pump, blood glucose, active alerts, and other information as reported
.EXAMPLE
$clAccount = Get-CareLinkAccount
$clProfile = Get-CareLinkProfile
$data = Get-CareLinkData -CarelinkUserProfile $clProfile -CarelinkUserAccount $clAccount
$data
#>

param (
<#The Carelink username
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token,
#>
#The Carelink Account User
[parameter(Mandatory = $true, Position = 1)]
[PSCustomObject]$CarelinkUserProfile,
#The Carelink User's Profile
[parameter(Mandatory = $true, Position = 2)]
[PSCustomObject]$CarelinkUserAccount
)

if ($script:CareLinkToken) {
#verify the token is still valid before proceding
$token = Confirm-CarelinkToken -Token $token
$token = Confirm-CarelinkToken -Token $script:CareLinkToken

#authentication header to make the request
$authHeader = @{
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"Authorization" = "Bearer $($Token.Token.value)"
"Referer" = "https://carelink.minimed.com/app/home"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.6"
"authorization" = "Bearer $($script:CareLinkToken.token)"
"authority" = "clcloud.minimed.com"
"path" = "/connect/carepartner/v6/display/message"
"origin" = "https://carelink.minimed.com"
"referer" = "https://carelink.minimed.com/"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"Sec-GPC" = "1"
}

#pump, sensor, and glucose
$payload = @{
"username" = $CarelinkUserProfile.username
"role" = $CarelinkUserAccount.role
"username" = $CarelinkUserProfile.username
"role" = $CarelinkUserAccount.role
} | ConvertTo-Json

$data = Invoke-RestMethod -Uri "https://clcloud.minimed.com/connect/v2/display/message" -Method "POST" -body $payload -header $authHeader -UserAgent $token.userAgent -WebSession $token.websession
return $data
$data = Invoke-RestMethod -Uri "https://clcloud.minimed.com/connect/carepartner/v6/display/message" -Method "POST" -Body $payload -header $authHeader #-UserAgent $token.userAgent #-WebSession $token.websession
return $data
}
else {
Write-Error "Token is not defined. Please retrieve a token, expiration date, and then set it with Set-CareLinkToken"
}
}

function Confirm-CareLinkToken {
param (
#The Carelink token to validate
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
<#
.SYNOPSIS
Confirms the Carelink token's validity
.DESCRIPTION
Used by other cmdlets within the module to verify the token being used to retrieve data from Carelink is valid. Can be used independently to verify a token's validity.
.EXAMPLE
Confirm-CareLinkToken
#>

<#
param (
#The Carelink token to validate
[parameter(Mandatory = $true, Position = 0)]
[PSCustomObject]$Token
)
#>

if ($script:CareLinkToken) {
#convert the token expiration string to a datetime object to compare
#string/datetime conversion, https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ee692801(v=technet.10)?redirectedfrom=MSDN
$expiration = [datetime]::ParseExact($token.TokenExpiration.Value.Split("UTC")[0].Trim(), "ddd MMM dd HH:mm:ss", $null)
$expiration = [datetime]::ParseExact($script:CareLinkToken.Expiration.Split("UTC")[0].Trim(), "ddd MMM dd HH:mm:ss", $null)
$nowUTC = (Get-Date).ToUniversalTime()

#compare the expiration date to now
if ($nowUTC -gt $expiration)
{
Write-Output "Token expired. Renewing..."
$newToken = Get-CareLinkToken -username $token.username -password $token.password
return $newToken
#compare the expiration date to now, by adding a minute we know if we're within expiration
if ($nowUTC -gt $expiration) {
Write-Warning "Token expiring. Renewing..."

#request a new token with the current token
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
$session.Cookies.Add((New-Object System.Net.Cookie("auth_tmp_token", "$($script:CareLinkToken.token)", "/", "carelink.minimed.com")))
$session.Cookies.Add((New-Object System.Net.Cookie("c_token_valid_to", "$($script:CareLinkToken.expiration)", "/", "carelink.minimed.com")))
$session.Cookies.Add((New-Object System.Net.Cookie("application_country", "us", "/", "carelink.minimed.com")))
$session.Cookies.Add((New-Object System.Net.Cookie("application_language", "en", "/", "carelink.minimed.com")))
$renewedToken = Invoke-WebRequest -UseBasicParsing -ContentType "application/json; charset=UTF-8" -Uri "https://carelink.minimed.com/patient/sso/reauth" `
-Method "POST" `
-WebSession $session `
-Headers @{
"Accept" = "application/json, text/plain, */*"
"Accept-Encoding" = "gzip, deflate, br"
"Accept-Language" = "en-US,en;q=0.9"
"Authorization" = "Bearer $($script:CareLinkToken.token)"
"Origin" = "https://carelink.minimed.com"
"Referer" = "https://carelink.minimed.com/app/connect"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"sec-ch-ua" = "`"Google Chrome`";v=`"119`", `"Chromium`";v=`"119`", `"Not?A_Brand`";v=`"24`""
"sec-ch-ua-mobile" = "?0"
"sec-ch-ua-platform" = "`"Windows`""
}

#define token object to return from the Headers in the response
$updatedToken = [PSCustomObject]@{
Expiration = ($renewedToken.Headers.'Set-Cookie'.Split(';') | Where-Object { $_.StartsWith("c_token_valid_to") }).Split('=')[1]
Token = ($renewedToken.Headers.'Set-Cookie'.Split(';') | Where-Object { $_.StartsWith("auth_tmp_token") }).Split('=')[1]
Headers = $renewedToken.Headers
}

#update the token used within the module's scope
Set-CareLinkToken -Expiration $updatedToken.Expiration -Token $updatedToken.Token
}
else
{
Write-Output "Token valid"
return $token
else {
Write-Output "Token valid"
return $true
}
}
}
else {
Write-Error "Token is not defined. Please retrieve a token, expiration date, and then set it with Set-CareLinkToken"
}
}

function Set-CareLinkToken {
<#
.SYNOPSIS
Set the Carelink Token and Expiration values
.DESCRIPTION
In order to retrieve data from carelink, you must authenticate with a browser so as to retrieve a valid Token ("auth_tmp_token") and
Token Expiration Date ("c_token_valid_to").
For example, using Dev Tools, copy the Token and Token Expiration date out. Using this cmdlet, you can set those values.
.EXAMPLE
Set-CareLinkToken -Expiration "Fri Nov 20 19:17:44 UTC 2023" -Token "c7822ebd1d9bf24609b7..."
#>

param (
#The Expiration DateTime of the token. For example, Mon Nov 20 01:36:04 UTC 2023
[parameter(Mandatory = $true, Position = 0)]
[string]$Expiration,
#The token to use when making calls to retrieve data, and request new tokens
[parameter(Mandatory = $true, Position = 1)]
[string]$Token
)

#set the carelink token variable to use within the module
$script:CarelinkToken = [PSCustomObject]@{
Expiration = "$Expiration"
Token = "$Token"
}
}
Loading

0 comments on commit e5cb085

Please sign in to comment.