Skip to content

Instantly share code, notes, and snippets.

@Molochnikov
Last active January 20, 2022 21:44
Show Gist options
  • Select an option

  • Save Molochnikov/abf7ca4fb724ea04ff411a87b4e4902b to your computer and use it in GitHub Desktop.

Select an option

Save Molochnikov/abf7ca4fb724ea04ff411a87b4e4902b to your computer and use it in GitHub Desktop.
Can send messages and files
[System.Net.ServicePointManager]::SecurityProtocol = `
[System.Net.SecurityProtocolType]::Tls12
function Invoke-MultipartFormDataUpload
{
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$InFile,
[string]$ContentType,
[Uri][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Uri,
[System.Management.Automation.PSCredential]$Credential,
$ChatId
)
BEGIN
{
if (-not (Test-Path $InFile))
{
$errorMessage = ("File {0} missing or unable to read." -f $InFile)
$exception = New-Object System.Exception $errorMessage
$errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, 'MultipartFormDataUpload', ([System.Management.Automation.ErrorCategory]::InvalidArgument), $InFile
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
if (-not $ContentType)
{
Add-Type -AssemblyName System.Web
$mimeType = [System.Web.MimeMapping]::GetMimeMapping($InFile)
if ($mimeType)
{
$ContentType = $mimeType
}
else
{
$ContentType = "application/octet-stream"
}
}
}
PROCESS
{
Add-Type -AssemblyName System.Net.Http
$httpClientHandler = New-Object System.Net.Http.HttpClientHandler
if ($Credential)
{
$networkCredential = New-Object System.Net.NetworkCredential @($Credential.UserName, $Credential.Password)
$httpClientHandler.Credentials = $networkCredential
$httpClientHandler.PreAuthenticate = $true
$httpClient = New-Object System.Net.Http.Httpclient $httpClientHandler
#$password = Get-PlainText -SecureString $Credential.Password
$Base64Auth = [System.Convert]::ToBase64String([System.Text.Encoding]::GetEncoding("iso-8859-1").GetBytes([String]::Format( "{0}:{1}", $Credential.UserName, $Credential.GetNetworkCredential().Password)))
#$Base64Auth = [Convert]::ToBase64String([Text.Encoding]::GetEncoding("iso-8859-1").Getbytes("$($Credential.UserName):$($password)"))
$httpClient.DefaultRequestHeaders.Add("Authorization", "Basic $Base64Auth")
}
else {
$httpClient = New-Object System.Net.Http.Httpclient $httpClientHandler
}
$httpClient.Timeout = 18000000000
#$httpClient.DefaultRequestHeaders.Add("AUTHORIZATION", "Basic YTph")
$packageFileStream = New-Object System.IO.FileStream @($InFile, [System.IO.FileMode]::Open)
$contentDispositionHeaderValue = New-Object System.Net.Http.Headers.ContentDispositionHeaderValue "form-data"
$contentDispositionHeaderValue.Name = "document"
$contentDispositionHeaderValue.FileName = (Split-Path $InFile -leaf)
$streamContent = New-Object System.Net.Http.StreamContent $packageFileStream
$streamContent.Headers.ContentDisposition = $contentDispositionHeaderValue
$streamContent.Headers.ContentType = New-Object System.Net.Http.Headers.MediaTypeHeaderValue $ContentType
$content = New-Object System.Net.Http.MultipartFormDataContent
$content.Add($streamContent)
$disposition = new-object System.Net.Http.Headers.ContentDispositionHeaderValue -arg "form-data"
$disposition.name = 'chat_id'
$con = new-object System.Net.Http.stringcontent $ChatId
$con.headers.contentdisposition = $disposition
$content.Add($con)
try
{
$response = $httpClient.PostAsync($Uri, $content).Result
if (!$response.IsSuccessStatusCode)
{
$responseBody = $response.Content.ReadAsStringAsync().Result
$errorMessage = "Status code {0}. Reason {1}. Server reported the following message: {2}." -f $response.StatusCode, $response.ReasonPhrase, $responseBody
throw [System.Net.Http.HttpRequestException] $errorMessage
}
#return $response.Content.ReadAsStringAsync().Result
return $response
}
catch [Exception]
{
$PSCmdlet.ThrowTerminatingError($_)
return $response
}
finally
{
if($null -ne $httpClient)
{
$httpClient.Dispose()
}
if($null -ne $response)
{
$response.Dispose()
}
}
}
END { }
}
$bottoken = 'your token'
$chatspath = 'C:\Users\Lev\SkyDrive\Projects\PowerShell\windowsrtbot\chat_ids.txt'
$last_update_id = 0
$openchat = {
$null = [reflection.assembly]::loadwithpartialname("system.windows.forms")
$form = new-object system.windows.forms.form
$form.showicon = $false
$form.size = new-object drawing.size -arg 600, 500
$form.text = $chat_id
$form.startposition = 'centerscreen'
$listbox = new-object windows.forms.listbox
$listbox.dock = 'fill'
$listbox.selectionmode = 'multiextended'
$keydown = {
if ($_.keycode.tostring() -eq 'C') {
$sb = new-object system.text.stringbuilder
foreach ($item in $listbox.selecteditems) {
$sb.appendline($item.tostring())
}
if ($sb.length -gt 0) {
[system.windows.forms.clipboard]::settext($sb.tostring())
}
}
}.getnewclosure()
$listbox.add_keydown($keydown)
$form.controls.add($listbox)
$timer = new-object system.windows.forms.timer
$timer.interval = 1000
$global:last_message_id = 0
$ontick = {
$x[$chat_id] |
sort-object -property message_id |
where-object {$_.message_id -gt $global:last_message_id} |
foreach-object {
$date = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.date))
$datestring = $date.tostring('dd.MM.yyyy HH:mm:ss')
$name = $_.from.first_name
$surname = $_.from.last_name
$message = $_.text
$item = $datestring,$name,$surname,":",$message -join ' '
$listbox.items.add($item)
$listbox.topindex = $listbox.items.count - 1
}
$global:last_message_id = $x[$chat_id] |
measure-object -property message_id -maximum |
select-object -expandproperty maximum
[system.windows.forms.application]::doevents()
}.getnewclosure()
$timer.add_tick($ontick)
$form.add_load({
start-sleep -seconds 1
$timer.start()
})
$form.add_closing({
$timer.stop()
})
$textbox = new-object windows.forms.textbox
$textbox.dock = 'bottom'
$keyup = {
if (($_.keycode.tostring() -eq 'Return') -and ($textbox.text)) {
$send = @{chat_id=$chat_id;message=$textbox.text}
$x.host.runspace.events.generateevent("message",$x.test,$send, "test event")
$date = get-date
$datestring = $date.tostring('dd.MM.yyyy HH:mm:ss')
$name = 'LevWindowsRT'
$message = $textbox.text
$item = $datestring,$name,":",$message -join ' '
$listbox.items.add($item)
$listbox.topindex = listbox.items.count - 1
$textbox.clear()
}
}.getnewclosure()
$textbox.add_keydown($keyup)
$form.controls.add($textbox)
$button = new-object windows.forms.button
$button.size = new-object drawing.size -arg $textbox.clientsize.height,$textbox.clientsize.height
$button.dock = "right"
$button.image = $form.icon
$click = {
$filedialog = new-object system.windows.forms.openfiledialog
$filedialog.filter = "All files (*.*)|*.*"
$filedialog.filterindex = 2
$filedialog.restoredirectory = $true
if ($filedialog.showdialog() -eq [system.windows.forms.dialogresult]::ok) {
$send = @{'chat_id'=$chat_id;'document'=($filedialog.filename.clone())}
$x.host.runspace.events.generateevent("file",$x.test,$send,"test event")
}
$filedialog.dispose()
}.getnewclosure()
$button.add_click($click)
$textbox.controls.add($button)
#$icon = $form.GetType().GetField("defaultIcon", ([System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Static)).getvalue($null)
$form.showdialog()
}
$x = [hashtable]::synchronized(@{})
$x.host = $host
$type ='application/json'
$api = 'https://api.telegram.org/bot{0}/'
while (1) {
Invoke-RestMethod -Method Post -ContentType $type -Uri (($api + 'getUpdates') -f $BotToken) -Body ([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -Compress -InputObject @{offset=($last_update_id + 1)} -Depth 50))) |
foreach-object {$_.result} |
tee-object -variable updates |
foreach-object {$_.message} |
group-object -property {$_.chat.id} |
foreach-object {
$chat_id = $_.name
if (-not ($x.containskey($chat_id))) {
if (-not (get-content -path $chatspath | where-object {$_ -eq $chat_id})) {
add-content $chatspath $chat_id
}
$x[$chat_id] = $_.group
$rs = [runspacefactory]::createrunspace()
$rs.apartmentstate,$rs.threadoptions = "sta","reusethread"
$rs.open()
$rs.sessionstateproxy.setvariable("x",$x)
$rs.sessionstateproxy.setvariable("chat_id",$chat_id)
$ps = [powershell]::create().addscript($openchat)
$ps.runspace = $rs
$async = $ps.begininvoke()
} else {
$x[$_.name] = $_.group
}
}
$last_update_id = $updates |
measure-object -property update_id -maximum |
select-object -expandproperty maximum
$messages = (get-event | where-object {$_.sourceidentifier -eq "message"})
if ($messages) {
$messages.sourceargs |
foreach-object {
$payload = @{
chat_id = $_.chat_id
text = $_.message
}
$uri = 'https://api.telegram.org/bot{0}/sendMessage' -f $BotToken
$invokeRestMethodSplat = @{
Uri = $uri
Body = ([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -Compress -InputObject $payload -Depth 50)))
ErrorAction = 'Stop'
ContentType = 'application/json'
Method = 'Post'
}
$results = Invoke-RestMethod @invokeRestMethodSplat
} |
select-object -property result
remove-event -sourceidentifier "message"
}
$files = (get-event | where-object {$_.sourceidentifier -eq "file"})
if ($files) {
$files.sourceargs |
foreach-object {
Invoke-MultipartFormDataUpload -InFile $_.document -Uri (($api + 'sendDocument') -f $BotToken) -ChatId $_.chat_id
} |
select-object -property result
remove-event -sourceidentifier "file"
}
start-sleep -seconds 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment