/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 <olragon@gmail.com> | |
# | |
# 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; |