gistto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []