diff --git a/README.md b/README.md index 8adec22..6874f13 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,13 @@ It requires the following perl modules * HTTP::Request * Config::Simple * File::HomeDir + * File::Basename + * File::MimeInfo + * Path::Tiny * Getopt::Long * JSON -For now it's very limited, and can only send messages to a room. Here're the vailable options: +For now it's very limited, and can only send text messages and files to a room. Here're the vailable options: * --user: specify the user you want to login as * --password: the password to auth against the HS @@ -19,8 +22,10 @@ For now it's very limited, and can only send messages to a room. Here're the vai * --debug: if present, will be verbose * --notice: send a notice instead of a message (more or less the same but the client can display it differently. Riot for example will not notify you for notices) * --conf: path to a conf file. Default conf file is ~/.patrixrc + * --file: if action is send-file, specify the path of the file to send * --action: what to do. Valid actions are * send-msg (default): send the text message + * send-file: send a binary file. --file must be set * get-access-token: just login and print the access token * get-room-list: prints the list of public rooms of this server diff --git a/scripts/patrix b/scripts/patrix index 8316e28..c032a33 100644 --- a/scripts/patrix +++ b/scripts/patrix @@ -8,6 +8,9 @@ use JSON qw(from_json to_json); use Getopt::Long; use Config::Simple; use File::HomeDir; +use File::MimeInfo; +use File::Basename; +use Path::Tiny; our $opt; @@ -19,6 +22,7 @@ GetOptions( "room=s" => \$opt->{room}, "message=s" => \$opt->{message}, "notice" => \$opt->{notice}, + "files=s" => \$opt->{file}, "debug" => \$opt->{debug}, "action=s" => \$opt->{action}, "conf=s" => \$opt->{conf} @@ -62,6 +66,9 @@ elsif (!$opt->{access_token} && (!$opt->{user} || !$opt->{password})){ if ($opt->{action} eq 'send-msg' && (!$opt->{room} || !$opt->{message})){ die "You need to provide a room ID and a message"; } +if ($opt->{action} eq 'send-file' && (!$opt->{room} || !$opt->{file})){ + die "You need to provide a room ID and a file to send\n"; +} $opt->{server} = 'https://' . $opt->{server} unless ($opt->{server} =~ m|https?://|); @@ -158,6 +165,51 @@ sub send_msg(){ my $resp = $lwp->request( $req ); } +sub send_file(){ + if ($opt->{debug}){ + print "Uploading file $opt->{file} to the media store\n\n"; + } + my $uri = $opt->{server} . '/_matrix/media/v1/upload?access_token=' . $opt->{access_token} . '&filename=' . basename($opt->{file}); + my $req = HTTP::Request->new( 'POST', $uri ); + $req->header( 'Content-Type' => mimetype $opt->{file} ); + $req->content( path( $opt->{file} )->slurp_raw ); + my $resp = $lwp->request( $req ); + if ($opt->{debug}){ + print "File upload response is\n" . + to_json(from_json($resp->decoded_content), { pretty => 1 }) . + "\n\n"; + } + unless ( $resp->is_success ){ + die "Error uploading file\n"; + } + my $file_uri = from_json($resp->decoded_content)->{content_uri}; + unless ($file_uri){ + die "Error occurred during file upload\n"; + } + if ($opt->{debug}){ + print "File uploaded, with the URI $file_uri\n"; + print "Now Sending the file link to the room $opt->{room}\n\n"; + } + $uri = $opt->{server} . '/_matrix/client/r0/rooms/' . $opt->{room} . '/send/m.room.message?access_token=' . $opt->{access_token}; + $req = HTTP::Request->new( 'POST', $uri ); + my $json = { + msgtype => 'm.file', + body => basename($opt->{file}), + filename => basename($opt->{file}), + info => { + mimetype => mimetype $opt->{file}, + size => (stat $opt->{file})[7] + }, + url => $file_uri + }; + $req->header( 'Content-Type' => 'application/json' ); + $req->content( to_json($json) ); + $resp = $lwp->request( $req ); + unless ( $resp->is_success ){ + die "Error posting file link on room $opt->{room}\n"; + } +} + sub list_room(){ my $uri = $opt->{server} . '/_matrix/client/r0/publicRooms?access_token=' . $opt->{access_token}; my $req = HTTP::Request->new( 'POST', $uri ); @@ -200,6 +252,11 @@ elsif ($opt->{action} eq 'send-msg'){ send_msg(); } } +elsif ($opt->{action} eq 'send-file'){ + login(); + join_room(); + send_file(); +} logout() if $must_logout;