lgtm_hd 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -6
- data/lgtm_hd.gemspec +4 -2
- data/lib/lgtm_hd.rb +1 -0
- data/lib/lgtm_hd/cli.rb +121 -53
- data/lib/lgtm_hd/configuration.rb +10 -6
- data/lib/lgtm_hd/lgtmdotin.rb +57 -0
- data/lib/lgtm_hd/meme_generator.rb +4 -6
- data/lib/lgtm_hd/utilities.rb +3 -0
- data/lib/lgtm_hd/version.rb +1 -1
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c41c2e01a27d7f6c8d8abeb1ab55d879c7301af8
|
4
|
+
data.tar.gz: 8276a44c7526c9fa68f5fbebba7b58b4049b84c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6421eb054e6a2872df460ffc5a8b6c3603a8a94faaddef6b6e9ca52beed0e3004e8dd3e75801f3c087d7ba03ccd3c91e7895f89393b9d6e5689863f7e5743350
|
7
|
+
data.tar.gz: a2703a165f8e37526decb537b1f9aa4d89c02dc0f8a89a16a8265ac2cff18cdd810e86d635a640b4097e435a3dcc8effee80e0aa581164d3a8fb64b0347639e1
|
data/README.md
CHANGED
@@ -23,14 +23,29 @@ Source | Happy Taeyeon!
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
$ lgtm_hd
|
27
|
-
$ lgtm_hd
|
26
|
+
$ lgtm_hd <source_image_uri>
|
27
|
+
$ lgtm_hd random
|
28
28
|
|
29
|
-
|
30
|
-
--clipboard will let the OS copy content of the file for direct pasting to Github comment box
|
31
|
-
--interactive is for lazy people who can
|
29
|
+
Options:
|
30
|
+
--clipboard (or -c) will let the OS copy content of the file for direct pasting to Github comment box
|
31
|
+
--interactive (or -i) is for lazy people who can't bother to type
|
32
|
+
--dest DIR (or -d) is for changing output folder
|
32
33
|
Default command is transform so you can just leave the command empty.
|
33
|
-
|
34
|
+
|
35
|
+
## Examples
|
36
|
+
|
37
|
+
$ lgtm_hd transform http://nogitweet.com/wp-content/uploads/2015/03/fbf5c1c80ffea521bad6e231061731a5.gif
|
38
|
+
\ Reading and inspecting source at http://nogitweet.com/wp-content/uploads/2015/03/fbf5c1c80ffea521bad6e231061731a5.gif
|
39
|
+
\ Processing Image
|
40
|
+
\ Exporting to file
|
41
|
+
\ Exported LGTM image to /Users/huydq/Desktop/lgtm_hd_20170527124831.gif.
|
42
|
+
|
43
|
+
$ lgtm_hd random -c -d /tmp/
|
44
|
+
\ Fetching random image from lgtm.in
|
45
|
+
\ Loading image at http://i.imgur.com/mHrrwpY.gif
|
46
|
+
\ Exported image to /tmp/lgtm_hd_20170527124027.gif
|
47
|
+
\ Copied file to OS's clipboard for direct pasting to Github comments or Slack
|
48
|
+
\ Or you can copy the markdown format by lgtm.in directly below
|
34
49
|
|
35
50
|
## Features
|
36
51
|
|
data/lgtm_hd.gemspec
CHANGED
@@ -11,8 +11,10 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.authors = ["Huy Dinh"]
|
12
12
|
spec.email = ["phradion@gmail.com"]
|
13
13
|
|
14
|
-
spec.summary = %q{
|
15
|
-
spec.description = %q{
|
14
|
+
spec.summary = %q{CLI tool for generating images from user input with LGTM text on it, or fetching images from LGTM.in based on user's query. Finally put the image to clipboard. Support direct image pasting to Github and Slack on MacOSX.}
|
15
|
+
spec.description = %q{This gem is command-line tool for fetching random image from lgtm.in.
|
16
|
+
It also provide tool to apply LGTM text based on input file/url with smart text colors and positions.
|
17
|
+
It also support direct clipboard paste to github's comment box or Slack on MacOSX.}
|
16
18
|
spec.homepage = "http://github.com/phradion/lgtm_hd"
|
17
19
|
spec.license = "MIT"
|
18
20
|
|
data/lib/lgtm_hd.rb
CHANGED
data/lib/lgtm_hd/cli.rb
CHANGED
@@ -8,84 +8,152 @@ module LgtmHD
|
|
8
8
|
class CLI
|
9
9
|
include Commander::Methods
|
10
10
|
|
11
|
+
CMD_RANDOM_SYNTAX = 'lgtm_hd random [-i | --interactive] [-d | --dest DIR]'.freeze
|
12
|
+
CMD_TRANSFORM_SYNTAX = 'lgtm_hd <URI|FILE> [-i | --interactive] [-d | --dest <DIR>]'.freeze
|
13
|
+
|
11
14
|
def run
|
12
15
|
program :name, LgtmHD::Configuration::PROGRAM_NAME
|
13
16
|
program :version, LgtmHD::VERSION
|
14
17
|
program :description, LgtmHD::Configuration::DESCRIPTION
|
18
|
+
|
15
19
|
default_command :transform
|
20
|
+
global_option '-i', '--interactive', 'Turn on interactive Mode. In case you forgot all these super complexive args and options' do say "-- LGTM HD Interactive Mode --" end
|
21
|
+
global_option '-d', '--dest DIR', String, 'Directory to export the LGTM image to. Default value is user\'s current working directory'
|
16
22
|
|
17
|
-
command :
|
18
|
-
c.syntax =
|
19
|
-
c.summary = '
|
23
|
+
command :random do |c|
|
24
|
+
c.syntax = CMD_RANDOM_SYNTAX
|
25
|
+
c.summary = 'Fetch random images from LGTM.in'
|
20
26
|
c.description = ''
|
21
|
-
c.example '', 'lgtm_hd
|
22
|
-
c.option '--clipboard', 'Copy the end result (LGTM image) to OS\'s clipboard'
|
23
|
-
c.option '--interactive', 'In case you forgot all these super complexive args and options'
|
27
|
+
c.example 'Example', 'lgtm_hd random'
|
24
28
|
|
25
29
|
c.action do |args, options|
|
26
|
-
|
30
|
+
if options.interactive # Interactive mode!
|
31
|
+
options.dest ||= ask('Destination Directory (Enter to skip): ')
|
32
|
+
end
|
33
|
+
dest_dir = CLI.destination_dir(options.dest)
|
34
|
+
dest_file_prefix = CLI.destination_file_prefix
|
35
|
+
check_uris(dest_dir)
|
36
|
+
|
37
|
+
say_step "Fetching from lgtm.in"
|
38
|
+
dest_uri,image_markdown = LgtmDotIn.fetch_random_image(dest_dir,dest_file_prefix) do |url, markdown|
|
39
|
+
say_step "Loading image at #{url}"
|
40
|
+
end
|
27
41
|
|
42
|
+
say_ok "Exported image to #{dest_uri}"
|
43
|
+
copy_file_to_clipboard(dest_uri)
|
44
|
+
say "\nOr you can copy the markdown format below provided by lgtm.in"
|
45
|
+
say_code_block "#{image_markdown}"
|
46
|
+
say "\nIf the image does not have LGTM texts on it, run the cmd below"
|
47
|
+
say_code_block "lgtm_hd #{dest_uri}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
command :transform do |c|
|
52
|
+
c.syntax = CMD_TRANSFORM_SYNTAX
|
53
|
+
c.summary = 'Generate LGTM text on top of image URL or local image File'
|
54
|
+
c.description = 'The command \e[3mtransform\e[0m is the default command hence you can skip typing it instead'
|
55
|
+
c.example 'Example', 'lgtm_hd http://domain.com/image.png'
|
56
|
+
|
57
|
+
c.action do |args, options|
|
28
58
|
# ARGS validation!
|
29
|
-
if args.length
|
30
|
-
|
31
|
-
output_uri = args[1]
|
59
|
+
if args.length >= 1
|
60
|
+
source_uri = args[0]
|
32
61
|
elsif options.interactive # Interactive mode!
|
33
|
-
|
34
|
-
|
35
|
-
output_uri = ask('Output Folder: ')
|
36
|
-
to_clipboard = agree("Copy to clipboard afterward? [Y/N]")
|
62
|
+
source_uri ||= ask(' Source Image (URL or Path/to/file): ')
|
63
|
+
options.dest ||= ask('Destination Directory (Enter to skip): ')
|
37
64
|
else
|
38
|
-
|
39
|
-
|
65
|
+
# Since this is the default command so we will provide a little extra care for first-time user
|
66
|
+
help_the_noobie
|
40
67
|
end
|
41
68
|
|
42
|
-
|
43
69
|
# Validate the inputs
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
Time.now.strftime('%Y-%m-%d_%H-%M-%S') +
|
48
|
-
File.extname(source_uri))
|
49
|
-
raise "Source is not proper URIs (URL or Path/to/file)" unless source_uri =~ URI::regexp || File.exist?(source_uri)
|
50
|
-
raise "Output is invalid path or directory" unless File.exist?(output_folder) && File.directory?(output_folder)
|
51
|
-
|
52
|
-
|
70
|
+
dest_dir = CLI.destination_dir(options.dest)
|
71
|
+
check_uris(dest_dir, source_uri)
|
72
|
+
dest_file = File.join(dest_dir, CLI.destination_file_prefix + File.extname(source_uri))
|
53
73
|
|
54
74
|
# Do stuff with our LGTM meme
|
55
|
-
|
56
|
-
meme_generator = MemeGenerator.new(input_image_uri:source_uri, output_image_uri:
|
57
|
-
|
75
|
+
say_step "Reading and inspecting source at #{source_uri}"
|
76
|
+
meme_generator = MemeGenerator.new(input_image_uri:source_uri, output_image_uri:dest_file)
|
77
|
+
say_step "Transforming Image"
|
58
78
|
meme_generator.draw
|
59
79
|
|
60
80
|
# Export and play around with the clipboard
|
61
|
-
|
81
|
+
say_step "Exporting to file"
|
62
82
|
meme_generator.export do |output|
|
63
|
-
|
64
|
-
|
65
|
-
if OS.mac? then
|
66
|
-
applescript "set the clipboard to (read (POSIX file \"#{output}\") as GIF picture)"
|
67
|
-
say "I see you are using MacOSX. Content of the file has been copied to your clipboard."
|
68
|
-
|
69
|
-
# Apple Script Command reference
|
70
|
-
# Sample: `osascript -e 'set the clipboard to (read (POSIX file "#{output}") as JPEG picture)'`
|
71
|
-
#
|
72
|
-
# Currently Github allow pasting image directly to comment box.
|
73
|
-
# However it does not support pure text content produced by pbcopy so we have to use direct Applescript
|
74
|
-
# No Universal solution as for now.
|
75
|
-
#
|
76
|
-
# Apple Script reference: http://www.macosxautomation.com/applescript/imageevents/08.html
|
77
|
-
else
|
78
|
-
Clipboard.copy(output)
|
79
|
-
say "Path to LGTM file has been copied to your clipboard."
|
80
|
-
end
|
81
|
-
end # end of if to_clipboard
|
83
|
+
say_ok "Exported LGTM image to #{output}."
|
84
|
+
copy_file_to_clipboard(dest_file)
|
82
85
|
end # end of meme_generator.export block
|
86
|
+
end # end of action
|
87
|
+
end # end of command transform
|
83
88
|
|
84
|
-
|
89
|
+
run!
|
90
|
+
end # end run def
|
91
|
+
|
92
|
+
def help_the_noobie
|
93
|
+
say "To add LGTM text:"
|
94
|
+
say_code_block CLI::CMD_TRANSFORM_SYNTAX
|
95
|
+
say "To fetch LGTM text:"
|
96
|
+
say_code_block CLI::CMD_RANDOM_SYNTAX
|
97
|
+
say "More Help:"
|
98
|
+
say_code_block "lgtm_hd --help"
|
99
|
+
say "\nVisit #{LgtmHD::Configuration::MORE_HELP_URL} for development purpose or more examples"
|
100
|
+
exit
|
101
|
+
end
|
85
102
|
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def copy_file_to_clipboard(output_file)
|
107
|
+
if OS.mac? then
|
108
|
+
applescript "set the clipboard to (read (POSIX file \"#{output_file}\") as GIF picture)"
|
109
|
+
say_ok "Copied file to OS's clipboard for direct pasting to Github comments or Slack"
|
110
|
+
|
111
|
+
# Apple Script Command reference
|
112
|
+
# Sample: `osascript -e 'set the clipboard to (read (POSIX file "#{output}") as JPEG picture)'`
|
113
|
+
#
|
114
|
+
# Currently Github allow pasting image directly to comment box.
|
115
|
+
# However it does not support pure text content produced by pbcopy so we have to use direct Applescript
|
116
|
+
# No Universal solution as for now.
|
117
|
+
#
|
118
|
+
# Apple Script reference: http://www.macosxautomation.com/applescript/imageevents/08.html
|
119
|
+
else
|
120
|
+
Clipboard.copy(output_file)
|
121
|
+
say_ok "Copied file's path to OS's clipboard"
|
86
122
|
end
|
123
|
+
end
|
87
124
|
|
88
|
-
|
125
|
+
def say_step(*args)
|
126
|
+
args.each do |arg|
|
127
|
+
say $terminal.color(arg, :magenta)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def say_code_block(*args)
|
132
|
+
args.each do |arg|
|
133
|
+
say $terminal.color("#{arg}", :black, :on_white)
|
134
|
+
end
|
89
135
|
end
|
90
|
-
|
91
|
-
|
136
|
+
|
137
|
+
def check_uris(dest_dir, source_uri = nil)
|
138
|
+
begin
|
139
|
+
raise ArgumentError, "Destination path for exporting image is invalid" unless File.exist?(dest_dir) && File.directory?(dest_dir)
|
140
|
+
if !!source_uri
|
141
|
+
raise ArgumentError, "Source image is neither proper URL nor FILE" unless source_uri =~ URI::regexp || File.exist?(source_uri)
|
142
|
+
end
|
143
|
+
rescue ArgumentError => e
|
144
|
+
say_error e.message
|
145
|
+
exit
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.destination_dir(dest_dir)
|
150
|
+
dest_dir ||= Dir.pwd
|
151
|
+
File.expand_path(dest_dir)
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.destination_file_prefix
|
155
|
+
LgtmHD::Configuration::OUTPUT_PREFIX + Time.now.strftime('%Y%m%d%H%M%S')
|
156
|
+
end
|
157
|
+
|
158
|
+
end # end of Class
|
159
|
+
end # end of Module
|
@@ -2,17 +2,21 @@ module LgtmHD
|
|
2
2
|
module Configuration
|
3
3
|
# Program configurations
|
4
4
|
PROGRAM_NAME = "lgtm_hd".freeze
|
5
|
-
|
6
|
-
|
5
|
+
AUTHOR = "Huy Dinh <phradion@gmail.com>".freeze
|
6
|
+
DESCRIPTION = "Generating images from user input with LGTM text on it,"\
|
7
|
+
"or fetching images from LGTM.in based on user's query.\n"\
|
8
|
+
"Finally put the image to clipboard.".freeze
|
9
|
+
MORE_HELP_URL = "https://github.com/phradion/lgtm_hd".freeze
|
10
|
+
|
7
11
|
# Output Image configurations
|
8
12
|
OUTPUT_PREFIX = "lgtm_hd_".freeze
|
9
|
-
OUTPUT_MAX_WIDTH = 500
|
10
|
-
OUTPUT_MAX_HEIGHT = 500
|
11
|
-
OUTPUT_DENSITY = 90
|
13
|
+
OUTPUT_MAX_WIDTH = 500
|
14
|
+
OUTPUT_MAX_HEIGHT = 500
|
15
|
+
OUTPUT_DENSITY = 90 # or 120 point per inch
|
12
16
|
|
13
17
|
# Caption configurations
|
14
18
|
FONT_PATH = "/fonts/impact.ttf".freeze
|
15
|
-
CAPTION_FONT_SIZE_DEFAULT = 96
|
19
|
+
CAPTION_FONT_SIZE_DEFAULT = 96
|
16
20
|
|
17
21
|
end
|
18
22
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'resolv-replace'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module LgtmHD
|
5
|
+
class LgtmDotIn
|
6
|
+
API_STARTING_ENDPOINT = "http://www.lgtm.in/g".freeze
|
7
|
+
ACTUAL_IMAGE_URL_USE_SSL = false
|
8
|
+
TRY_FETCHING_IMAGE_LIMIT = 3 # I have hit lgtm.in with bad content 5 times in a row
|
9
|
+
TRY_FETCHING_META_LIMIT = 3 # God know how many more redirect lgtm.in will use in the future
|
10
|
+
|
11
|
+
def self.fetch_random_image(dest_path = nil, file_prefix = nil)
|
12
|
+
# LGTM.in has so many broken images
|
13
|
+
# So we loop until a good image is found
|
14
|
+
limit = TRY_FETCHING_IMAGE_LIMIT
|
15
|
+
begin
|
16
|
+
json_data = fetch_meta_data
|
17
|
+
image_url = json_data["actualImageUrl"]
|
18
|
+
image_markdown = json_data["markdown"].lines.first.strip
|
19
|
+
yield image_url, image_markdown
|
20
|
+
|
21
|
+
# fetching image data
|
22
|
+
dest_file = File.join(dest_path ||= '/tmp', (file_prefix ||= 'lgtmdotin_') + File.extname(image_url))
|
23
|
+
uri = URI.parse(image_url)
|
24
|
+
|
25
|
+
uri.open(redirect: false, ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE) do |input_stream|
|
26
|
+
File.open(dest_file, 'wb') do |output_stream|
|
27
|
+
IO.copy_stream(input_stream, output_stream)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
[dest_file, image_markdown]
|
31
|
+
rescue OpenURI::HTTPError, SocketError, Net::ReadTimeout => error
|
32
|
+
retry if (limit -= 1) > 0
|
33
|
+
raise error, "We have tried 3 times but all images are broken. Either LGTM.in is trash or you are super unlucky"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
private
|
39
|
+
def self.fetch_meta_data(uri = API_STARTING_ENDPOINT, limit = TRY_FETCHING_META_LIMIT)
|
40
|
+
uri = URI.parse(API_STARTING_ENDPOINT)
|
41
|
+
##
|
42
|
+
# LGTM.in has a JSON endpoint that
|
43
|
+
# .forwards to an SSL HTTP address that
|
44
|
+
# .has no valid SSL certificate
|
45
|
+
# Hence the loop
|
46
|
+
#
|
47
|
+
begin
|
48
|
+
data = uri.open('Accept' => 'application/json', redirect: false, ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
49
|
+
json = JSON.parse data.readlines.join("")
|
50
|
+
rescue OpenURI::HTTPRedirect => redirect
|
51
|
+
uri = redirect.uri # assigned from the "Location" response header
|
52
|
+
retry if (limit -= 1) > 0
|
53
|
+
raise IOError, "There maybe a network issue. The program failed to contact LGTM.in JSON API"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -2,7 +2,8 @@ require "mini_magick"
|
|
2
2
|
|
3
3
|
module LgtmHD
|
4
4
|
class MemeGenerator
|
5
|
-
|
5
|
+
@@caption_positions = {caption_position_top: "north center", caption_position_bottom: "south center"}
|
6
|
+
|
6
7
|
# TODO make options list for this class
|
7
8
|
# TODO pass BLOB data into this class instead of paths
|
8
9
|
def initialize(input_image_uri:, output_image_uri:)
|
@@ -54,11 +55,8 @@ module LgtmHD
|
|
54
55
|
# Default value is top
|
55
56
|
#
|
56
57
|
def caption_position
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
return {:caption_position_top => "north center",
|
61
|
-
:caption_position_bottom => "south center"}[@caption_position]
|
58
|
+
@caption_position = :caption_position_bottom unless [:caption_position_top, :caption_position_bottom].include? @caption_position
|
59
|
+
@@caption_positions[@caption_position]
|
62
60
|
end
|
63
61
|
|
64
62
|
def caption_font
|
data/lib/lgtm_hd/utilities.rb
CHANGED
data/lib/lgtm_hd/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lgtm_hd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Huy Dinh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,8 +136,10 @@ dependencies:
|
|
136
136
|
- - '='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 4.7.0
|
139
|
-
description:
|
140
|
-
|
139
|
+
description: |-
|
140
|
+
This gem is command-line tool for fetching random image from lgtm.in.
|
141
|
+
It also provide tool to apply LGTM text based on input file/url with smart text colors and positions.
|
142
|
+
It also support direct clipboard paste to github's comment box or Slack on MacOSX.
|
141
143
|
email:
|
142
144
|
- phradion@gmail.com
|
143
145
|
executables:
|
@@ -162,6 +164,7 @@ files:
|
|
162
164
|
- lib/lgtm_hd.rb
|
163
165
|
- lib/lgtm_hd/cli.rb
|
164
166
|
- lib/lgtm_hd/configuration.rb
|
167
|
+
- lib/lgtm_hd/lgtmdotin.rb
|
165
168
|
- lib/lgtm_hd/meme_generator.rb
|
166
169
|
- lib/lgtm_hd/utilities.rb
|
167
170
|
- lib/lgtm_hd/version.rb
|
@@ -185,8 +188,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
188
|
version: '0'
|
186
189
|
requirements: []
|
187
190
|
rubyforge_project:
|
188
|
-
rubygems_version: 2.
|
191
|
+
rubygems_version: 2.6.12
|
189
192
|
signing_key:
|
190
193
|
specification_version: 4
|
191
|
-
summary:
|
194
|
+
summary: CLI tool for generating images from user input with LGTM text on it, or fetching
|
195
|
+
images from LGTM.in based on user's query. Finally put the image to clipboard. Support
|
196
|
+
direct image pasting to Github and Slack on MacOSX.
|
192
197
|
test_files: []
|