gistto 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.
@@ -0,0 +1,48 @@
1
+ module Gistto
2
+ # Messages used in the application
3
+
4
+
5
+ # Message used when a configuration file already exists
6
+ MSG_CONFIG_EXISTS= <<-EOS
7
+ Gistto is already configured on your MAC :) !!
8
+
9
+ but
10
+
11
+ if you want to overwrite the configuration run:
12
+ gistto config -n
13
+
14
+ enjoy Gistto!! <3
15
+ EOS
16
+
17
+
18
+ MSG_GITHUB_USER_NOT_CONFIGURED = <<-EOS
19
+ git config --global user.name is not configured, do you want to type user name instead ? (y/n)
20
+ EOS
21
+
22
+
23
+
24
+ MSG_BANNER = <<-EOS
25
+ Usage : gistto [action] [options] [arguments] ...
26
+ * action :
27
+ * config [-n|--new]
28
+ * add [-p|--private] file-path1 file-path2 ... file-pathN
29
+ * get [-o|--open] [-c|--clipboard] [-l|--local] [-s|--show] gist-ID
30
+ * delete gist-ID
31
+ * list
32
+
33
+ warn: [-l|--local] will overwrite local files without mercy :)
34
+
35
+ -n, --new Makes a new user configuration
36
+ -p, --private Save Gist as private
37
+ -o, --open Open Gist in browser in raw format
38
+ -c, --clipboard Copy Gist to clipboard
39
+ -l, --local Copy Gist file(s) to gissto folder
40
+ -s, --show Show Gist file(s) in the screen
41
+ -v, --version Display Gistto current version
42
+ -h, --help Display help screen
43
+ EOS
44
+
45
+
46
+ end
47
+
48
+
@@ -0,0 +1,307 @@
1
+ module Gistto
2
+ module Client
3
+ extend self
4
+
5
+ #
6
+ #
7
+ # => PRIVATE METHODS
8
+ #
9
+ #
10
+ private
11
+
12
+ #
13
+ # configuration method
14
+ # TODO: refactoring config method to separate responsabilities
15
+ #
16
+ def config
17
+ puts "Please wait while we configure gistto in your Mac :)\n".cyan
18
+ #
19
+ # verify if configuration file exists : unless if only for degub purpose
20
+ #
21
+ overwrite = (@options.empty?) ? false : @options.has_key?(:new_config)
22
+ abort Gistto::MSG_CONFIG_EXISTS if File.exists?(File.join(Dir.home,'.gistto')) && !overwrite
23
+ config_file_path = File.join(Dir.home, '.gistto')
24
+ puts "configuration file \t[%s]" % "#{config_file_path}".cyan
25
+ #
26
+ # validates cert and copy to temp
27
+ #
28
+ path_cert = File.join('/tmp','gistto.crt')
29
+ unless File.exists? path_cert
30
+ FileUtils.cp File.join(File.expand_path('../../../extras', __FILE__),'gistto.crt'), '/tmp'
31
+ abort "Cert File can't be copied to temp dir" unless File.exists? path_cert
32
+ end
33
+ puts "Security Cert \t\t[%s] [%s]" % ["Configured".green, "#{path_cert}".cyan]
34
+ #
35
+ # creating home file
36
+ #
37
+ home_path = File.join(Dir.home, 'gistto')
38
+ FileUtils.mkdir home_path unless File.exists? home_path
39
+ puts "Gistto directory \t[%s] [%s]" % ["Configured".green, "#{home_path}".cyan]
40
+ #
41
+ # getting github user and ask for password if github --global user.name is not configured
42
+ # the password will be asked for typing otherwise aborted
43
+ #
44
+ str_user = get_user_from_global
45
+ if str_user.empty?
46
+ # set user name manually?
47
+ print "git config --global user.name is not configured, do you want to type user name instead ? (y/n)"
48
+ answer = $stdin.gets.chomp
49
+ # ask for user
50
+ str_user = ask_for 'user name' if answer.downcase == 'y'
51
+ # user still empty?
52
+ abort "Please configure GitHub Account before continue, remember add git config --global user.name" if str_user.empty?
53
+ end
54
+ #
55
+ # ask for password
56
+ #
57
+ str_pass = ask_for 'password', true
58
+ if str_pass.empty?
59
+ puts "Password can't be blank, please try again".yellow
60
+ str_pass = ask_for 'password', true
61
+ abort "Password can't be blank".red if str_pass.empty?
62
+ end
63
+ #
64
+ # generate token
65
+ #
66
+ github_response = get_token_for str_user, str_pass
67
+ #abort "\nAn error ocurred getting authorization token with GitHub API [status = %s]" % "#{github_response.status}".red unless github_response.status == 201
68
+ #
69
+ # if message is present and error ocurred
70
+ #
71
+ github_data = JSON.load github_response.body
72
+ abort "\nAn error ocurred generating GitHub Token, please try again!\nGitHub Error = %s" % "#{github_data['message']}".red if github_data.has_key? 'message'
73
+ puts "Token \t\t\t[%s]" % "Configured".green
74
+ #
75
+ # validate if token key exists
76
+ #
77
+ if github_data.has_key? 'token'
78
+ # creating configuration file
79
+ File.open(config_file_path , 'w') do |f|
80
+ f.puts "Token:%s" % "#{github_data['token']}"
81
+ f.puts "Cert:%s" % "#{path_cert}"
82
+ f.puts "Gistto-Home:%s" % home_path
83
+ f.close
84
+ end
85
+ puts "Configuration done!".yellow
86
+ puts "GitHub Token : \t\t[%s] \n\n%s" % ["#{github_data['token']}".green, "enjoy Gistto !!!".green]
87
+ else
88
+ puts "\nToken could not be generated and stored in gistto configuration file, please try again".yellow
89
+ end
90
+ rescue
91
+ exit
92
+ end # config
93
+
94
+ #
95
+ # add method
96
+ #
97
+ def add *params
98
+ # validate params
99
+ abort "add options need files to add if you wanna type directly use option type" if params.empty?
100
+ # process files
101
+ params[0].each do |file|
102
+ # exists
103
+ file_path = ((/\//.match(file).size) > 0) ? file : File.join(Dir.pwd, file)
104
+ file_exist = File.exist? file_path
105
+ if file_exist
106
+ file_name = File.basename file_path
107
+ file_content = File.read file_path
108
+
109
+ if file_content.empty?
110
+ puts "#{file_path} [%s] [empty]\n" % "skip".red
111
+ else
112
+ is_public = (@options.empty?) ? true : !@options.has_key?(:private)
113
+ gist_data = post_new_gist generate_data "#{file_name}", "#{file_name}", file_content.chomp, is_public
114
+ if gist_data.has_key? 'id'
115
+ puts "#{file_path} [%s] [#{gist_data['id']}]\n" % "created".green
116
+ else
117
+ puts "#{file_path} [%s] [#{gist_data['message']}]\n" % "skip".red
118
+ end
119
+ end
120
+
121
+ else
122
+ puts "#{file_path} [%s] [doesn't exists]\n" % "skip".red
123
+ end
124
+ end
125
+ rescue Exception => e
126
+ puts e
127
+ end # add
128
+
129
+ #
130
+ # type method
131
+ # read from stdin and creates a file
132
+ # the parameter expected are the file-name and description
133
+ # todo: --save -> to save the typed text to gistto folder
134
+ # todo: refactoring
135
+ #
136
+ def type *params
137
+ # verify params must be 2
138
+ abort "type needs two params filename and description [if descriptions contains spaces must be quoted]" unless params[0].length == 2
139
+ filename = params[0][0]
140
+ description = params[0][1]
141
+ # reading from $stdin
142
+ #content = $stdin.read
143
+
144
+ content = ""
145
+ if $stdin.tty?
146
+ # headers and instructions
147
+ # puts "Remember to finish the typing you must hit CTRL-D [in somecases twice :)]\n"
148
+ puts "Remember to finish the edition please type ::eof"
149
+ puts "please type the content of %s \n" % "#{params[0][0]}".green
150
+ while line = $stdin.gets.chomp
151
+ break if line == "::eof"
152
+ content << line + "\n"
153
+ end
154
+ else
155
+ $stdin.each_line do |line|
156
+ content << line
157
+ end
158
+ end
159
+
160
+ # validating content
161
+ abort "the content of the file mustn't be blank" if content.empty?
162
+ #creating file
163
+ is_public = (@options.empty?) ? true : !@options.has_key?(:private)
164
+ gist_data = post_new_gist generate_data "#{filename}", "#{description}", content.chomp, is_public
165
+ if gist_data.has_key? 'id'
166
+ puts "\n#{filename} [%s] [#{gist_data['id']}]\n" % "created".green
167
+ else
168
+ puts "\n#{filename} [%s] [#{gist_data['message']}]\n" % "fail".red\
169
+ end
170
+ rescue Exception => e
171
+ puts e
172
+ end # type
173
+
174
+ #
175
+ # get a gist by id
176
+ #
177
+ def get *id
178
+ if id.empty?
179
+ puts "gist-ID is required parameter for get method"
180
+ exit
181
+ end
182
+ #options
183
+ copy_to_clipboard = (@options.empty?) ? false : @options.has_key?(:clipboard)
184
+ open_in_browser = (@options.empty?) ? false : @options.has_key?(:open)
185
+ save_local = (@options.empty?) ? false : @options.has_key?(:local)
186
+ show_in_screen =(@options.empty?) ? false : @options.has_key?(:show)
187
+
188
+ if !copy_to_clipboard && !open_in_browser && !save_local && !show_in_screen
189
+ puts "Get without options[-c|-s|-l|-o] don't produce any output we will activate copy to clipboard".yellow
190
+ copy_to_clipboard = true
191
+ end
192
+
193
+ gistto_home = read_from_config_file "Gistto-Home"
194
+ #
195
+ str_code = ""
196
+ id[0].each do |item|
197
+
198
+ gist_response = get_gists ({id: item})
199
+ if gist_response.status == 200
200
+ #
201
+ gist_data = JSON.load(gist_response.body)
202
+ #screen
203
+ puts "\n\n%s\t\t#{gist_data['description']}" % "#{gist_data['id']}".cyan if show_in_screen
204
+ # recorring files
205
+ str_code << "\n\nGIST ID :#{item}\n"
206
+ gist_data['files'].map do |name, content|
207
+ # screen
208
+ puts "\n%s\n" % name.yellow if show_in_screen
209
+ puts "#{content['content']}\n\n" if show_in_screen
210
+ # clipboard
211
+ str_code << "\n\n****** #{name} *******\n\n"
212
+ str_code << "#{content['content']} \n"
213
+ # open in browser
214
+ navigate_to "#{content['raw_url']}" if open_in_browser
215
+ # create files
216
+ if save_local
217
+ # creating folders
218
+ local_path = File.join gistto_home, gist_data['id']
219
+ local_file = File.join local_path, name
220
+ FileUtils.mkdir_p local_path
221
+ # creating files
222
+ File.open(local_file, 'w') {|f| f.write(content['content']) }
223
+ #
224
+ puts "%s successfull created in %s" % ["#{name}".green, "#{local_path}".green]
225
+ end
226
+ end # map
227
+ # clipboard
228
+ if copy_to_clipboard && item.equal?(id[0].last)
229
+ pbcopy str_code
230
+ puts "\nCode copied to clipboard!"
231
+ end
232
+ else
233
+ puts "\nOcurred an error getting gist #{id} [%s]\n" % "fail".red
234
+ end
235
+
236
+ end # each id
237
+ rescue Exception => e
238
+ puts e
239
+ end # get
240
+
241
+ #
242
+ # list
243
+ # =>
244
+ def list *page
245
+ page = [[1]] if page.empty?
246
+ gist_response = get_gists({page: page[0][0]})
247
+ if gist_response.status == 200
248
+ gist_data = JSON.load gist_response.body
249
+
250
+ # getting pages
251
+ total_moves = get_total_moves gist_response[:link]
252
+ # printing
253
+ gist_data.map do |items|
254
+ puts "%s%s#{items['description']}" % ["#{items['id']}".cyan, "#{items['public'] ? "\t\t\tPublic\t\t" : "\tPrivate\t\t"}".magenta]
255
+ puts "Files :" + items['files'].map {|name, content| "\t#{name}".green }.join(",")
256
+ puts "\n"
257
+ end
258
+ # moves?
259
+ unless total_moves.empty?
260
+ puts "There are more gist pending to show, to load them run:"
261
+ total_moves.each { |e| puts "gistto list #{e}".green }
262
+ end
263
+ else
264
+ puts "\nOcurred an error getting list of gist[%s]\n" % "fail".red
265
+ end
266
+ rescue Exception => e
267
+ puts e
268
+ end # list
269
+
270
+ #
271
+ #
272
+ #
273
+ #
274
+ def delete id
275
+ id.each do |gist|
276
+ gist_response = delete_gist gist
277
+ if gist_response.status == 204
278
+ puts "Gist %s deleted ! " % "#{gist}".cyan
279
+ else
280
+ gist_data = JSON.parse gist_response.body
281
+ puts "Gist %s couldn't be deleted [#{gist_data['message']}]" % "#{gist}".red
282
+ end
283
+ end
284
+ rescue Exception => e
285
+ puts e
286
+ end # delete
287
+
288
+ #
289
+ #
290
+ # uses PATCH method
291
+ #
292
+ #
293
+ def update
294
+ puts "Not implemented yet"
295
+ end # update
296
+
297
+
298
+ def sync
299
+ puts "Not implemented yet"
300
+ end
301
+
302
+ def pull
303
+ puts "Not implemented yet"
304
+ end
305
+
306
+ end
307
+ end
@@ -0,0 +1,12 @@
1
+ module Gistto
2
+ module Client
3
+ #
4
+ # GITHUB AUTHORIZATIONS, REFERAL LINKS
5
+ # AND VALID METHODS
6
+ #
7
+ GITHUB_API = 'https://api.github.com'
8
+ GITHUB_API_AUTH_LINK = '/authorizations'
9
+ GITHUB_API_GIST_LINK = '/gists'
10
+ VALID_METHODS = ['config','add','list','delete','type','get','sync','pull','update']
11
+ end
12
+ end
@@ -0,0 +1,78 @@
1
+ module Gistto
2
+ module Client
3
+ extend self
4
+
5
+ private
6
+ #
7
+ #
8
+ # https_open_for
9
+ #
10
+ #
11
+ def https_open_for ops={}
12
+ ops={:url=> nil, :mthd=> nil,:content => nil, :username => nil, :password => nil, :page=> nil}.merge(ops)
13
+ conn = Faraday.new(GITHUB_API , :ssl => { :ca_file => check_cert})
14
+ conn.basic_auth ops[:username], ops[:password] unless ops[:username].nil? && ops[:password].nil?
15
+ response= conn.method(ops[:mthd]).call do |req|
16
+ req.url ops[:url] + ((ops[:username].nil? && ops[:password].nil?) ? "?access_token=%s" % read_token : "" ) + ((ops[:page].nil?) ? "" : "&page=#{ops[:page]}")
17
+ req.headers['Content-Type'] = 'application/json'
18
+ req.body = JSON.generate(ops[:content]) unless ops[:content].nil?
19
+ end
20
+ response
21
+ #rescue Exception => e
22
+ #raise "An error ocurred trying to open connection with GitHub [%s]" % "#{e}".red
23
+ end # https_open_for
24
+
25
+ #
26
+ # Make connection to Get Token
27
+ #
28
+ def get_token_for(username, password)
29
+ url = GITHUB_API_AUTH_LINK
30
+ scopes = %w[repo gist]
31
+ content = generate_scope "Gistto", scopes
32
+ https_open_for ({url: url, mthd: "post", content: content, username: username, password: password})
33
+ end # get_token_for
34
+
35
+ #
36
+ # create a new public gist
37
+ #
38
+ def post_new_gist content
39
+ url = GITHUB_API_GIST_LINK
40
+ response = https_open_for ({url: url, mthd:"post", content: content})
41
+ JSON.parse response.body
42
+ end # post_new_gist
43
+
44
+ #
45
+ #
46
+ #
47
+ #
48
+ def get_gists ops={}
49
+ ops={:id=>nil, :page=>1}.merge(ops)
50
+ url = GITHUB_API_GIST_LINK + ( ops[:id].nil? ? "" : "/#{ops[:id]}")
51
+ https_open_for ({url: url, mthd:"get" , page: ops[:page]})
52
+ end # get_gists
53
+
54
+ #
55
+ #
56
+ #
57
+ #
58
+ def delete_gist id
59
+ url = "#{GITHUB_API_GIST_LINK}/#{id}"
60
+ https_open_for ({:url=> url, mthd:"delete"})
61
+ end # delete_gist
62
+
63
+
64
+ #
65
+ # check if cert exist otherwise create
66
+ #
67
+ def check_cert
68
+ path = File.join('/tmp','gistto.crt')
69
+ unless File.exists? path
70
+ FileUtils.cp File.join(File.expand_path('../../../extras', __FILE__),'gistto.crt'), '/tmp'
71
+ abort "Cert File can't be copied to temp dir" unless File.exists? path
72
+ end
73
+ path
74
+ end # check_cert
75
+
76
+
77
+ end
78
+ end
@@ -0,0 +1,140 @@
1
+ module Gistto
2
+ module Client
3
+ extend self
4
+
5
+ private
6
+ #
7
+ # Ask for data that must be introduced by user
8
+ # todo: refactoring for generic questions
9
+ #
10
+ def ask_for(what, hidden= false)
11
+ `stty -echo` if hidden
12
+ print "Please type your GitHub Account #{what} : "
13
+ data = $stdin.gets.chomp
14
+ if hidden
15
+ `stty echo`
16
+ puts ""
17
+ end
18
+ data
19
+ end # ask_for
20
+
21
+ #
22
+ # get user from git global configuration
23
+ #
24
+ def get_user_from_global
25
+ %x(git config --global user.name).strip
26
+ end # get_user_from_global
27
+
28
+ #
29
+ # generates data JSON
30
+ # create gist
31
+ # delete gist
32
+ # update gist
33
+ # list gist
34
+ #
35
+ def generate_data file_name, description, content, public=true
36
+ # filename and content
37
+ file_data = {}
38
+ file_data[file_name] = {:content => content}
39
+ # data
40
+ gist_data = {"files" => file_data}
41
+ gist_data.merge!({ 'description' => description })
42
+ gist_data.merge!({ 'public' => public })
43
+ gist_data
44
+ end # generate_data
45
+
46
+ #
47
+ #
48
+ #
49
+ #
50
+ def generate_scope note, scope
51
+ scopes = {:note => note, :scopes => scope}
52
+ scopes
53
+ end
54
+
55
+
56
+
57
+ #
58
+ # pbcopy
59
+ # todo: modify pbcopy to support any OS
60
+ #
61
+ def pbcopy str
62
+ IO.popen('pbcopy', 'w'){ |f| f << str.to_s }
63
+ end # pbcopy
64
+
65
+ #
66
+ #
67
+ # create a random file name en base a date of creation
68
+ #
69
+ #
70
+ def gistto_file_name
71
+ d_c = Time.now
72
+ "gistto-#{d_c.year}.#{d_c.month}.#{d_c.day}.#{d_c.hour}.#{d_c.min}.#{d_c.sec}.txt"
73
+ end # gistto file name
74
+
75
+ #
76
+ #
77
+ #
78
+ #
79
+ def has_param params, key
80
+ #return false unless#params.first.first.kind_of? Array
81
+ params.first.first.has_key?(key) && params.first.first[key] unless params.empty?
82
+ end # has_param
83
+
84
+ #
85
+ #
86
+ #
87
+ #
88
+ def read_token
89
+ return @temporal_token unless @temporal_token.nil?
90
+ @temporal_token = read_from_config_file "Token"
91
+ @temporal_token
92
+ end
93
+
94
+ #
95
+ #
96
+ #
97
+ #
98
+ #
99
+ def read_from_config_file param
100
+ config_value = nil
101
+ # configuration file
102
+ configuration_file = File.join(Dir.home, '.gistto')
103
+ File.open(configuration_file, 'r') do |handler|
104
+ while line = handler.gets
105
+ if /^#{param}:/ =~ line
106
+ config_value = line.split(":")[1].chomp!
107
+ break
108
+ end
109
+ end
110
+ end
111
+ config_value
112
+ end
113
+
114
+ #
115
+ #
116
+ #
117
+ #
118
+ def navigate_to url
119
+ `open #{url}`
120
+ end # navigate_to
121
+
122
+
123
+ #
124
+ #
125
+ #
126
+ #
127
+ def get_total_moves links
128
+ # validating for return
129
+ return [] if links.nil?
130
+ # get all available moves in links
131
+ total_moves = links.split(",").map do |link|
132
+ link = link.gsub(/[<>]/,'').strip.split(";").first
133
+ i_page = link.split("&").to_a.select { |v| v.match("page") }.map { |v| v.split("=")[1] }.first
134
+ link = i_page
135
+ end.uniq
136
+ total_moves
137
+ end # get_total_pages
138
+
139
+ end
140
+ end
@@ -0,0 +1,3 @@
1
+ module Gistto
2
+ VERSION = "0.0.1"
3
+ end
data/lib/gistto.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "gistto/version"
2
+ require "gistto/messages"
3
+ require "gistto/client"
4
+ require "gistto/enhancements/color"
5
+ require "gistto/modules/https"
6
+ require "gistto/modules/utils"
7
+ require "gistto/modules/actions"
8
+ require "gistto/modules/constants"
9
+
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gistto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - erikwco
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Gist Client with multiples and suitables functionalities
14
+ email:
15
+ - erikchacon@me.com
16
+ executables:
17
+ - gistto
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
26
+ - bin/gistto
27
+ - extras/gistto.bck
28
+ - extras/gistto.crt
29
+ - gistto.gemspec
30
+ - lib/gistto.rb
31
+ - lib/gistto/client.rb
32
+ - lib/gistto/enhancements/color.rb
33
+ - lib/gistto/enhancements/json.rb
34
+ - lib/gistto/messages.rb
35
+ - lib/gistto/modules/actions.rb
36
+ - lib/gistto/modules/constants.rb
37
+ - lib/gistto/modules/https.rb
38
+ - lib/gistto/modules/utils.rb
39
+ - lib/gistto/version.rb
40
+ homepage: https://github.com/erikwco/gistto
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.0.0
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Gist Client for GitHub
64
+ test_files: []