Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Cloudup upload plugin for Shutter (http://shutter-project.org/)

Copy file Cloudup.pm into /usr/share/shutter/resources/system/upload_plugins/upload/

/usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm

Add execute permission

sudo chmod a+x /usr/share/shutter/resources/system/upload_plugins/upload/Cloudup.pm

Restart Shutter

Config Cloudup username / password

Edit -> Preferences -> Upload -> Cloudup

Upload screenshot using Cloudup [your-cloudup-username], new screenshot will be added into "Screen Shot" folder

#! /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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment