@ -5,13 +5,19 @@ param (
[ Parameter ( Mandatory = $true ) ]
[ Parameter ( Mandatory = $true ) ]
[ string ]
[ string ]
$User ,
$User Id ,
[ Parameter ( Mandatory = $true ) ]
[ Parameter ( Mandatory = $true ) ]
[ securestring ]
[ securestring ]
$AccessToken
$AccessToken
)
)
$account_data_type_prefix = 'de.lubiland.pingposh.'
$account_data_types = @ {
next_batch = $account_data_type_prefix + 'next_batch'
}
function Send-MatrixEvent {
function Send-MatrixEvent {
param (
param (
[ Parameter ( Mandatory = $true ) ]
[ Parameter ( Mandatory = $true ) ]
@ -174,7 +180,7 @@ function Join-Pong {
FormattedBody = $formatted_body
FormattedBody = $formatted_body
}
}
}
}
function Open- Matrix Event {
function Open- Event {
param (
param (
[ Parameter ( Mandatory = $true ) ]
[ Parameter ( Mandatory = $true ) ]
$Event ,
$Event ,
@ -195,11 +201,75 @@ function Open-MatrixEvent {
Send-Pong -RoomId $RoomId @bodies -OriginHomeServer $origin_homeserver -Duration $difference . TotalMilliseconds -PingEventId $Event . event_id
Send-Pong -RoomId $RoomId @bodies -OriginHomeServer $origin_homeserver -Duration $difference . TotalMilliseconds -PingEventId $Event . event_id
}
}
}
}
function Start-MatrixSync {
function Get-MatrixAccountData {
param (
[ Parameter ( Mandatory = $true ) ]
[ string ]
$Type
)
$uri = '{0}/_matrix/client/r0/user/{1}/account_data/{2}' -f $HomeServer , $UserId , $Type
$header_splat = @ {
Authentication = 'Bearer'
Token = $AccessToken
ContentType = 'application/json'
}
$http_splat = @ {
Uri = $uri
Method = 'Get'
}
$response = Invoke-RestMethod @header_splat @http_splat
return $response
}
function Set-MatrixAccountData {
param (
[ Parameter ( Mandatory = $true ) ]
[ string ]
$Type ,
[ Parameter ( Mandatory = $true ) ]
[ System.Object ]
$Content
)
$uri = '{0}/_matrix/client/r0/user/{1}/account_data/{2}' -f $HomeServer , $UserId , $Type
$header_splat = @ {
Authentication = 'Bearer'
Token = $AccessToken
ContentType = 'application/json'
}
$http_splat = @ {
Uri = $uri
Method = 'Put'
Body = $Content | ConvertTo-Json -Compress
}
Invoke-RestMethod @header_splat @http_splat | Out-Null
}
function Get-NextBatchToken {
$account_data = Get-MatrixAccountData -Type $account_data_types . next_batch
return $account_data . next_batch
}
function Set-NextBatchToken {
param (
[ Parameter ( Mandatory = $true ) ]
[ string ]
$Token
)
Set-MatrixAccountData -Type $account_data_types . next_batch -Content @ { next_batch = $Token }
}
function Invoke-MatrixSync {
param (
param (
[ string ]
[ string ]
$Token ,
$Token ,
[ string ]
$FilterId ,
[ int ]
[ int ]
$Timeout = 30000
$Timeout = 30000
)
)
@ -208,6 +278,9 @@ function Start-MatrixSync {
if ( $Token ) {
if ( $Token ) {
$uri + = '&since={0}' -f $Token
$uri + = '&since={0}' -f $Token
}
}
if ( $FilterId ) {
$uri + = '&filter={0}' -f $FilterId
}
$header_splat = @ {
$header_splat = @ {
Authentication = 'Bearer'
Authentication = 'Bearer'
@ -225,17 +298,105 @@ function Start-MatrixSync {
foreach ( $room_id in $room_ids ) {
foreach ( $room_id in $room_ids ) {
$events = $response . rooms . join . $room_id . timeline . events
$events = $response . rooms . join . $room_id . timeline . events
foreach ( $event in $events ) {
foreach ( $event in $events ) {
Open- Matrix Event -Event $event -RoomId $room_id
Open- Event -Event $event -RoomId $room_id
}
}
}
}
Write-Output $response . next_batch
return $response . next_batch
}
function Get-MatrixFilterId {
param (
[ System.Object ]
$Filter
)
$uri = '{0}/_matrix/client/r0/user/{1}/filter' -f $HomeServer , $UserId
$header_splat = @ {
Authentication = 'Bearer'
Token = $AccessToken
ContentType = 'application/json'
}
$http_splat = @ {
Uri = $uri
Method = 'Post'
#a filter can be up to 3 layers deep according to spec
#https://matrix.org/docs/spec/client_server/r0.6.0#filtering
Body = $Filter | ConvertTo-Json -Compress -Depth 3
}
}
$response = Invoke-RestMethod @header_splat @http_splat
return $response . filter_id
}
function Get-FilterId {
$filter = @ {
event_fields = @ (
#all fields used in Open-Event
'event_id'
'sender'
'origin_server_ts'
'content.msgtype'
'content.body'
)
presence = @ {
#we don't use presence information
types = @ ( 'invalid' )
}
account_data = @ {
#we only retrieve account_data via the account_data api endpoint
types = @ ( 'invalid' )
}
room = @ {
ephemeral = @ {
#we don't use ephemeral events like typing or read receipts
types = @ ( 'invalid' )
}
state = @ {
#we don't use room state
types = @ ( 'invalid' )
}
timeline = @ {
#exclude ourself
not_senders = @ (
$UserId
)
types = @ (
#to receive !ping commands
'm.room.message'
)
}
account_data = @ {
#we don't use room specific account_data
types = @ ( 'invalid' )
}
}
}
$filter_id = Get-MatrixFilterId -Filter $filter
return $filter_id
}
function Start-MatrixSync {
#get last used next_batch from account_data
$token = Get-NextBatchToken
#get /sync filter
$filter_id = Get-FilterId
Try {
#try first sync with the old token
$token = Invoke-MatrixSync -Token $token -FilterId $filter_id
} Catch {
#if it fails start a fresh sync reset $token
$token = $null
}
#start sync loop
while ( $true ) {
while ( $true ) {
#use the token of the last sync
#use $token of the previous sync
#initial token is $null
Set-NextBatchToken -Token $token
$token = Start-MatrixSync -Token $token
$token = Invoke-MatrixSync -Token $token -FilterId $filter_id
}
}
}
Start-MatrixSync