imgurr 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +16 -0
- data/LICENSE.md +21 -0
- data/README.md +13 -0
- data/bin/imgurr +8 -0
- data/imgurr.gemspec +31 -0
- data/lib/imgurr/color.rb +53 -0
- data/lib/imgurr/command.rb +101 -0
- data/lib/imgurr/imgurAPI.rb +53 -0
- data/lib/imgurr/imgurErrors.rb +26 -0
- data/lib/imgurr/platform.rb +103 -0
- data/lib/imgurr.rb +25 -0
- data/test/run +1 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d4544fad3819e0f8c9d81e8a59e1be7435a78296
|
4
|
+
data.tar.gz: 890d54d33ea441afd7970d73ea1d937d0df4dde9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 99eb2135ac23a07d1a23333aaf0db10564a4e347c70cb54b12acf8e8f51538236a2685372ad93ed2eb0eea4317536315785ef6ab34d5753578258b4ba153131f
|
7
|
+
data.tar.gz: 1b807e4cb0ab03b55b0582376dd23c307edba8d3c919f176f3f3cf7caafdcb4beceb0bb3a7f94f73753b31ebece59c9468f3ca01311a7f49a7ae6e20047fb86c
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) Christophe Naud-Dulude, https://github.com/Chris911/
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
data/bin/imgurr
ADDED
data/imgurr.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'imgurr'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2013-04-06'
|
5
|
+
s.summary = "Imgurr lets you upload images to imgur from the command line"
|
6
|
+
s.description = "Imgurr is a ruby gem that lets you upload images to Imgur and manage your account"
|
7
|
+
s.authors = ["Christophe Naud-Dulude"]
|
8
|
+
s.email = 'christophe.naud.dulude@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/Chris911/imgurr'
|
10
|
+
|
11
|
+
s.require_paths = %w[lib]
|
12
|
+
## If your gem includes any executables, list them here.
|
13
|
+
s.executables = ["imgurr"]
|
14
|
+
s.default_executable = 'imgurr'
|
15
|
+
|
16
|
+
s.add_dependency('json', "~> 1.7.0")
|
17
|
+
|
18
|
+
s.add_development_dependency('rake', "~> 0.9.2")
|
19
|
+
|
20
|
+
## Specify any RDoc options here. You'll want to add your README and
|
21
|
+
## LICENSE files to the extra_rdoc_files list.
|
22
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
23
|
+
s.extra_rdoc_files = %w[README.md LICENSE.md]
|
24
|
+
|
25
|
+
s.license = 'MIT'
|
26
|
+
|
27
|
+
s.files = %w( README.md LICENSE.md Gemfile Gemfile.lock imgurr.gemspec )
|
28
|
+
s.files += Dir.glob("lib/**/*")
|
29
|
+
s.files += Dir.glob("bin/**/*")
|
30
|
+
s.files += Dir.glob("test/**/*")
|
31
|
+
end
|
data/lib/imgurr/color.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Imgurr
|
2
|
+
# Color collects some methods for colorizing terminal output.
|
3
|
+
# Thanks to https://github.com/holman
|
4
|
+
module Color
|
5
|
+
extend self
|
6
|
+
|
7
|
+
CODES = {
|
8
|
+
:reset => "\e[0m",
|
9
|
+
|
10
|
+
:cyan => "\e[36m",
|
11
|
+
:magenta => "\e[35m",
|
12
|
+
:red => "\e[31m",
|
13
|
+
:yellow => "\e[33m"
|
14
|
+
}
|
15
|
+
|
16
|
+
# Tries to enable Windows support if on that platform.
|
17
|
+
#
|
18
|
+
# Returns nothing.
|
19
|
+
def self.included(other)
|
20
|
+
if RUBY_PLATFORM =~ /win32/ || RUBY_PLATFORM =~ /mingw32/
|
21
|
+
require 'Win32/Console/ANSI'
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
# Oh well, we tried.
|
25
|
+
end
|
26
|
+
|
27
|
+
# Wraps the given string in ANSI color codes
|
28
|
+
#
|
29
|
+
# string - The String to wrap.
|
30
|
+
# color_code - The String representing he ANSI color code
|
31
|
+
#
|
32
|
+
# Examples
|
33
|
+
#
|
34
|
+
# colorize("Boom!", :magenta)
|
35
|
+
# # => "\e[35mBoom!\e[0m"
|
36
|
+
#
|
37
|
+
# Returns the wrapped String unless the the platform is windows and
|
38
|
+
# does not have Win32::Console, in which case, returns the String.
|
39
|
+
def colorize(string, color_code)
|
40
|
+
if !defined?(Win32::Console) && !!(RUBY_PLATFORM =~ /win32/ || RUBY_PLATFORM =~ /mingw32/)
|
41
|
+
# looks like this person doesn't have Win32::Console and is on windows
|
42
|
+
# just return the uncolorized string
|
43
|
+
return string
|
44
|
+
end
|
45
|
+
"#{CODES[color_code] || color_code}#{string}#{CODES[:reset]}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set up shortcut methods to all the codes define in CODES.
|
49
|
+
self.class_eval(CODES.keys.reject {|color| color == :reset }.map do |color|
|
50
|
+
"def #{color}(string); colorize(string, :#{color}); end"
|
51
|
+
end.join("\n"))
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# Command is the main point of entry for boom commands; shell arguments are
|
4
|
+
# passed through to Command, which then filters and parses through individual
|
5
|
+
# commands and reroutes them to constituent object classes.
|
6
|
+
#
|
7
|
+
# Highly inspired by @holman/boom
|
8
|
+
#
|
9
|
+
|
10
|
+
module Imgurr
|
11
|
+
class Command
|
12
|
+
class << self
|
13
|
+
#include Imgurup::Color
|
14
|
+
|
15
|
+
# Public: executes a command.
|
16
|
+
#
|
17
|
+
# args - The actual commands to operate on. Can be as few as zero
|
18
|
+
# arguments or as many as three.
|
19
|
+
def execute(*args)
|
20
|
+
command = args.shift
|
21
|
+
major = args.shift
|
22
|
+
minor = args.empty? ? nil : args.join(' ')
|
23
|
+
|
24
|
+
return help unless command
|
25
|
+
delegate(command, major, minor)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Public: prints any given string.
|
29
|
+
#
|
30
|
+
# s = String output
|
31
|
+
#
|
32
|
+
# Prints to STDOUT and returns. This method exists to standardize output
|
33
|
+
# and for easy mocking or overriding.
|
34
|
+
def output(s)
|
35
|
+
puts(s)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: gets $stdin.
|
39
|
+
#
|
40
|
+
# Returns the $stdin object. This method exists to help with easy mocking
|
41
|
+
# or overriding.
|
42
|
+
def stdin
|
43
|
+
$stdin
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: allows main access to most commands.
|
47
|
+
#
|
48
|
+
# Returns output based on method calls.
|
49
|
+
def delegate(command, major, minor)
|
50
|
+
return version if command == '-v'
|
51
|
+
return version if command == '--version'
|
52
|
+
return help if command == 'help'
|
53
|
+
return help if command[0] == 45 || command[0] == '-' # any - dash options are pleas for help
|
54
|
+
return echo(major,minor) if command == 'echo' || command == 'e'
|
55
|
+
return upload(major) if command == 'upload' || command == 'up' || command == 'u'
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Upload an image to Imgur
|
60
|
+
#
|
61
|
+
# Returns nothing
|
62
|
+
def upload(major)
|
63
|
+
response = ImgurAPI.upload(major)
|
64
|
+
puts response if response.start_with?('Error')
|
65
|
+
puts "Copied #{Platform.copy(response)} to clipboard" if response.start_with?('http')
|
66
|
+
end
|
67
|
+
|
68
|
+
# Public: the version of boom that you're currently running.
|
69
|
+
#
|
70
|
+
# Returns a String identifying the version number.
|
71
|
+
def version
|
72
|
+
output "You're running imgurup #{Imgurup::VERSION}."
|
73
|
+
end
|
74
|
+
|
75
|
+
# Public: launches preferences JSON file in an editor for you to edit manually.
|
76
|
+
#
|
77
|
+
# Returns nothing.
|
78
|
+
def edit
|
79
|
+
Platform.edit(account.json_file)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Public: prints all the commands of boom.
|
83
|
+
#
|
84
|
+
# Returns nothing.
|
85
|
+
def help
|
86
|
+
text = '
|
87
|
+
- imgurup: help ---------------------------------------------------
|
88
|
+
|
89
|
+
imgurup upload <image> Upload image and copy link to clipboard
|
90
|
+
|
91
|
+
|
92
|
+
all other documentation is located at:
|
93
|
+
https://github.com/Chris911/imgurup
|
94
|
+
'.gsub(/^ {8}/, '') # strip the first eight spaces of every line
|
95
|
+
|
96
|
+
output text
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# Interface for the Imgur API
|
5
|
+
#
|
6
|
+
|
7
|
+
module Imgurr
|
8
|
+
class ImgurAPI
|
9
|
+
class << self
|
10
|
+
API_URI = URI.parse('https://api.imgur.com')
|
11
|
+
API_PUBLIC_KEY = 'Client-ID 70ff50b8dfc3a53'
|
12
|
+
|
13
|
+
ENDPOINTS = {
|
14
|
+
:image => '/3/image',
|
15
|
+
:gallery => '/3/gallery'
|
16
|
+
}
|
17
|
+
|
18
|
+
# HTTP Client used for API requests
|
19
|
+
# TODO: Confirm SSL Certificate
|
20
|
+
def web_client
|
21
|
+
http = Net::HTTP.new(API_URI.host, API_URI.port)
|
22
|
+
http.use_ssl = true
|
23
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
24
|
+
http
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Upload an image
|
28
|
+
#
|
29
|
+
# args - The image path for the image to upload
|
30
|
+
#
|
31
|
+
def upload(image_path)
|
32
|
+
params = {:image => File.read(image_path)}
|
33
|
+
request = Net::HTTP::Post.new(API_URI.request_uri + ENDPOINTS[:image])
|
34
|
+
request.set_form_data(params)
|
35
|
+
request.add_field('Authorization', API_PUBLIC_KEY)
|
36
|
+
|
37
|
+
response = web_client.request(request)
|
38
|
+
handle_response(response.body)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Handle API Response
|
42
|
+
#
|
43
|
+
# args - Response data
|
44
|
+
#
|
45
|
+
def handle_response(response)
|
46
|
+
data = JSON.parse(response)
|
47
|
+
#puts JSON.pretty_unparse(data)
|
48
|
+
data['data']['link'] if(data['success'])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# Interface for the Imgur API
|
5
|
+
#
|
6
|
+
|
7
|
+
module Imgurr
|
8
|
+
class ImgurErrors
|
9
|
+
class << self
|
10
|
+
|
11
|
+
ERROR_CODES = {
|
12
|
+
400 => 'Missing Parameters',
|
13
|
+
401 => 'Auth Required',
|
14
|
+
403 => 'Forbidden',
|
15
|
+
404 => 'Resource does not exist',
|
16
|
+
429 => 'Rate Limiting',
|
17
|
+
500 => 'Internal Error'
|
18
|
+
}
|
19
|
+
|
20
|
+
def handle_error(response)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# Platform is a centralized point to shell out platform specific functionality
|
4
|
+
# like clipboard access or commands to open URLs.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# Clipboard is a centralized point to shell out to each individual platform's
|
8
|
+
# clipboard, pasteboard, or whatever they decide to call it.
|
9
|
+
#
|
10
|
+
# Source: https://github.com/holman/boom
|
11
|
+
#
|
12
|
+
module Imgurr
|
13
|
+
class Platform
|
14
|
+
class << self
|
15
|
+
# Public: tests if currently running on darwin.
|
16
|
+
#
|
17
|
+
# Returns true if running on darwin (MacOS X), else false
|
18
|
+
def darwin?
|
19
|
+
!!(RUBY_PLATFORM =~ /darwin/)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: tests if currently running on windows.
|
23
|
+
#
|
24
|
+
# Apparently Windows RUBY_PLATFORM can be 'win32' or 'mingw32'
|
25
|
+
#
|
26
|
+
# Returns true if running on windows (win32/mingw32), else false
|
27
|
+
def windows?
|
28
|
+
!!(RUBY_PLATFORM =~ /mswin|mingw/)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: returns the command used to open a file or URL
|
32
|
+
# for the current platform.
|
33
|
+
#
|
34
|
+
# Currently only supports MacOS X and Linux with `xdg-open`.
|
35
|
+
#
|
36
|
+
# Returns a String with the bin
|
37
|
+
def open_command
|
38
|
+
if darwin?
|
39
|
+
'open'
|
40
|
+
elsif windows?
|
41
|
+
'start'
|
42
|
+
else
|
43
|
+
'xdg-open'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: opens a given URL in the browser. This
|
48
|
+
# method is designed to handle multiple platforms.
|
49
|
+
#
|
50
|
+
# Returns nothing
|
51
|
+
def open(url)
|
52
|
+
unless windows?
|
53
|
+
system("#{open_command} '#{url.gsub("\'","'\\\\''")}'")
|
54
|
+
else
|
55
|
+
system("#{open_command} #{url.gsub("\'","'\\\\''")}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: returns the command used to copy a given Item's value to the
|
60
|
+
# clipboard for the current platform.
|
61
|
+
#
|
62
|
+
# Returns a String with the bin
|
63
|
+
def copy_command
|
64
|
+
if darwin?
|
65
|
+
'pbcopy'
|
66
|
+
elsif windows?
|
67
|
+
'clip'
|
68
|
+
else
|
69
|
+
'xclip -selection clipboard'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Public: copies a given URL value to the clipboard. This method is
|
74
|
+
# designed to handle multiple platforms.
|
75
|
+
#
|
76
|
+
# Returns nothing
|
77
|
+
def copy(url)
|
78
|
+
IO.popen(copy_command,"w") {|cc| cc.write(url)}
|
79
|
+
url
|
80
|
+
end
|
81
|
+
|
82
|
+
# Public: opens the JSON file in an editor for you to edit. Uses the
|
83
|
+
# $EDITOR environment variable, or %EDITOR% on Windows for editing.
|
84
|
+
# This method is designed to handle multiple platforms.
|
85
|
+
# If $EDITOR is nil, try to open using the open_command.
|
86
|
+
#
|
87
|
+
# Returns a String with a helpful message.
|
88
|
+
def edit(json_file)
|
89
|
+
unless $EDITOR.nil?
|
90
|
+
unless windows?
|
91
|
+
system("`echo $EDITOR` #{json_file} &")
|
92
|
+
else
|
93
|
+
system("start %EDITOR% #{json_file}")
|
94
|
+
end
|
95
|
+
else
|
96
|
+
system("#{open_command} #{json_file}")
|
97
|
+
end
|
98
|
+
|
99
|
+
'Make your edits, and do be sure to save.'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/imgurr.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
# External require
|
9
|
+
require 'net/http'
|
10
|
+
require 'net/https'
|
11
|
+
require 'json'
|
12
|
+
require 'openssl'
|
13
|
+
|
14
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
15
|
+
|
16
|
+
# Internal require
|
17
|
+
require 'imgurr/command'
|
18
|
+
require 'imgurr/color'
|
19
|
+
require 'imgurr/imgurAPI'
|
20
|
+
require 'imgurr/platform'
|
21
|
+
require 'imgurr/imgurErrors'
|
22
|
+
|
23
|
+
module Imgurr
|
24
|
+
VERSION = '0.0.1'
|
25
|
+
end
|
data/test/run
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Test script will go here
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: imgurr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christophe Naud-Dulude
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.7.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.2
|
41
|
+
description: Imgurr is a ruby gem that lets you upload images to Imgur and manage
|
42
|
+
your account
|
43
|
+
email: christophe.naud.dulude@gmail.com
|
44
|
+
executables:
|
45
|
+
- imgurr
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files:
|
48
|
+
- README.md
|
49
|
+
- LICENSE.md
|
50
|
+
files:
|
51
|
+
- README.md
|
52
|
+
- LICENSE.md
|
53
|
+
- Gemfile
|
54
|
+
- Gemfile.lock
|
55
|
+
- imgurr.gemspec
|
56
|
+
- bin/imgurr
|
57
|
+
- lib/imgurr/color.rb
|
58
|
+
- lib/imgurr/command.rb
|
59
|
+
- lib/imgurr/imgurAPI.rb
|
60
|
+
- lib/imgurr/imgurErrors.rb
|
61
|
+
- lib/imgurr/platform.rb
|
62
|
+
- lib/imgurr.rb
|
63
|
+
- test/run
|
64
|
+
homepage: https://github.com/Chris911/imgurr
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --charset=UTF-8
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.0.3
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Imgurr lets you upload images to imgur from the command line
|
89
|
+
test_files: []
|