2021-08-06 15:13:36 +03:00
const { MatrixEvent } = require ( 'matrix-js-sdk/lib/models/event' ) ;
2024-09-29 20:53:07 +03:00
const url = require ( "url" )
2023-08-23 10:25:48 +03:00
const isEmoji = string => true ;
2021-02-14 10:57:35 +03:00
const sendError = async ( event , roomId , e ) => {
e . response ? error = ` Error( ${ e . response . status } ): ${ e . response . data . error } `
: e . data ? error = ` Error( ${ e . errcode } ): ${ e . data . error } `
: error = ` Error: ${ e . syscall } , ${ e . code } ` ;
return matrixClient . sendHtmlNotice ( roomId ,
2022-04-26 06:09:55 +03:00
' ' , error ) ;
2021-02-14 10:57:35 +03:00
} ;
const addReact = async ( event , key ) => {
const roomId = event . event . room _id ;
return matrixClient . sendEvent ( event . event . room _id , 'm.reaction' , {
'm.relates_to' : {
rel _type : 'm.annotation' ,
event _id : event . getId ( ) ,
key ,
} ,
} ) . catch ( ( e ) => sendError ( null , roomId , e ) ) ;
} ;
const eventHandler = ( args , roomId , command , event ) => {
const userInput = args . join ( ' ' ) ;
const flaggedInput = userInput . substr ( userInput . indexOf ( ' ' ) + 1 ) ;
const address = args . slice ( 0 , 1 ) . join ( ' ' ) . replace ( /"/g , '' ) ;
args = [ ] ;
2023-08-23 10:25:48 +03:00
let visibility = null ;
2021-02-14 10:57:35 +03:00
switch ( command ) {
case 'config' :
return ;
case 'help' : case 'flood' : case 'notify' :
args . push ( roomId ) ;
break ;
2022-01-24 12:53:34 +03:00
case 'unflood' : case 'unnotify' :
args . push ( roomId , true ) ;
command = command . substring ( 2 ) ;
break ;
2023-08-23 10:25:48 +03:00
case 'unreact' :
args . push ( roomId , event , userInput , true ) ;
command = 'react' ;
break ;
2021-02-22 12:48:10 +03:00
case 'tip' : case 'makeitrain' :
args . push ( roomId , event , address , flaggedInput ) ;
2021-02-14 10:57:35 +03:00
break ;
case 'archive' : case 'rearchive' :
args . push ( roomId , userInput , ! ! ~ command . indexOf ( 're' ) ) ;
command = 'archive' ;
break ;
case 'post' : case 'reply' : case 'media' : case 'mediareply' :
case 'random' : case 'randomreply' : case 'randommedia' : case 'randommediareply' :
2023-08-23 10:25:48 +03:00
case 'direct' : case 'directreply' : case 'directmedia' : case 'directmediareply' :
case 'private' : case 'privatereply' : case 'privatemedia' : case 'privatemediareply' :
case 'unlisted' : case 'unlistedreply' : case 'unlistedmedia' : case 'unlistedmediareply' :
visibility = command . match ( /^(direct|private|unlisted)/ ) ;
2021-02-26 08:54:30 +03:00
args . push ( roomId , event , userInput , {
2021-02-14 10:57:35 +03:00
isReply : ! ! ~ command . indexOf ( 'reply' ) ,
hasMedia : ! ! ~ command . indexOf ( 'media' ) ,
hasSubject : ! ! ~ command . indexOf ( 'random' ) ,
2023-08-23 10:25:48 +03:00
visibility : visibility ? visibility [ 1 ] : null
2021-02-14 10:57:35 +03:00
} ) ;
command = 'post' ;
break ;
2023-09-04 12:56:31 +03:00
case 'crossblog' :
args . push ( roomId , event , userInput , true ) ;
command = 'nitter'
break ;
2021-02-14 10:57:35 +03:00
// fallthrough
default :
args . push ( roomId , event , userInput ) ;
}
2024-09-29 20:53:07 +03:00
if ( [ "boo" , "clap" , "copy" , "flood" , "follow" , "notify" , "pin" , "unpin" , "post" , "react" , "redact" , "status" , "unfollow" , "unreblog" , "unroll" ] . includes ( command ) && ! fediverse . auth [ event . getSender ( ) ] ) return matrixClient . sendHtmlNotice ( roomId , ' ' , ` ${ event . getSender ( ) } , для использования команды ${ command } нужно привязать аккаунт Fediverse. Используйте для этого команду +auth <имя сервера> ` )
2021-02-14 10:57:35 +03:00
registrar [ command ] && registrar [ command ] . runQuery . apply ( null , args ) ;
} ;
2021-08-06 15:13:36 +03:00
/ * *
matrixClient . fetchRoomEvent ( ) does not return an Event class
however , this class is necessary for decryption , so reinstate it .
afterwards , decrypt .
* /
const fetchEncryptedOrNot = async ( roomId , event ) => {
const fetchedEvent = await matrixClient . fetchRoomEvent ( roomId , event . event _id )
const realEvent = new MatrixEvent ( fetchedEvent ) ;
if ( realEvent . isEncrypted ( ) ) {
await matrixClient . decryptEventIfNeeded ( realEvent , { emit : false , isRetry : false } ) ;
}
return realEvent ;
}
2021-02-14 10:57:35 +03:00
module . exports . sendError = sendError ;
module . exports . addReact = addReact ;
module . exports . eventHandler = eventHandler ;
2021-08-06 15:13:36 +03:00
module . exports . fetchEncryptedOrNot = fetchEncryptedOrNot
2021-02-14 10:57:35 +03:00
module . exports . editNoticeHTML = ( roomId , event , html , plain ) => matrixClient . sendMessage ( roomId , {
body : ` * ${ plain || html . replace ( /<[^<]+?>/g , '' ) } ` ,
formatted _body : ` * ${ html } ` ,
format : 'org.matrix.custom.html' ,
msgtype : 'm.notice' ,
'm.new_content' : {
body : plain || html . replace ( /<[^<]+?>/g , '' ) ,
formatted _body : html ,
format : 'org.matrix.custom.html' ,
msgtype : 'm.notice' ,
} ,
'm.relates_to' : {
rel _type : 'm.replace' ,
event _id : event . event _id ,
} ,
} ) ;
module . exports . handleReact = async ( event ) => {
2023-08-23 10:25:48 +03:00
const reactions = config . matrix . reactions ;
2021-02-14 10:57:35 +03:00
const roomId = event . event . room _id ;
2021-08-06 15:13:36 +03:00
if ( ! event . getContent ( ) [ 'm.relates_to' ] ) return ;
2021-02-14 10:57:35 +03:00
const reaction = event . getContent ( ) [ 'm.relates_to' ] ;
2021-08-06 15:13:36 +03:00
const metaEvent = await fetchEncryptedOrNot ( roomId , reaction ) ;
2022-01-24 12:53:34 +03:00
if ( ! metaEvent . getContent ( ) . meta || metaEvent . event . sender !== config . matrix . user ) return ;
2023-08-23 10:25:48 +03:00
let args = metaEvent . getContent ( ) . meta . split ( ' ' ) ;
2021-02-14 10:57:35 +03:00
isMeta = [ 'status' , 'reblog' , 'mention' , 'redact' , 'unreblog' ] ;
if ( ! isMeta . includes ( args [ 0 ] ) ) return ;
let command = [ ] ;
args . shift ( ) . toLowerCase ( ) ;
2023-08-23 10:25:48 +03:00
switch ( reaction . key ) {
case reactions . copy : command = 'copy' ; break ;
case reactions . clap : command = 'clap' ; break ;
case reactions . redact : command = 'redact' ; break ;
case reactions . rain : command = 'makeitrain' ; break ;
case reactions . unroll : command = 'unroll' ; break ;
case reactions . expand :
command = 'expand' ;
args = [ reaction . event _id ] ;
break ;
default :
if ( isEmoji ( reaction . key ) ) {
command = 'react' ;
args . push ( reaction . key ) ;
}
break ;
2024-09-29 20:53:07 +03:00
}
2021-02-14 10:57:35 +03:00
eventHandler ( args , roomId , command , event ) ;
} ;
module . exports . handleReply = async ( event ) => {
const roomId = event . event . room _id ;
2022-04-25 09:43:48 +03:00
if ( ! event . event . content [ 'm.relates_to' ] [ 'm.in_reply_to' ] ) return ;
const reply = event . event . content [ 'm.relates_to' ] [ 'm.in_reply_to' ] ;
2021-08-06 15:13:36 +03:00
const metaEvent = await fetchEncryptedOrNot ( roomId , reply ) ;
2024-09-29 20:53:07 +03:00
if ( authEvents . includes ( metaEvent . event _id ) ) {
const domain = metaEvent . event . content . body . match ( /https?:\/\/[^\s]+/ ) ;
if ( domain && domain [ 0 ] ) {
domain [ 0 ] = url . parse ( domain [ 0 ] ) . host
let code = event . getContent ( ) . body . split ( "\n" ) ;
code = code [ code . length - 1 ] . trim ( )
auth . obtainAccessToken ( domain [ 0 ] , code , event )
authEvents = authEvents . filter ( f => f != event . event _id )
}
}
2022-01-24 12:53:34 +03:00
if ( ! metaEvent . getContent ( ) . meta || metaEvent . event . sender !== config . matrix . user ) return ;
2022-04-25 09:43:48 +03:00
const args = metaEvent . getContent ( ) . meta . split ( ' ' ) ;
args . push ( event . getContent ( ) . formatted _body . trim ( ) . split ( '</mx-reply>' ) [ 1 ] ) ;
2021-02-14 10:57:35 +03:00
isMeta = [ 'status' , 'reblog' , 'mention' , 'redact' , 'unreblog' ] ;
if ( ! isMeta . includes ( args [ 0 ] ) ) return ;
args . shift ( ) . toLowerCase ( ) ;
command = 'reply' ;
eventHandler ( args , roomId , command , event ) ;
} ;
module . exports . selfReact = async ( event ) => {
2023-08-23 10:25:48 +03:00
const reactions = config . matrix . reactions ;
2021-02-14 10:57:35 +03:00
if ( event . getType ( ) !== 'm.room.message' ) return ;
if ( event . event . unsigned . age > 10000 ) return ;
2021-08-06 15:13:36 +03:00
if ( ! event . getContent ( ) . meta ) return ;
2021-02-14 10:57:35 +03:00
const { meta } = event . getContent ( ) ;
const type = meta . split ( ' ' ) [ 0 ] ;
2023-08-23 10:25:48 +03:00
if ( type === 'redact' || type === 'unreblog' )
addReact ( event , reactions . redact ) ;
if ( type === 'status' || type === 'reblog' || type === 'mention' )
addReact ( event , reactions . expand ) ;
} ;
module . exports . expandReact = async ( event ) => {
const reactions = config . matrix . reactions ;
if ( event . getSender ( ) !== matrixClient . credentials . userId ) return ;
if ( ! event . getContent ( ) . meta ) return ;
const { meta } = event . getContent ( ) ;
const type = meta . split ( ' ' ) [ 0 ] ;
2021-02-14 10:57:35 +03:00
if ( type === 'status' || type === 'reblog' || type === 'mention' ) {
2023-08-23 10:25:48 +03:00
addReact ( event , reactions . unroll ) ;
addReact ( event , reactions . copy ) ;
addReact ( event , reactions . clap ) ;
if ( config . fediverse . tipping )
addReact ( event , reactions . rain ) ;
2021-02-14 10:57:35 +03:00
}
} ;
2021-07-23 09:02:32 +03:00
module . exports . retryPromise = async ( argList , promiseFn ) => {
let err ;
for ( var arg of argList ) {
try {
return await promiseFn ( arg ) ;
} catch ( e ) { err = e ; }
}
throw err || new Error ( 'retryPromise error' ) ;
} ;