neocities 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +15 -0
- data/bin/neocities +1 -1
- data/lib/neocities.rb +3 -3
- data/lib/neocities/cli.rb +94 -24
- data/lib/neocities/client.rb +32 -16
- data/lib/neocities/version.rb +1 -1
- data/neocities.gemspec +4 -14
- metadata +8 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6247ca86f02faa4f57147bf46dde7f04e6d96f9
|
4
|
+
data.tar.gz: 9f4a4b8f63992410de81fb9992edd7f133e7ad4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5547e47f7ff6d96504cf4b7883da0503b5a9bda6d6cd795fdae357afb83e67152e1fffe33e012193e5512ec83e502dfd6882c520fc76e79397e339354027dded
|
7
|
+
data.tar.gz: efcd58356410fbd8ee8e28389d789c803ba7ff6659f4ce8ff9aafba49637bff0d05ac39ef033e50d50ffb6e4c398e337a24320ce33f354d9a3ceedbab48a3aba
|
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# The Neocities Gem
|
2
|
+
|
3
|
+
A CLI and library for using the Neocities API. Makes it easy to quickly upload, push, delete, and list your Neocities site.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
If you're using OSX (or already have ruby installed), run this command:
|
8
|
+
|
9
|
+
gem install neocities
|
10
|
+
|
11
|
+
After that, you are all set! Run `neocities` to see the options and get started.
|
12
|
+
|
13
|
+
## Neocities::Client
|
14
|
+
|
15
|
+
This gem also ships with Neocities::Client, which you can use to write code that interfaces with the Neocities API.
|
data/bin/neocities
CHANGED
data/lib/neocities.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require File.join(File.dirname(__FILE__), 'neocities', 'version')
|
2
|
+
require File.join(File.dirname(__FILE__), 'neocities', 'client')
|
3
|
+
require File.join(File.dirname(__FILE__), 'neocities', 'cli')
|
data/lib/neocities/cli.rb
CHANGED
@@ -4,11 +4,11 @@ require 'tty/table'
|
|
4
4
|
require 'tty/prompt'
|
5
5
|
require 'fileutils'
|
6
6
|
require 'buff/ignore'
|
7
|
+
require File.join(File.dirname(__FILE__), 'client')
|
7
8
|
|
8
9
|
module Neocities
|
9
10
|
class CLI
|
10
|
-
|
11
|
-
SUBCOMMANDS = %w{upload delete list info sync pizza}
|
11
|
+
SUBCOMMANDS = %w{upload delete list info push logout pizza}
|
12
12
|
HELP_SUBCOMMANDS = ['-h', '--help', 'help']
|
13
13
|
PENELOPE_MOUTHS = %w{^ o ~ - v U}
|
14
14
|
PENELOPE_EYES = %w{o ~ O}
|
@@ -20,6 +20,7 @@ module Neocities
|
|
20
20
|
@subargs = @argv[1..@argv.length]
|
21
21
|
@prompt = TTY::Prompt.new
|
22
22
|
@api_key = ENV['NEOCITIES_API_KEY'] || nil
|
23
|
+
@app_config_path = File.join self.class.app_config_path, 'config'
|
23
24
|
end
|
24
25
|
|
25
26
|
def display_response(resp)
|
@@ -42,7 +43,7 @@ module Neocities
|
|
42
43
|
send "display_#{@subcmd}_help_and_exit" if @subargs.empty?
|
43
44
|
|
44
45
|
begin
|
45
|
-
@api_key = File.read
|
46
|
+
@api_key = File.read @app_config_path
|
46
47
|
rescue Errno::ENOENT
|
47
48
|
@api_key = nil
|
48
49
|
end
|
@@ -59,9 +60,9 @@ module Neocities
|
|
59
60
|
|
60
61
|
res = @client.key
|
61
62
|
if res[:api_key]
|
62
|
-
FileUtils.mkdir_p Pathname(
|
63
|
-
File.write
|
64
|
-
puts "The api key for #{@pastel.bold @sitename} has been stored in #{@pastel.bold
|
63
|
+
FileUtils.mkdir_p Pathname(@app_config_path).dirname
|
64
|
+
File.write @app_config_path, res[:api_key]
|
65
|
+
puts "The api key for #{@pastel.bold @sitename} has been stored in #{@pastel.bold @app_config_path}."
|
65
66
|
else
|
66
67
|
display_response resp
|
67
68
|
exit
|
@@ -82,6 +83,21 @@ module Neocities
|
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
86
|
+
def logout
|
87
|
+
confirmed = false
|
88
|
+
loop {
|
89
|
+
case @subargs[0]
|
90
|
+
when '-y' then @subargs.shift; confirmed = true
|
91
|
+
when /^-/ then puts(@pastel.red.bold("Unknown option: #{@subargs[0].inspect}")); display_logout_help_and_exit
|
92
|
+
else break
|
93
|
+
end
|
94
|
+
}
|
95
|
+
if confirmed
|
96
|
+
FileUtils.rm @app_config_path
|
97
|
+
puts @pastel.bold("Your api key has been removed.")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
85
101
|
def info
|
86
102
|
resp = @client.info(@subargs[0] || @sitename)
|
87
103
|
|
@@ -137,14 +153,14 @@ module Neocities
|
|
137
153
|
end
|
138
154
|
end
|
139
155
|
|
140
|
-
def
|
156
|
+
def push
|
141
157
|
@no_gitignore = false
|
142
158
|
@excluded_files = []
|
143
159
|
loop {
|
144
160
|
case @subargs[0]
|
145
161
|
when '--no-gitignore' then @subargs.shift; @no_gitignore = true
|
146
162
|
when '-e' then @subargs.shift; @excluded_files.push(@subargs.shift)
|
147
|
-
when /^-/ then puts(@pastel.red.bold("Unknown option: #{@subargs[0].inspect}"));
|
163
|
+
when /^-/ then puts(@pastel.red.bold("Unknown option: #{@subargs[0].inspect}")); display_push_help_and_exit
|
148
164
|
else break
|
149
165
|
end
|
150
166
|
}
|
@@ -153,12 +169,12 @@ module Neocities
|
|
153
169
|
|
154
170
|
if !root_path.exist?
|
155
171
|
display_response result: 'error', message: "path #{root_path} does not exist"
|
156
|
-
|
172
|
+
display_push_help_and_exit
|
157
173
|
end
|
158
174
|
|
159
175
|
if !root_path.directory?
|
160
176
|
display_response result: 'error', message: 'provided path is not a directory'
|
161
|
-
|
177
|
+
display_push_help_and_exit
|
162
178
|
end
|
163
179
|
|
164
180
|
Dir.chdir(root_path) do
|
@@ -166,10 +182,20 @@ module Neocities
|
|
166
182
|
|
167
183
|
if @no_gitignore == false
|
168
184
|
begin
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
185
|
+
ignores = File.readlines('.gitignore').collect! do |ignore|
|
186
|
+
File.directory?(ignore.strip!) ? "#{ignore}**" : ignore
|
187
|
+
end
|
188
|
+
paths.select! do |path|
|
189
|
+
res = true
|
190
|
+
ignores.each do |ignore|
|
191
|
+
if File.fnmatch?(ignore.strip, path)
|
192
|
+
res = false
|
193
|
+
break
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
puts "Not pushing .gitignore entries (--no-gitignore to disable)"
|
198
|
+
rescue Errno::ENOENT
|
173
199
|
end
|
174
200
|
end
|
175
201
|
|
@@ -179,7 +205,7 @@ module Neocities
|
|
179
205
|
|
180
206
|
paths.each do |path|
|
181
207
|
next if path.directory?
|
182
|
-
print @pastel.bold("
|
208
|
+
print @pastel.bold("Uploading #{path} ... ")
|
183
209
|
resp = @client.upload path, path
|
184
210
|
|
185
211
|
if resp[:result] == 'success'
|
@@ -213,7 +239,7 @@ module Neocities
|
|
213
239
|
end
|
214
240
|
|
215
241
|
if path.directory?
|
216
|
-
puts "#{path} is a directory, skipping (see the
|
242
|
+
puts "#{path} is a directory, skipping (see the push command)"
|
217
243
|
next
|
218
244
|
end
|
219
245
|
|
@@ -256,9 +282,11 @@ HERE
|
|
256
282
|
|
257
283
|
#{@pastel.dim 'Examples:'}
|
258
284
|
|
259
|
-
#{@pastel.green '$ neocities delete myfile.jpg'}
|
285
|
+
#{@pastel.green '$ neocities delete myfile.jpg'} Delete myfile.jpg
|
260
286
|
|
261
|
-
#{@pastel.green '$ neocities delete myfile.jpg myfile2.jpg'}
|
287
|
+
#{@pastel.green '$ neocities delete myfile.jpg myfile2.jpg'} Delete myfile.jpg and myfile2.jpg
|
288
|
+
|
289
|
+
#{@pastel.green '$ neocities delete mydir'} Deletes mydir and everything inside it (be careful!)
|
262
290
|
|
263
291
|
HERE
|
264
292
|
exit
|
@@ -280,19 +308,19 @@ HERE
|
|
280
308
|
exit
|
281
309
|
end
|
282
310
|
|
283
|
-
def
|
311
|
+
def display_push_help_and_exit
|
284
312
|
display_banner
|
285
313
|
|
286
314
|
puts <<HERE
|
287
|
-
#{@pastel.green.bold '
|
315
|
+
#{@pastel.green.bold 'push'} - Recursively upload a local directory to your Neocities site
|
288
316
|
|
289
317
|
#{@pastel.dim 'Examples:'}
|
290
318
|
|
291
|
-
#{@pastel.green '$ neocities
|
319
|
+
#{@pastel.green '$ neocities push .'} Recursively upload current directory.
|
292
320
|
|
293
|
-
#{@pastel.green '$ neocities
|
321
|
+
#{@pastel.green '$ neocities push -e node_modules -e secret.txt .'} Exclude certain files from push
|
294
322
|
|
295
|
-
#{@pastel.green '$ neocities
|
323
|
+
#{@pastel.green '$ neocities push --no-gitignore .'} Don't use .gitignore to exclude files
|
296
324
|
|
297
325
|
HERE
|
298
326
|
exit
|
@@ -308,6 +336,20 @@ HERE
|
|
308
336
|
|
309
337
|
#{@pastel.green '$ neocities info fauux'} Gets info for 'fauux' site
|
310
338
|
|
339
|
+
HERE
|
340
|
+
exit
|
341
|
+
end
|
342
|
+
|
343
|
+
def display_logout_help_and_exit
|
344
|
+
display_banner
|
345
|
+
|
346
|
+
puts <<HERE
|
347
|
+
#{@pastel.green.bold 'logout'} - Remove the site api key from the config
|
348
|
+
|
349
|
+
#{@pastel.dim 'Examples:'}
|
350
|
+
|
351
|
+
#{@pastel.green '$ neocities logout -y'}
|
352
|
+
|
311
353
|
HERE
|
312
354
|
exit
|
313
355
|
end
|
@@ -326,16 +368,44 @@ HERE
|
|
326
368
|
display_banner
|
327
369
|
puts <<HERE
|
328
370
|
#{@pastel.dim 'Subcommands:'}
|
329
|
-
|
371
|
+
push Recursively upload a local directory to your site
|
330
372
|
upload Upload individual files to your Neocities site
|
331
373
|
delete Delete files from your Neocities site
|
332
374
|
list List files from your Neocities site
|
333
375
|
info Information and stats for your site
|
376
|
+
logout Remove the site api key from the config
|
334
377
|
version Unceremoniously display version and self destruct
|
335
378
|
pizza Order a free pizza
|
336
379
|
|
337
380
|
HERE
|
338
381
|
exit
|
339
382
|
end
|
383
|
+
|
384
|
+
def self.app_config_path
|
385
|
+
File.join root_config_path, 'neocities'
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.root_config_path
|
389
|
+
platform = if RUBY_PLATFORM =~ /win32/
|
390
|
+
:win32
|
391
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
392
|
+
:darwin
|
393
|
+
elsif RUBY_PLATFORM =~ /linux/
|
394
|
+
:linux
|
395
|
+
else
|
396
|
+
:unknown
|
397
|
+
end
|
398
|
+
|
399
|
+
case platform
|
400
|
+
when :win32
|
401
|
+
return File.join(ENV['LOCALAPPDATA']) if ENV['LOCALAPPDATA']
|
402
|
+
File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data'
|
403
|
+
when :darwin
|
404
|
+
File.join ENV['HOME'], 'Library', 'Application Support'
|
405
|
+
else
|
406
|
+
return File.join(ENV['XDG_CONFIG_HOME']) if ENV['XDG_CONFIG_HOME']
|
407
|
+
File.join ENV['HOME'], '.config'
|
408
|
+
end
|
409
|
+
end
|
340
410
|
end
|
341
411
|
end
|
data/lib/neocities/client.rb
CHANGED
@@ -1,27 +1,31 @@
|
|
1
|
-
require 'http'
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
2
3
|
require 'json'
|
3
4
|
require 'pathname'
|
5
|
+
require 'uri'
|
6
|
+
require 'net/http/post/multipart'
|
4
7
|
|
5
8
|
module Neocities
|
6
9
|
class Client
|
7
10
|
API_URI = 'https://neocities.org/api/'
|
8
11
|
|
9
12
|
def initialize(opts={})
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
@uri = URI.parse API_URI
|
14
|
+
@http = Net::HTTP.new @uri.host, @uri.port
|
15
|
+
@http.use_ssl = true
|
16
|
+
@opts = opts
|
17
|
+
|
18
|
+
unless @opts[:api_key] || (@opts[:sitename] && @opts[:password])
|
15
19
|
raise ArgumentError, 'client requires a login (sitename/password) or an api_key'
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
19
23
|
def list(path=nil)
|
20
|
-
|
24
|
+
get 'list', :path => path
|
21
25
|
end
|
22
26
|
|
23
27
|
def key
|
24
|
-
|
28
|
+
get 'key'
|
25
29
|
end
|
26
30
|
|
27
31
|
def upload(path, remote_path=nil)
|
@@ -31,25 +35,37 @@ module Neocities
|
|
31
35
|
raise ArgumentError, "#{path.to_s} does not exist."
|
32
36
|
end
|
33
37
|
|
34
|
-
|
35
|
-
(remote_path || path.basename) => HTTP::FormData::File.new(path.to_s)
|
36
|
-
}
|
38
|
+
post 'upload', (remote_path || path.basename) => UploadIO.new(path.to_s, 'application/octet-stream')
|
37
39
|
end
|
38
40
|
|
39
41
|
def delete(*paths)
|
40
|
-
|
42
|
+
post 'delete', 'filenames[]' => paths
|
41
43
|
end
|
42
44
|
|
43
45
|
def info(sitename)
|
44
|
-
|
46
|
+
get 'info', sitename: sitename
|
45
47
|
end
|
46
48
|
|
47
49
|
private
|
48
50
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
51
|
+
def get(path, params={})
|
52
|
+
req = Net::HTTP::Get.new "#{@uri.path}#{path}?#{URI.encode_www_form(params)}"
|
53
|
+
request req
|
54
|
+
end
|
55
|
+
|
56
|
+
def post(path, args={})
|
57
|
+
req = Net::HTTP::Post::Multipart.new("#{@uri.path}#{path}", args)
|
58
|
+
res = request req
|
52
59
|
end
|
53
60
|
|
61
|
+
def request(req)
|
62
|
+
if @opts[:api_key]
|
63
|
+
req['Authorization'] = "Bearer #{@opts[:api_key]}"
|
64
|
+
else
|
65
|
+
req.basic_auth @opts[:sitename], @opts[:password]
|
66
|
+
end
|
67
|
+
resp = @http.request req
|
68
|
+
JSON.parse resp.body, symbolize_names: true
|
69
|
+
end
|
54
70
|
end
|
55
71
|
end
|
data/lib/neocities/version.rb
CHANGED
data/neocities.gemspec
CHANGED
@@ -16,18 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.test_files = spec.files.grep(%r{^(tests)/})
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
-
spec.add_dependency 'tty-table',
|
20
|
-
spec.add_dependency 'tty-prompt',
|
21
|
-
spec.add_dependency 'pastel',
|
22
|
-
spec.add_dependency '
|
23
|
-
spec.add_dependency 'buff-ignore', '~> 1.2'
|
24
|
-
|
25
|
-
# spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
-
# spec.add_development_dependency 'faker'
|
27
|
-
# spec.add_development_dependency 'minitest'
|
28
|
-
# spec.add_development_dependency 'minitest-reporters'
|
29
|
-
# spec.add_development_dependency 'rack-test'
|
30
|
-
# spec.add_development_dependency 'mocha'
|
31
|
-
# spec.add_development_dependency 'webmock'
|
32
|
-
# spec.add_development_dependency 'simplecov'
|
19
|
+
spec.add_dependency 'tty-table', '~> 0.8', '>= 0.8.0'
|
20
|
+
spec.add_dependency 'tty-prompt', '~> 0.12', '>= 0.12.0'
|
21
|
+
spec.add_dependency 'pastel', '~> 0.7', '>= 0.7.1'
|
22
|
+
spec.add_dependency 'multipart-post', '~> 2.0', '>= 2.0.0'
|
33
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neocities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Drake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-table
|
@@ -71,39 +71,25 @@ dependencies:
|
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: 0.7.1
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
|
-
name:
|
74
|
+
name: multipart-post
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
77
|
- - "~>"
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: '2.
|
79
|
+
version: '2.0'
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 2.
|
82
|
+
version: 2.0.0
|
83
83
|
type: :runtime
|
84
84
|
prerelease: false
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '2.
|
89
|
+
version: '2.0'
|
90
90
|
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
|
-
version: 2.
|
93
|
-
- !ruby/object:Gem::Dependency
|
94
|
-
name: buff-ignore
|
95
|
-
requirement: !ruby/object:Gem::Requirement
|
96
|
-
requirements:
|
97
|
-
- - "~>"
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: '1.2'
|
100
|
-
type: :runtime
|
101
|
-
prerelease: false
|
102
|
-
version_requirements: !ruby/object:Gem::Requirement
|
103
|
-
requirements:
|
104
|
-
- - "~>"
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '1.2'
|
92
|
+
version: 2.0.0
|
107
93
|
description:
|
108
94
|
email:
|
109
95
|
- contact@neocities.org
|
@@ -114,6 +100,7 @@ extra_rdoc_files: []
|
|
114
100
|
files:
|
115
101
|
- ".gitignore"
|
116
102
|
- Gemfile
|
103
|
+
- README.md
|
117
104
|
- bin/neocities
|
118
105
|
- lib/neocities.rb
|
119
106
|
- lib/neocities/cli.rb
|