Datamark.by

Dashboard

Сбор метрик личного кабинета "Электронный знак"
Last updated: 5 months ago

Start with Grafana Cloud and the new FREE tier. Includes 10K series Prometheus or Graphite Metrics and 50gb Loki Logs

Downloads: 8

Reviews: 0

  • Datamark.by.png
    Datamark.by.png

Работает на Powershell 5 начиная с Win7SP1/Win8.1/Win2012.

Команды:

  • Get-DatamarkBYOrders - сбор метрик по заказам
  • Get-DatamarkBYShips - сбор метрик по отгрузкам
  • Get-DatamarkBYMetrics - сбор всех метрик

Параметры:

  • username - имя пользователя
  • password - пароль
  • hash - имя файла, содержащего зашифрованные имя пользователя и пароль
  • days_from - начало даты запроса метрик в днях от текущей даты
  • days_to - конец даты запроса метрик в днях от текущей даты
  • uri - адрес API

При перовом запуске команд с параметрами username и password будет создаваться два файла, имена которых являются хэши данных аутентификации и токена. Расположение файлов зависит от имени пользователя, под которым запускается служба сборщика метрик Telegraf (для пользователя "Локальная система" это каталог "Windows\System32"). Для того, чтобы не хранить данные аутентификации (логин и пароль) в конфигурационном файле сборщика метрик Telegraf, необходимо в качестве параметра hash указать имя файла (один из двух файлов с наименьшим размером).

Telegraf config:

[global_tags]

[agent]
  interval = "10s"
  round_interval = true
  metric_buffer_limit = 5000
  flush_buffer_when_full = true
  collection_jitter = "0s"
  flush_interval = "10s"
  flush_jitter = "0s"
  debug = false
  quiet = false
  logfile = "/Program Files/Telegraf/telegraf.log"
  hostname = ""

[[outputs.influxdb]]
  urls = ["http://docker:8086"] # required
  database = "telegraf" # required
  precision = "s"
  timeout = "5s"
  username = "username"
  password = "password"
  [outputs.influxdb.tagdrop]
    influxdb_tag = ["*"]
    
[[outputs.influxdb]]
  urls = ["http://docker:8086"]
  database = "datamarkby"
  precision = "s"
  timeout = "5s"
  username = "username"
  password = "password"
  [outputs.influxdb.tagpass]
    influxdb_tag = ["datamarkby"]

[[inputs.exec]]
  interval = "1h"
  commands = [
    "powershell Get-DatamarkBYOrders -hash 'hash'",
    "powershell Get-DatamarkBYShips -hash 'hash' -days_from 30"
  ]
  timeout = "5m"
  name_suffix = ""
  data_format = "influx"
  [inputs.exec.tags]
    influxdb_tag = "datamarkby"

Collector Configuration Details

Windows\System32\WindowsPowerShell\v1.0\Modules\Influxdata.Telegraf.DatamarkBY\Influxdata.Telegraf.DatamarkBY.psm1

[console]::OutputEncoding = [System.Text.Encoding]::UTF8

function isEmpty($value) {
    if ([string]::isnullorempty($value)) { return "0" } # Empty string or Null
    else { return $value -Replace " ", "\ " -Replace ",", "." }
}

function Get-SecureFromString {
    param (
        [parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$string
    )
    
    return $string | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
}

function Get-StringFromSecure {
    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$secure
    )
    
    try {
        $string = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR(($secure | ConvertTo-SecureString -EA 0)))
    }
    catch {
        Write-Debug $_.Exception.Message
        return $null
    }
    return $string
}

function Get-SecureFromAuth { # Convert username/password to hash
    param (
        [parameter(Mandatory = $true)][string]$username,
        [parameter(Mandatory = $true)][string]$password
    )
    
    return ($username + [char]29 + $password) | Get-SecureFromString
}

function Get-AuthFromSecure { # Convert hash to username/password
    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$hash
    )
    
    if ($auth = $hash | Get-StringFromSecure) {
        $auth = $auth.Split([char]29)
        if ($auth.count -eq 2) { return @{username = $auth[0]; password = $auth[1]} }
    }
    Write-Debug "Get-AuthFromSecure: auth not found"
    return $null
}

function Get-HashFromString {
    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$string,
        [string]$algorithm = 'MD5'
    )
    
    try {
        $ms = [System.IO.MemoryStream]::new()
        $sw = [System.IO.StreamWriter]::new($ms)
        $sw.Write($string)
        $sw.Flush()
        $ms.Position = 0
        $hash = (Get-FileHash -InputStream $ms -Algorithm $algorithm).Hash
    }
    catch {
        Write-Debug $_.Exception.Message
        return $null
    }
    return $hash
}

function Get-DatamarkBYToken {
    [CmdletBinding()]
    param (
        [AllowNull()][AllowEmptyString()][string]$username,
        [AllowNull()][AllowEmptyString()][string]$password,
        [AllowNull()][AllowEmptyString()][string]$hash,
        [string]$uri = 'https://api.datamark.by'
    )
    
    function Check-DatamarkBYToken {
        [CmdletBinding()]
        param (
            [parameter(Mandatory = $true)][string]$username,
            [parameter(Mandatory = $true)][string]$password,
            [AllowNull()][AllowEmptyString()][string]$token,
            [string]$uri = 'https://api.datamark.by'
        )
        
        if ($token) {
            $response = Get-DatamarkBYRequestResponse -request '/directories' -method 'Post' -token $token -uri $uri
        }
        if ($response -eq $null) {
            try {
                $response = Invoke-RestMethod -Method 'Post' -Uri ($uri + '/auth') -Body @{username = $username; password = $password}
            }
            catch {
                Write-Debug $_.Exception.Message
                return $null
            }
            return $response.token # return new token
        }
        return $token # return old token
    }
    
    if ($hash -and (Test-Path $hash)) {
        if ($auth = Get-Content $hash | Get-AuthFromSecure) { $username = $auth.username; $password = $auth.password }
    }
    if (!$username -or !$password) {
        Write-Debug "Get-DatamarkBYToken: hash not found"
        return $null
    }
    
    # Get MD5 hash from username
    $username_hash = $username | Get-HashFromString
    if (Test-Path $username_hash) { # Get token from file by MD5 hash
        $token = Get-Content $username_hash | Get-StringFromSecure
    }
    $token_check = Check-DatamarkBYToken -username $username -password $password -token $token -uri $uri
    if ($token -ne $token_check -and $token_check) { # Get a new token and save it
        $token_check | Get-SecureFromString | Set-Content $username_hash
        Get-SecureFromAuth -username $username -password $password | Set-Content ( ($username + [char]29 + $password) | Get-HashFromString)
    }
    return $token_check
}

function Get-DatamarkBYRequestResponse {
    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true)][string]$request,
        [parameter(Mandatory = $true)][string]$method,
        [parameter(Mandatory = $true)][string]$token,
        [string]$body = '{}',
        [string]$uri = 'https://api.datamark.by'
    )
    
    Write-Debug ($method + ' ' + $uri + $request)
    try {
        if ($body -eq '{}') { # For Get method
            $response = Invoke-RestMethod -Method $method -Uri ($uri + $request) -Headers @{token = $token}
        }
        else {
            $response = Invoke-RestMethod -Method $method -Uri ($uri + $request) -Headers @{token = $token} -Body $body
        }
    }
    catch {
        Write-Debug "$_.Exception.Response.StatusCode.value__: $_.Exception.Response.StatusDescription"
        return $null
    }
    return $response
}

function Build-DatamarkBYRequestBody {
    param (
        [parameter(Mandatory = $true)][string]$date_from,
        [parameter(Mandatory = $true)][string]$date_to,
        [byte]$label_type = 0,
        [byte]$page = 1
    )
    
    if ($label_type -eq 0) { # ships body
        $body = "{
            `"date_from`": `"$date_from`",
            `"date_to`": `"$date_to`",
            `"page`": $page
        }"
    }
    else { # orders body
        $body = "{
            `"date_from`": `"$date_from`",
            `"date_to`": `"$date_to`",
            `"date_type`": `"created`",
            `"label_type`": $label_type,
            `"page`": $page
        }"
    }
    return $body
}

function Get-DatamarkBYOrders {
    param (
        [string]$username,
        [string]$password,
        [string]$hash,
        [byte]$days_from = 0,
        [byte]$days_to = 0,
        [string]$uri = 'https://api.datamark.by'
    )
    
    if ($days_to -gt $days_from) { return }
    else {
        $date_from  = (Get-Date (Get-Date).AddDays(-$days_from) -Format 'yyyy-MM-dd').ToString()
        $date_to    = (Get-Date (Get-Date).AddDays(-$days_to)   -Format 'yyyy-MM-dd').ToString()
    }
    if (!($token = Get-DatamarkBYToken -username $username -password $password -hash $hash)) { return }
    
    $base   = "datamarkby_orders"
    $tags   = "label_type={0}"
    $values = "id={1}i,count={2}i,status={3}i {4}000000000"
    $output = $base + "," + $tags + " " + $values
    5..7 | % { # 5 - Серийный номер; 6 - Код агрегации (SSCC); 7 - Код стран ЕАЭС идентификации товара
        $label_type = $_
        if ($label_type -eq 7) {
            $tags   = "label_type={0},gtin={1}"
            $values = "id={2}i,count={3}i,status={4}i {5}000000000"
            $output = $base + "," + $tags + " " + $values
        }
        $body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -label_type $label_type
        $request = '/orders/list'
        $method = 'Post'
        $response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
        if ($response -and $response.count -gt 0) {
            $pages = [math]::Ceiling($response.count / $response.orders_list.count)
            1..$pages | % {
                $response.orders_list | % {
                    if ($label_type -eq 7) {
                        $output -f (isEmpty($_.type.id)), (isEmpty($_.gtin)), (isEmpty($_.id)), (isEmpty($_.count)), (isEmpty($_.status.code)), `
                            (Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
                    }
                    else {
                        $output -f (isEmpty($_.type.id)), (isEmpty($_.id)), (isEmpty($_.count)), (isEmpty($_.status.code)), `
                            (Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
                    }
                }
                if ($_ -ne $pages) {
                    $body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -label_type $label_type -page ($_ + 1)
                    $response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
                }
            }
        }
    }
}

function Get-DatamarkBYShips {
    param (
        [string]$username,
        [string]$password,
        [string]$hash,
        [byte]$days_from = 0,
        [byte]$days_to = 0,
        [string]$uri = 'https://api.datamark.by'
    )
    
    if ($days_to -gt $days_from) { return }
    else {
        $date_from  = (Get-Date (Get-Date).AddDays(-$days_from) -Format 'yyyy-MM-dd').ToString()
        $date_to    = (Get-Date (Get-Date).AddDays(-$days_to)   -Format 'yyyy-MM-dd').ToString()
    }
    if (!($token = Get-DatamarkBYToken -username $username -password $password -hash $hash)) { return }
    
    $base = "datamarkby_ships"
    $body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to
    $request = '/ships/shipped'
    $method = 'Post'
    $response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
    if ($response -and $response.count -gt 0) {
        $pages = [math]::Ceiling($response.count / $response.ships_list.count)
        1..$pages | % {
            $response.ships_list | % {
                $tags   = "currency={0},user_to_name={1},user_to_unp={2},user_to_country={3},country={4}"
                $values = "id={5}i,real_count={6}i,received_count={7}i,status={8}i,price={9},doc_name=`"{10}`",contract_id={11}i {12}000000000"
                $output = $base + "," + $tags + " " + $values
                $output -f (isEmpty($_.price.currency)), (isEmpty($_.user_to.name)), (isEmpty($_.user_to.unp)), (isEmpty($_.user_to.country)), (isEmpty($_.country.id)), `
                    (isEmpty($_.code)), (isEmpty($_.real_count)), (isEmpty($_.received_count)), (isEmpty($_.status.code)), (isEmpty($_.price.price)), (isEmpty($_.name)), (isEmpty($_.contract.id)), `
                    (Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
                $ships = Get-DatamarkBYRequestResponse -request ('/ships/' + $_.code) -method 'Get' -token $token -uri $uri
                if ($ships) {
                    $tags   = "currency={0},user_to_name={1},user_to_unp={2},user_to_country={3},country={4},gtin={5},name={6},articul={7}"
                    $values = "id={8}i,count={9}i,status={10}i,price={11},doc_name=`"{12}`",contract_id={13}i {14}000000000"
                    $output = $base + "," + $tags + " " + $values
                    foreach ($item in $ships.items) {
                        $output -f (isEmpty($_.price.currency)), (isEmpty($_.user_to.name)), (isEmpty($_.user_to.unp)), (isEmpty($_.user_to.country)), (isEmpty($_.country.id)), (isEmpty($item.gtin)), (isEmpty($item.name)), (isEmpty($item.articul)), `
                            (isEmpty($_.code)), (isEmpty($item.count)), (isEmpty($_.status.code)), (isEmpty($_.price.price)), (isEmpty($_.name)), (isEmpty($_.contract.id)), `
                            (Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
                    }
                }
            }
            if ($_ -ne $pages) {
                $body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -page ($_ + 1)
                $response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
            }
        }
    }
}

function Get-DatamarkBYMetrics {
    param (
        [string]$username,
        [string]$password,
        [string]$hash,
        [byte]$days_from = 0,
        [byte]$days_to = 0,
        [string]$uri = 'https://api.datamark.by'
    )
    
    Get-DatamarkBYOrders    -username $username -password $password -hash $hash -days_from $days_from -days_to $date_to -uri $uri
    Get-DatamarkBYShips     -username $username -password $password -hash $hash -days_from $days_from -days_to $date_to -uri $uri
}
Dependencies: