/usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm
sudo chmod a+x /usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm
Edit -> Preferences -> Upload -> Cloudup
/usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm
sudo chmod a+x /usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm
Edit -> Preferences -> Upload -> Cloudup
| #! /usr/bin/env perl | |
| ################################################### | |
| # | |
| # Copyright (C) 2016 Long Nguyen <[email protected]> | |
| # | |
| # This file is part of Shutter. | |
| # | |
| # Shutter is free software; you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation; either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # Shutter is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with Shutter; if not, write to the Free Software | |
| # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| # | |
| ################################################### | |
| package Cloudup; #edit | |
| my $api = 'https://api.cloudup.com/1'; | |
| use lib $ENV{'SHUTTER_ROOT'}.'/share/shutter/resources/modules'; | |
| use utf8; | |
| use strict; | |
| use POSIX qw/setlocale/; | |
| use Locale::gettext; | |
| use Glib qw/TRUE FALSE/; | |
| use Data::Dumper; | |
| use Shutter::Upload::Shared; | |
| our @ISA = qw(Shutter::Upload::Shared); | |
| my $d = Locale::gettext->domain("shutter-plugins"); | |
| $d->dir( $ENV{'SHUTTER_INTL'} ); | |
| my %upload_plugin_info = ( | |
| 'module' => "Cloudup", #edit (must be the same as 'package') | |
| 'url' => "https://cloudup.com/", #edit (the website's url) | |
| 'registration' => "https://provider.com/signup", #edit (a link to the registration page) | |
| 'name' => "Cloudup", #edit (the provider's name) | |
| 'description' => "Upload screenshots to Cloudup",#edit (a description of the service) | |
| 'supports_anonymous_upload' => FALSE, #TRUE if you can upload *without* username/password | |
| 'supports_authorized_upload' => TRUE, #TRUE if username/password are supported (might be in addition to anonymous_upload) | |
| 'supports_oauth_upload' => FALSE, #TRUE if OAuth is used (see Dropbox.pm as an example) | |
| ); | |
| binmode( STDOUT, ":utf8" ); | |
| if ( exists $upload_plugin_info{$ARGV[ 0 ]} ) { | |
| print $upload_plugin_info{$ARGV[ 0 ]}; | |
| exit; | |
| } | |
| #don't touch this | |
| sub new { | |
| my $class = shift; | |
| #call constructor of super class (host, debug_cparam, shutter_root, gettext_object, main_gtk_window, ua) | |
| my $self = $class->SUPER::new( shift, shift, shift, shift, shift, shift ); | |
| bless $self, $class; | |
| return $self; | |
| } | |
| #load some custom modules here (or do other custom stuff) | |
| sub init { | |
| my $self = shift; | |
| use JSON; #example1 | |
| use LWP::UserAgent; #example2 | |
| use HTTP::Request::Common; #example3 | |
| use LWP::Simple; | |
| use File::Basename; | |
| use JSON; | |
| use Data::Dumper; | |
| return TRUE; | |
| } | |
| sub getReq { | |
| my ( $uri, $username, $password, $method, $content ) = @_; | |
| $method = 'GET' unless defined $method; | |
| $content = '' unless defined $content; | |
| my $req = HTTP::Request->new($method => $uri); | |
| if ($content ne '') { | |
| if ($method eq 'POST') { | |
| $req->content_type('application/x-www-form-urlencoded'); | |
| $req->content($content); | |
| } | |
| if ($method eq 'PATCH') { | |
| $req->content_type('application/json'); | |
| $req->content(to_json($content)); | |
| } | |
| } | |
| if ($username ne '' && $password ne '') { | |
| $req->authorization_basic($username, $password); | |
| } | |
| return $req; | |
| } | |
| #handle | |
| sub upload { | |
| my ( $self, $upload_filename, $username, $password ) = @_; | |
| my $api = 'https://api.cloudup.com/1'; | |
| my $json = JSON->new->allow_nonref; | |
| #store as object vars | |
| $self->{_filename} = $upload_filename; | |
| $self->{_basename} = basename($upload_filename); | |
| $self->{_username} = $username; | |
| $self->{_password} = $password; | |
| utf8::encode $upload_filename; | |
| utf8::encode $password; | |
| utf8::encode $username; | |
| #examples related to the sub 'init' | |
| my $json_coder = JSON::XS->new; | |
| my $browser = LWP::UserAgent->new( | |
| 'timeout' => 20, | |
| 'keep_alive' => 10, | |
| 'env_proxy' => 1, | |
| ); | |
| my $res_user = @_; | |
| my $req_user = @_; | |
| #username/password are provided | |
| if ( $username ne "" && $password ne "" ) { | |
| eval{ | |
| ######################## | |
| #put the login code here | |
| ######################## | |
| #if login failed (status code == 999) => Shutter will display an appropriate message | |
| #unless($login == 'success'){ | |
| # $self->{_links}{'status'} = 999; | |
| # return; | |
| #} | |
| $req_user = getReq($api . '/user', $username, $password); | |
| $res_user = $browser->request($req_user); | |
| unless($res_user->is_success){ | |
| $self->{_links}{'status'} = 999; | |
| return; | |
| } | |
| }; | |
| if($@){ | |
| $self->{_links}{'status'} = $@; | |
| return %{ $self->{_links} }; | |
| } | |
| if($self->{_links}{'status'} == 999){ | |
| return %{ $self->{_links} }; | |
| } | |
| } | |
| #upload the file | |
| eval{ | |
| ######################### | |
| #put the upload code here | |
| ######################### | |
| # Get stream | |
| my $req_stream = getReq($api . '/streams', $username, $password); | |
| my $res_stream = $browser->request($req_stream); | |
| my $streams = from_json($res_stream->decoded_content(), {utf8 => 1}); | |
| my $stream_id = ''; | |
| foreach my $stream (@{ $streams }) { | |
| if ($stream->{title} eq 'Screen Shot') { | |
| $stream_id = $stream->{id}; | |
| } | |
| } | |
| # Create stream | |
| if ($stream_id eq '') { | |
| my $req_new_stream = getReq($api . '/streams', $username, $password, 'POST', 'title=Screen Shot'); | |
| my $res_new_stream = $browser->request($req_new_stream); | |
| my $stream = from_json($res_new_stream->decoded_content()); | |
| $stream_id = $stream->{id}; | |
| print "New stream: " . Dumper($stream_id); | |
| } | |
| # Create item | |
| my $req = getReq($api . '/items', $username, $password, 'POST', 'filename='.$self->{_basename}.'&stream_id='.$stream_id); | |
| my $res = $browser->request($req); | |
| my $json = $res->decoded_content(); | |
| my $item = from_json($json, {utf8 => 1}); | |
| #save all retrieved links to a hash, as an example: | |
| $self->{_links}->{'direct_link'} = $item->{direct_url}; | |
| $self->{_links}->{'short_link'} = $item->{url}; | |
| # Upload to S3 | |
| # $item->{s3_url} | |
| my $s3_res = $browser->request(POST $item->{s3_url}, | |
| Content_Type => 'form-data', | |
| Content => [ | |
| 'key' => $item->{s3_key}, | |
| 'AWSAccessKeyId' => $item->{s3_access_key}, | |
| 'acl' => 'public-read', | |
| 'policy' => $item->{s3_policy}, | |
| 'signature' => $item->{s3_signature}, | |
| 'Content-Type' => $item->{mime}, | |
| 'Content-Length' => -s $self->{_filename}, | |
| 'file' => [$self->{_filename}] | |
| ]); | |
| unless ($s3_res->is_success) { | |
| die 'Upload file to S3 failed'; | |
| } | |
| # Signal completion | |
| my $item_uri = $api . '/items/' . $item->{id}; | |
| #my $item_uri = 'http://httpbin.org/patch'; | |
| my $sig_res = $browser->request(getReq($item_uri, $username, $password, 'PATCH', {complete => JSON::true})); | |
| #set success code (200) | |
| $self->{_links}{'status'} = 200; | |
| }; | |
| if($@){ | |
| $self->{_links}{'status'} = $@; | |
| } | |
| #and return links | |
| return %{ $self->{_links} }; | |
| } | |
| #you are free to implement some custom subs here, but please make sure they don't interfere with Shutter's subs | |
| #hence, please follow this naming convention: _<provider>_sub (e.g. _imageshack_convert_x_to_y) | |
| 1; |