You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
5.7 KiB
PowerShell
224 lines
5.7 KiB
PowerShell
param (
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$HomeServer,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$User,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[securestring]
|
|
$AccessToken
|
|
)
|
|
|
|
function Send-MatrixEvent {
|
|
param (
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$RoomId,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Event,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$EventType
|
|
)
|
|
|
|
#txn_id should be unique per client, so we use timestamp+random
|
|
$txn_id = '{0}{1}' -f (Get-Date -UFormat '%s'),(Get-Random)
|
|
|
|
$uri = '{0}/_matrix/client/r0/rooms/{1}/send/{2}/{3}' -f $HomeServer,$RoomId,$EventType,$txn_id
|
|
|
|
$header_splat = @{
|
|
Authentication = 'Bearer'
|
|
Token = $AccessToken
|
|
ContentType = 'application/json'
|
|
}
|
|
$http_splat = @{
|
|
Uri = $uri
|
|
Method = 'Put'
|
|
Body = $Event
|
|
}
|
|
|
|
$response = Invoke-RestMethod @header_splat @http_splat
|
|
if($response.event_id) {
|
|
Write-Host ('Event {0} sent to room {1}' -f $response.event_id,$RoomId)
|
|
}
|
|
}
|
|
function Send-MatrixNotice {
|
|
param (
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$RoomId,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Body,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string]
|
|
$FormattedBody
|
|
)
|
|
|
|
$event = @{
|
|
msgtype = 'm.notice'
|
|
body = $Body
|
|
}
|
|
|
|
if($FormattedBody) {
|
|
$event += @{
|
|
format = 'org.matrix.custom.html'
|
|
formatted_body = $FormattedBody
|
|
}
|
|
}
|
|
|
|
$event_json = $event | ConvertTo-Json -Compress
|
|
|
|
Send-MatrixEvent -RoomId $RoomId -Event $event_json -EventType 'm.room.message'
|
|
}
|
|
function Compare-Timestamps {
|
|
param (
|
|
[Parameter(Mandatory=$true)]
|
|
[Int64]
|
|
$OriginServerTs
|
|
)
|
|
|
|
$current_time = (Get-Date).ToUniversalTime()
|
|
|
|
#$OriginServerTs is milliseconds since 1970-01-01 (epoch time in milliseconds)
|
|
$original_time = Get-Date -Date ((Get-Date -Date '1970-01-01') + [timespan]::FromMilliseconds($OriginServerTs))
|
|
|
|
#return the difference
|
|
Write-Output ($current_time - $original_time)
|
|
}
|
|
function ConvertTo-HumanReadableTimespan {
|
|
param (
|
|
[parameter(Mandatory=$true)]
|
|
[timespan]
|
|
$TimeSpan
|
|
)
|
|
|
|
switch($TimeSpan) {
|
|
Default {
|
|
$output = '{0} days' -f [System.Math]::Round($TimeSpan.TotalDays, 2)
|
|
}
|
|
{$PSItem.TotalHours -lt 24} {
|
|
$output = '{0} h' -f [System.Math]::Round($TimeSpan.TotalHours, 2)
|
|
}
|
|
{$PSItem.TotalMinutes -lt 120} {
|
|
$output = '{0} min' -f [System.Math]::Round($TimeSpan.TotalMinutes, 2)
|
|
}
|
|
{$PSItem.TotalSeconds -lt 120} {
|
|
$output = '{0} s' -f [System.Math]::Round($TimeSpan.TotalSeconds, 2)
|
|
}
|
|
{$PSItem.TotalMilliseconds -lt 10000} {
|
|
$output = '{0} ms' -f [System.Math]::Round($TimeSpan.TotalMilliseconds, 0)
|
|
}
|
|
}
|
|
|
|
Write-Output $output
|
|
}
|
|
function Join-Pong {
|
|
param (
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$RoomId,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$PingEventId,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$SenderMxId,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$ReadableTimespan,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string]
|
|
$Ball
|
|
)
|
|
|
|
if($Ball) {
|
|
$padded_ball = $Ball+' '
|
|
}
|
|
|
|
$body = '{0}: Pong! (ping {1}took {2} to arrive)' -f $SenderMxId,$padded_ball,$ReadableTimespan
|
|
$formatted_body = '<a href=''https://matrix.to/#/{0}''>{0}</a>: Pong! ' -f $SenderMxId
|
|
$formatted_body += '(<a href="https://matrix.to/#/{0}/{1}">ping</a> {2}took {3} to arrive)' -f $RoomId,$PingEventId,$padded_ball,$ReadableTimespan
|
|
|
|
return @{
|
|
Body = $body
|
|
FormattedBody = $formatted_body
|
|
}
|
|
}
|
|
function Open-MatrixEvent {
|
|
param (
|
|
[Parameter(Mandatory=$true)]
|
|
$Event,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
$RoomId
|
|
)
|
|
|
|
#the "ball" is a string returned by the bot
|
|
if($Event.content.msgtype -eq 'm.text' -and $Event.content.body -match '!ping( (?<ball>.*))?') {
|
|
$difference = Compare-Timestamps -OriginServerTs $Event.origin_server_ts
|
|
$readable_timespan = ConvertTo-HumanReadableTimespan -TimeSpan $difference
|
|
|
|
#$bodies contains a hashtable with keys Body and FormattedBody
|
|
$bodies = Join-Pong -RoomId $RoomId -PingEventId $Event.event_id -SenderMxId $Event.sender -ReadableTimespan $readable_timespan -Ball $Matches.ball
|
|
|
|
Send-MatrixNotice -RoomId $RoomId @bodies
|
|
}
|
|
}
|
|
function Start-MatrixSync {
|
|
param (
|
|
[string]
|
|
$Token,
|
|
|
|
[int]
|
|
$Timeout = 30000
|
|
)
|
|
|
|
$uri = '{0}/_matrix/client/r0/sync?timeout={1}' -f $HomeServer,$Timeout
|
|
if($Token) {
|
|
$uri += '&since={0}' -f $Token
|
|
}
|
|
|
|
$header_splat = @{
|
|
Authentication = 'Bearer'
|
|
Token = $AccessToken
|
|
ContentType = 'application/json'
|
|
}
|
|
$http_splat = @{
|
|
Uri = $uri
|
|
}
|
|
|
|
$response = Invoke-RestMethod @header_splat @http_splat
|
|
|
|
#.PSObject.Properties because the rooms under .join are [NoteProperty]
|
|
$room_ids = $response.rooms.join.PSObject.Properties.Name
|
|
foreach($room_id in $room_ids) {
|
|
$events = $response.rooms.join.$room_id.timeline.events
|
|
foreach($event in $events) {
|
|
Open-MatrixEvent -Event $event -RoomId $room_id
|
|
}
|
|
}
|
|
|
|
Write-Output $response.next_batch
|
|
}
|
|
|
|
#Send-MatrixNotice -RoomId '!amKUIaaKdERatZsJgB:matrix.org' -Message ('asef :) {0}' -f (Get-Date))
|
|
|
|
#start sync loop
|
|
while($true) {
|
|
#use the token of the last sync
|
|
#initial token is $null
|
|
$token = Start-MatrixSync -Token $token
|
|
} |