Simple PowerShell script to send commands to your servers using Telegram

This is a template in order to send messages to your server to run commands or do checks on the server. I use it on a Ubuntu 18.04 server to trigger LXD backups (Sorry Linux Admins, I was too lazy to rewrite it in Python). Another Telegram “Bot” runs on my little home lab to restart and start servers via Telegram. This script has been tested on Windows and Linux Ubuntu 18.04.

Prerequisites:

  • PowerShell
  • A Telegram account
  • A Telegram bot (How to here)

Table of Contents

The Script explained

The script has 3 parts divided into functions and a never-ending while loop at the end of the script to constantly check for new messages on the bot. Fill in the highlighted lines with the information of the @botfather, or visit this page to set it up. To get your ID set the bot up with your BotToken, let it run and send it a message. It will answer with your Telegram ID.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$BotToken = "1160745WoldMd85ko"
$TelegramApiUri = "https://api.telegram.org/bot$($BotToken)"
[string]$AllowedID = "YourID"

Send-TelegramMessage

This function tries to send your provided message, it does a basic check for the response of the Telegram URL on the highlighted line. After that, it shows you which message was sent and if it was successfully transmitted to Telegram.

Function Send-TelegramMessage {
    param(
        [string]$Text,
        [string]$Userid
    )
    $Uri = $TelegramApiUri + "/sendMessage"
    $obj = @{chat_id = ([string]$UserId); text = [string]$text } | ConvertTo-Json
    $Result = Invoke-WebRequest -Method Post -ContentType "application/json;charset=utf-8" -Uri $Uri -Body $Obj -ErrorAction SilentlyContinue
    if ($Result.StatusDescription -like "OK") {
        Write-Host -ForegroundColor Green -Object "$Text has been sent"
    }
    else {
        Write-Host -ForegroundColor Red -Object "An error occured while sending $($Text)"
    }
}

Get-TelegramUpdates

This function is managing the updates our bot receives by keeping track of the offset value. The offset is basically the identifier of the message we want to receive. By the API documentation of Telegram “/getupdates” it needs to be greater by one than the highest among the identifiers of previously received updates. Hence the +1 on the marked line.

Function Get-TelegramUpdates() {
    $OffsetPath = "$env:TEMPoffset.txt"
    if (!(Test-Path $OffsetPath)) {
        New-Item -Path $OffsetPath -ItemType File
    }
    $Offset = Get-Content -Path $OffsetPath
    $Uri = $TelegramApiUri + "/getUpdates"
    $ResultJson = Invoke-WebRequest -Uri $Uri -UseBasicParsing -Body @{offset = $Offset } | ConvertFrom-Json
    $Offset = $ResultJson.result[0].update_id
    if ($offset -gt 1000) {
        $Offset + 1 | Set-Content -Path $OffsetPath -Force
    }
    return $ResultJson.result[0]
}

Get-TelegramMessage

This function is the one you need to change in order to do your zen with the script. Line 12 is to check if the message is empty or not. If it is the function returns and waits for the next check. The next check (Line 20) is to “proof” your identity to the script, please be aware this only provides some simple security. The last highlighted part of the script is where you put your magic. I like to work with if, else if and else in order to send the user a message when a command is unknown or wrong.

Function Get-TelegramMessages {
    param (
        [Parameter()]
        $AllowedID,
        [string]
        $TelegramApiUri
    )
    $result = Get-TelegramUpdates
    if ($result -like $null -or $result -like "") {
        return
    }
    $TelegramUserId = $result.message.from.id
    $UserMessage = $result.message.text
    #Checks for your ID
    if ($TelegramUserId -notin "$AllowedID") {
        Send-TelegramMessage -Text "Your ID is $TelegramUserId, the script does not know you." -Userid $TelegramUserId
        return
    }
    else {
        if ($UserMessage.tolower() -like "*start vm1*") {
            Start-VM -Name "vm1"
            $Message = "Starting VM1"
            Send-TelegramMessage -Text $Message -Userid $TelegramUserId
        }
        else {
            Send-TelegramMessage -Text "Unknown Command"  -Userid $TelegramUserId
        }
    }
}

Constant checks

The last part of the script is self explanatory, we provide the function Get-TelegramMessages the BotToken and an ID that is allowed to send commands to our server.

while ($true) {
    Start-Sleep 1
    Get-TelegramMessages -AllowedID $AllowedID -TelegramApiUri $TelegramApiUri
}

TLDR just give me the script

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$BotToken = "1160fistofzeno"
$TelegramApiUri = "https://api.telegram.org/bot$($BotToken)"
$AllowedID = "MYTelegramID","SecondID"
Function Send-TelegramMessage {
    param(
        [string]$Text,
        [string]$Userid
    )
    $Uri = $TelegramApiUri + "/sendMessage"
    $obj = @{chat_id = ([string]$UserId); text = [string]$text } | ConvertTo-Json
    $Result = Invoke-WebRequest -Method Post -ContentType "application/json;charset=utf-8" -Uri $Uri -Body $Obj -ErrorAction SilentlyContinue
    if ($Result.StatusDescription -like "OK") {
        Write-Host -ForegroundColor Green -Object "$Text has been sent"
    }
    else {
        Write-Host -ForegroundColor Red -Object "An error occured while sending $($Text)"
    }
}
Function Get-TelegramUpdates() {
    $OffsetPath = "$env:TEMPoffset.txt"
    if (!(Test-Path $OffsetPath)) {
        New-Item -Path $OffsetPath -ItemType File
    }
    $Offset = Get-Content -Path $OffsetPath
    $Uri = $TelegramApiUri + "/getUpdates"
    $ResultJson = Invoke-WebRequest -Uri $Uri -UseBasicParsing -Body @{offset = $Offset } | ConvertFrom-Json
    $Offset = $ResultJson.result[0].update_id
    if ($offset -gt 1000) {
        $Offset + 1 | Set-Content -Path $OffsetPath -Force
    }
    return $ResultJson.result[0]
}
function Get-TelegramMessages {
    param (
        [Parameter()]
        $AllowedID,
        [string]
        $TelegramApiUri
    )
    $result = Get-TelegramUpdates
    if ($result -like $null -or $result -like "") {
        return
    }
    $TelegramUserId = $result.message.from.id
    $UserMessage = $result.message.text
    #Checks for your ID
    if ($TelegramUserId -notin "$AllowedID") {
        Send-TelegramMessage -Text "Your ID is $TelegramUserId, the script does not know you." -Userid $TelegramUserId
        return
    }
    else {
        if ($UserMessage.tolower() -like "*start vm1*") {
            Start-VM -Name "vm1"
            $Message = "Starting VM1"
            Send-TelegramMessage -Text $Message -Userid $TelegramUserId
        }
        else {
            Send-TelegramMessage -Text "Unknown Command"  -Userid $TelegramUserId
        }
    }
}
while ($true) {
    Start-Sleep 1
    Get-TelegramMessages -AllowedID $AllowedID -TelegramApiUri $TelegramApiUri
}

4 thoughts on “Simple PowerShell script to send commands to your servers using Telegram

Add yours

  1. Thanks! This helped me a lot!

    I have a few things.

    First:
    Change:
    $OffsetPath = “$env:TEMPoffset.txt”
    $Offset = Get-Content -Path $OffsetPath

    if (!(Test-Path $OffsetPath)) {
    New-Item -Path $OffsetPath -ItemType File
    }

    To:
    $OffsetPath = “$env:TEMPoffset.txt”

    if (!(Test-Path $OffsetPath)) {
    New-Item -Path $OffsetPath -ItemType File
    }

    $Offset = Get-Content -Path $OffsetPath

    Otherwise you will get an error if the offset file does not exist yet.

    Do you have an idea how I can allow multiple id’s? I can’t get it done.

    1. Hi Morph,
      thank you for your comment 🙂
      I’ve corrected the error you pointed out.

      Did you try $AllowedID = “ID1”, “ID2”?
      This should work, but i currently can not test this.

      Greetings
      Xiakit

    2. Hi MorpH,
      I fixed it, I really don’t know what I was thinking when writing this script 😀
      The $AllowedID was fixed to a String, that’s why it could not check for multiple values.
      Cheers
      Xiakit

Leave a Reply

Powered by WordPress.com.

Up ↑

%d bloggers like this: