neocities-red 1.0.0
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/.github/dependabot.yml +6 -0
- data/.gitignore +7 -0
- data/.rspec +4 -0
- data/Gemfile +13 -0
- data/README.md +64 -0
- data/bin/neocities-red +6 -0
- data/ext/mkrf_conf.rb +19 -0
- data/lib/neocities/cli.rb +522 -0
- data/lib/neocities/client.rb +177 -0
- data/lib/neocities/file_list.rb +45 -0
- data/lib/neocities/file_remover.rb +31 -0
- data/lib/neocities/file_uploader.rb +43 -0
- data/lib/neocities/pizza.rb +89 -0
- data/lib/neocities/profile_info.rb +39 -0
- data/lib/neocities/site_exporter.rb +40 -0
- data/lib/neocities/version.rb +5 -0
- data/lib/neocities.rb +11 -0
- data/neocities-red.gemspec +33 -0
- metadata +206 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: eec23bd190087f4364c5a68d394b5662a3709e1a567663e0f218c025d0eeb83a
|
|
4
|
+
data.tar.gz: 3f22fc98249d04d665e9d848cae49507cc475949efc1c0253a3e7f606a487650
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: '0966d54d18cafd78536595231de74f89ca46664b87227b65b17263ef1101c9e9b3fb684909b8a5d3393c2a3df3f510c93c77f8cf5809dd6597fc9c5ebbfe2d9b'
|
|
7
|
+
data.tar.gz: bbef63e19889dd92d1d676c0137b0843feaf6845afaf2f3282b1122281411a51d06d8df63873e8c99f240223676595c38460204963165bf71c147f4219488bc0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Neocities Red
|
|
2
|
+
|
|
3
|
+
Hello, there is a fork of [neocities-ruby gem](https://github.com/neocities/neocities-ruby) with my own features and implementations. A much of my changes doesn't make sense to be pushed into original repository, so i pushed it here.
|
|
4
|
+
|
|
5
|
+
## Main changes/Features:
|
|
6
|
+
|
|
7
|
+
### Currently, this gems tests with ruby 3.4.*, it doesn't supports ruby 4 due of dependencies
|
|
8
|
+
|
|
9
|
+
1) Added MultiThread uploading of files to neocities. This feature boosts `neocities push`;
|
|
10
|
+
2) Moves from `http.rb` to `faraday` gem;
|
|
11
|
+
3) Fixed `-e` flag to exclude folders recursively;
|
|
12
|
+
4) Added `--ignore-dotfiles` to ignore all files-folders starts with '.';
|
|
13
|
+
5) Added `--optimized` for `neocities push` flag to upload only modified files;
|
|
14
|
+
6) Fixed bug with neocities info on modern rubies;
|
|
15
|
+
7) Re-designed `upload` method;
|
|
16
|
+
|
|
17
|
+
## TODO'S:
|
|
18
|
+
1) Check all entire cli and client logic, fix bugs.
|
|
19
|
+
2) Change dependencies for modern analogs.
|
|
20
|
+
3) Refactor `cli.rb` or use `rails/thor` gem instead.
|
|
21
|
+
4) Add tests
|
|
22
|
+
5) Make sure that gem is compatible with Linux, Freebsd, Windows
|
|
23
|
+
6) Make it compatible with ruby 4.0.0
|
|
24
|
+
|
|
25
|
+
# The Neocities Gem
|
|
26
|
+
|
|
27
|
+
A CLI and library for using the Neocities API. Makes it easy to quickly upload, push, delete, and list your Neocities site.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
gem install neocities-red
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Running
|
|
36
|
+
|
|
37
|
+
After that, you are all set! Run `neocities-red` in a command line to see the options and get started.
|
|
38
|
+
|
|
39
|
+
## Gem modules
|
|
40
|
+
|
|
41
|
+
This gem also transpose all processes to several class in lib/neocities, which could be used to write code that interfaces with the Neocities API.
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
require 'neocities-red'
|
|
45
|
+
|
|
46
|
+
# use api key
|
|
47
|
+
params = {
|
|
48
|
+
api_key: 'MyKeyFromNeocities'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# or sitename and password
|
|
52
|
+
# params = {
|
|
53
|
+
# sitename: 'petrapixel,
|
|
54
|
+
# password: 'mypass'
|
|
55
|
+
# }
|
|
56
|
+
|
|
57
|
+
client = Neocities::Client.new(params)
|
|
58
|
+
client.key
|
|
59
|
+
client.upload(path, remote_path)
|
|
60
|
+
client.info(sitename)
|
|
61
|
+
client.delete(path)
|
|
62
|
+
client.push(path)
|
|
63
|
+
client.list(path)
|
|
64
|
+
```
|
data/bin/neocities-red
ADDED
data/ext/mkrf_conf.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'rubygems/command'
|
|
5
|
+
require 'rubygems/dependency_installer'
|
|
6
|
+
begin
|
|
7
|
+
Gem::Command.build_args = ARGV
|
|
8
|
+
rescue NoMethodError
|
|
9
|
+
end
|
|
10
|
+
inst = Gem::DependencyInstaller.new
|
|
11
|
+
begin
|
|
12
|
+
inst.install 'openssl-win-root', '~> 1.1' if Gem.win_platform?
|
|
13
|
+
rescue StandardError
|
|
14
|
+
exit(1)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
f = File.open(File.join(File.dirname(__FILE__), 'Rakefile'), 'w') # create dummy rakefile to indicate success
|
|
18
|
+
f.write("task :default\n")
|
|
19
|
+
f.close
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'pastel'
|
|
5
|
+
require 'tty/table'
|
|
6
|
+
require 'tty/prompt'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
require 'json'
|
|
9
|
+
require 'whirly'
|
|
10
|
+
require 'digest'
|
|
11
|
+
require 'time'
|
|
12
|
+
|
|
13
|
+
# warning - the big quantity of working threads could be considered like-a DDOS. Your ip-address could get banned for a few days.
|
|
14
|
+
MAX_THREADS = 5
|
|
15
|
+
|
|
16
|
+
module Neocities
|
|
17
|
+
class CLI
|
|
18
|
+
SUBCOMMANDS = %w[upload delete list info push logout pizza pull].freeze
|
|
19
|
+
HELP_SUBCOMMANDS = ['-h', '--help', 'help'].freeze
|
|
20
|
+
PENELOPE_MOUTHS = %w[^ o ~ - v U].freeze
|
|
21
|
+
PENELOPE_EYES = %w[o ~ O].freeze
|
|
22
|
+
|
|
23
|
+
def initialize(argv)
|
|
24
|
+
@argv = argv.dup
|
|
25
|
+
@pastel = Pastel.new eachline: "\n"
|
|
26
|
+
@subcmd = @argv.first
|
|
27
|
+
@subargs = @argv[1..@argv.length]
|
|
28
|
+
@prompt = TTY::Prompt.new
|
|
29
|
+
@api_key = ENV['NEOCITIES_API_KEY'] || nil
|
|
30
|
+
@app_config_path = File.join self.class.app_config_path('neocities'), 'config.json'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def display_response(resp)
|
|
34
|
+
if resp.is_a?(Exception)
|
|
35
|
+
out = "#{@pastel.red.bold 'ERROR:'} #{resp.detailed_message}"
|
|
36
|
+
puts out
|
|
37
|
+
exit
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if resp[:result] == 'success'
|
|
41
|
+
puts "#{@pastel.green.bold 'SUCCESS:'} #{resp[:message]}"
|
|
42
|
+
elsif resp[:result] == 'error' && resp[:error_type] == 'file_exists'
|
|
43
|
+
out = "#{@pastel.yellow.bold 'EXISTS:'} #{resp[:message]}"
|
|
44
|
+
out += " (#{resp[:error_type]})" if resp[:error_type]
|
|
45
|
+
puts out
|
|
46
|
+
else
|
|
47
|
+
out = "#{@pastel.red.bold 'ERROR:'} #{resp[:message]}"
|
|
48
|
+
out += " (#{resp[:error_type]})" if resp[:error_type]
|
|
49
|
+
puts out
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def run
|
|
54
|
+
if @argv[0] == 'version'
|
|
55
|
+
puts Neocities::VERSION
|
|
56
|
+
exit
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if HELP_SUBCOMMANDS.include?(@subcmd) && SUBCOMMANDS.include?(@subargs[0])
|
|
60
|
+
send "display_#{@subargs[0]}_help_and_exit"
|
|
61
|
+
elsif @subcmd.nil? || !SUBCOMMANDS.include?(@subcmd)
|
|
62
|
+
display_help_and_exit
|
|
63
|
+
elsif @subargs.join('').match(HELP_SUBCOMMANDS.join('|')) && @subcmd != 'info'
|
|
64
|
+
send "display_#{@subcmd}_help_and_exit"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
unless @api_key
|
|
68
|
+
begin
|
|
69
|
+
file = File.read @app_config_path
|
|
70
|
+
data = JSON.parse file
|
|
71
|
+
|
|
72
|
+
if data
|
|
73
|
+
@api_key = data['API_KEY'].strip
|
|
74
|
+
@sitename = data['SITENAME']
|
|
75
|
+
@last_pull = data['LAST_PULL'] # Store the last time a pull was performed so that we only fetch from updated files
|
|
76
|
+
end
|
|
77
|
+
rescue Errno::ENOENT
|
|
78
|
+
@api_key = nil
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if @api_key.nil?
|
|
83
|
+
puts 'Please login to get your API key:'
|
|
84
|
+
|
|
85
|
+
if !@sitename && !@password
|
|
86
|
+
@sitename = @prompt.ask('sitename:', default: ENV['NEOCITIES_SITENAME'])
|
|
87
|
+
@password = @prompt.mask('password:', default: ENV['NEOCITIES_PASSWORD'])
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
@client = Neocities::Client.new sitename: @sitename, password: @password
|
|
91
|
+
|
|
92
|
+
resp = @client.key
|
|
93
|
+
if resp[:api_key]
|
|
94
|
+
conf = {
|
|
95
|
+
"API_KEY": resp[:api_key],
|
|
96
|
+
"SITENAME": @sitename
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
FileUtils.mkdir_p Pathname(@app_config_path).dirname
|
|
100
|
+
File.write @app_config_path, conf.to_json
|
|
101
|
+
|
|
102
|
+
puts "The api key for #{@pastel.bold @sitename} has been stored in #{@pastel.bold @app_config_path}."
|
|
103
|
+
else
|
|
104
|
+
display_response resp
|
|
105
|
+
exit
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
@client = Neocities::Client.new api_key: @api_key
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
send @subcmd
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def delete
|
|
115
|
+
display_delete_help_and_exit if @subargs.empty?
|
|
116
|
+
|
|
117
|
+
@subargs.each do |path|
|
|
118
|
+
FileRemover.new(@client, path).remove
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def logout
|
|
123
|
+
confirmed = false
|
|
124
|
+
|
|
125
|
+
loop do
|
|
126
|
+
case @subargs[0]
|
|
127
|
+
when '-y'
|
|
128
|
+
@subargs.shift
|
|
129
|
+
confirmed = true
|
|
130
|
+
when /^-/
|
|
131
|
+
puts @pastel.red.bold("Unknown option: #{@subargs[0].inspect}")
|
|
132
|
+
break
|
|
133
|
+
else
|
|
134
|
+
break
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if confirmed
|
|
139
|
+
FileUtils.rm @app_config_path
|
|
140
|
+
puts @pastel.bold('Your api key has been removed.')
|
|
141
|
+
else
|
|
142
|
+
display_logout_help_and_exit
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def info
|
|
147
|
+
profile_info = ProfileInfo.new(@client, @subargs, @sitename).pretty_print
|
|
148
|
+
puts TTY::Table.new(profile_info)
|
|
149
|
+
rescue Exception => e
|
|
150
|
+
display_response(e)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def list
|
|
154
|
+
display_list_help_and_exit if @subargs.empty?
|
|
155
|
+
|
|
156
|
+
@detail = true if @subargs.delete('-d') == '-d'
|
|
157
|
+
|
|
158
|
+
@subargs[0] = nil if @subargs.delete('-a')
|
|
159
|
+
|
|
160
|
+
path = @subargs[0]
|
|
161
|
+
|
|
162
|
+
FileList.new(@client, path, @detail).show
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def push
|
|
166
|
+
display_push_help_and_exit if @subargs.empty?
|
|
167
|
+
@no_gitignore = false
|
|
168
|
+
@ignore_dotfiles = false
|
|
169
|
+
@excluded_files = []
|
|
170
|
+
@dry_run = false
|
|
171
|
+
@prune = false
|
|
172
|
+
@optimized = false
|
|
173
|
+
|
|
174
|
+
loop do
|
|
175
|
+
case @subargs[0]
|
|
176
|
+
when '--no-gitignore'
|
|
177
|
+
@subargs.shift
|
|
178
|
+
@no_gitignore = true
|
|
179
|
+
when '--ignore-dotfiles'
|
|
180
|
+
@subargs.shift
|
|
181
|
+
@ignore_dotfiles = true
|
|
182
|
+
when '-e'
|
|
183
|
+
@subargs.shift
|
|
184
|
+
filepath = Pathname.new(@subargs.shift).cleanpath.to_s
|
|
185
|
+
|
|
186
|
+
if File.file?(filepath)
|
|
187
|
+
@excluded_files.push(filepath)
|
|
188
|
+
elsif File.directory?(filepath)
|
|
189
|
+
folder_files = Dir.glob(File.join(filepath, '**', '*'), File::FNM_DOTMATCH).push(filepath)
|
|
190
|
+
@excluded_files += folder_files
|
|
191
|
+
end
|
|
192
|
+
when '--dry-run'
|
|
193
|
+
@subargs.shift
|
|
194
|
+
@dry_run = true
|
|
195
|
+
when '--prune'
|
|
196
|
+
@subargs.shift
|
|
197
|
+
@prune = true
|
|
198
|
+
when '--optimized'
|
|
199
|
+
@subargs.shift
|
|
200
|
+
@optimized = true
|
|
201
|
+
when /^-/
|
|
202
|
+
puts @pastel.red.bold("Unknown option: #{@subargs[0].inspect}")
|
|
203
|
+
display_push_help_and_exit
|
|
204
|
+
else
|
|
205
|
+
break
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
if @subargs[0].nil?
|
|
210
|
+
display_response result: 'error', message: 'no local path provided'
|
|
211
|
+
display_push_help_and_exit
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
root_path = Pathname @subargs[0]
|
|
215
|
+
|
|
216
|
+
unless root_path.exist?
|
|
217
|
+
display_response result: 'error', message: "path #{root_path} does not exist"
|
|
218
|
+
display_push_help_and_exit
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
unless root_path.directory?
|
|
222
|
+
display_response result: 'error', message: 'provided path is not a directory'
|
|
223
|
+
display_push_help_and_exit
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
puts @pastel.green.bold('Doing a dry run, not actually pushing anything') if @dry_run
|
|
227
|
+
|
|
228
|
+
if @prune
|
|
229
|
+
pruned_dirs = []
|
|
230
|
+
resp = @client.list
|
|
231
|
+
resp[:files].each do |file|
|
|
232
|
+
path = Pathname(File.join(@subargs[0], file[:path]))
|
|
233
|
+
|
|
234
|
+
pruned_dirs << path if !path.exist? && file[:is_directory]
|
|
235
|
+
|
|
236
|
+
next unless !path.exist? && !pruned_dirs.include?(path.dirname)
|
|
237
|
+
|
|
238
|
+
print @pastel.bold("Deleting #{file[:path]} ... ")
|
|
239
|
+
resp = @client.delete_wrapper_with_dry_run file[:path], @dry_run
|
|
240
|
+
|
|
241
|
+
if resp[:result] == 'success'
|
|
242
|
+
print "#{@pastel.green.bold('SUCCESS')}\n"
|
|
243
|
+
else
|
|
244
|
+
print "\n"
|
|
245
|
+
display_response resp
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
Dir.chdir(root_path) do
|
|
251
|
+
paths = Dir.glob(File.join('**', '*'), File::FNM_DOTMATCH)
|
|
252
|
+
|
|
253
|
+
if @no_gitignore == false
|
|
254
|
+
begin
|
|
255
|
+
ignores = File.readlines('.gitignore').collect! do |ignore|
|
|
256
|
+
ignore.strip!
|
|
257
|
+
File.directory?(ignore) ? "#{ignore}**" : ignore
|
|
258
|
+
end
|
|
259
|
+
paths.select! do |path|
|
|
260
|
+
res = true
|
|
261
|
+
ignores.each do |ignore|
|
|
262
|
+
if File.fnmatch?(ignore.strip, path)
|
|
263
|
+
res = false
|
|
264
|
+
break
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
puts 'Not pushing .gitignore entries (--no-gitignore to disable)'
|
|
269
|
+
rescue Errno::ENOENT
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
@excluded_files += paths.select { |path| path.start_with?('.') } if @ignore_dotfiles
|
|
274
|
+
|
|
275
|
+
# do not upload files which already uploaded (checking by sha1_hash)
|
|
276
|
+
if @optimized
|
|
277
|
+
hex = paths.select { |path| File.file?(path) }
|
|
278
|
+
.map { |file| { filepath: file, sha1_hash: Digest::SHA1.file(file).hexdigest } }
|
|
279
|
+
|
|
280
|
+
res = @client.list
|
|
281
|
+
server_hex = res[:files].map { |n| n[:sha1_hash] }.compact
|
|
282
|
+
|
|
283
|
+
uploaded_files = hex.select { |n| server_hex.include?(n[:sha1_hash]) }
|
|
284
|
+
.map { |n| n[:filepath] }
|
|
285
|
+
@excluded_files += uploaded_files
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
paths -= @excluded_files
|
|
289
|
+
paths.collect! { |path| Pathname path }
|
|
290
|
+
|
|
291
|
+
task_queue = Queue.new
|
|
292
|
+
paths.each { |path| task_queue.push(path) }
|
|
293
|
+
|
|
294
|
+
threads = []
|
|
295
|
+
|
|
296
|
+
MAX_THREADS.times do
|
|
297
|
+
threads << Thread.new do
|
|
298
|
+
until task_queue.empty?
|
|
299
|
+
path = begin
|
|
300
|
+
task_queue.pop(true)
|
|
301
|
+
rescue StandardError
|
|
302
|
+
nil
|
|
303
|
+
end
|
|
304
|
+
next if path.nil? || path.directory?
|
|
305
|
+
|
|
306
|
+
Neocities::FileUploader.new(@client, path).upload
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
threads.each(&:join)
|
|
312
|
+
puts 'All files uploaded.'
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def upload
|
|
317
|
+
display_upload_help_and_exit if @subargs.empty?
|
|
318
|
+
|
|
319
|
+
loop do
|
|
320
|
+
case @subargs[0]
|
|
321
|
+
when /^-/
|
|
322
|
+
puts @pastel.red.bold("Unknown option: #{@subargs[0].inspect}")
|
|
323
|
+
display_upload_help_and_exit
|
|
324
|
+
else
|
|
325
|
+
break
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
FileUploader.new(@client, @subargs[0], @subargs[1]).upload
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def pull
|
|
333
|
+
quiet = ['--quiet', '-q'].include?(@subargs[0])
|
|
334
|
+
file = File.read(@app_config_path)
|
|
335
|
+
data = JSON.parse(file)
|
|
336
|
+
last_pull_time = data['LAST_PULL']['time']
|
|
337
|
+
last_pull_loc = data['LAST_PULL']['loc']
|
|
338
|
+
|
|
339
|
+
SiteExporter.new(@client, @sitename, data, @app_config_path)
|
|
340
|
+
.export(quiet, last_pull_time, last_pull_loc)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def pizza
|
|
344
|
+
display_pizza_help_and_exit
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def display_pizza_help_and_exit
|
|
348
|
+
puts Pizza.new.make_order
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def display_list_help_and_exit
|
|
352
|
+
display_banner
|
|
353
|
+
|
|
354
|
+
puts <<HERE
|
|
355
|
+
#{@pastel.green.bold 'list'} - List files on your Neocities site
|
|
356
|
+
|
|
357
|
+
#{@pastel.dim 'Examples:'}
|
|
358
|
+
|
|
359
|
+
#{@pastel.green '$ neocities list /'} List files in your root directory
|
|
360
|
+
|
|
361
|
+
#{@pastel.green '$ neocities list -a'} Recursively display all files and directories
|
|
362
|
+
|
|
363
|
+
#{@pastel.green '$ neocities list -d /mydir'} Show detailed information on /mydir
|
|
364
|
+
|
|
365
|
+
HERE
|
|
366
|
+
exit
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def display_delete_help_and_exit
|
|
370
|
+
display_banner
|
|
371
|
+
|
|
372
|
+
puts <<HERE
|
|
373
|
+
#{@pastel.green.bold 'delete'} - Delete files on your Neocities site
|
|
374
|
+
|
|
375
|
+
#{@pastel.dim 'Examples:'}
|
|
376
|
+
|
|
377
|
+
#{@pastel.green '$ neocities delete myfile.jpg'} Delete myfile.jpg
|
|
378
|
+
|
|
379
|
+
#{@pastel.green '$ neocities delete myfile.jpg myfile2.jpg'} Delete myfile.jpg and myfile2.jpg
|
|
380
|
+
|
|
381
|
+
#{@pastel.green '$ neocities delete mydir'} Deletes mydir and everything inside it (be careful!)
|
|
382
|
+
|
|
383
|
+
HERE
|
|
384
|
+
exit
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def display_upload_help_and_exit
|
|
388
|
+
display_banner
|
|
389
|
+
|
|
390
|
+
puts <<HERE
|
|
391
|
+
#{@pastel.green.bold 'upload'} - Upload file to your Neocities site to the specific path
|
|
392
|
+
|
|
393
|
+
#{@pastel.dim 'Examples:'}
|
|
394
|
+
|
|
395
|
+
#{@pastel.green '$ neocities upload /img.jpg /images/img2.jpg'} Upload img.jpg to /images folder and with img2.jpg name
|
|
396
|
+
HERE
|
|
397
|
+
exit
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def display_pull_help_and_exit
|
|
401
|
+
display_banner
|
|
402
|
+
|
|
403
|
+
puts <<HERE
|
|
404
|
+
#{@pastel.magenta.bold 'pull'} - Get the most recent version of files from your site, does not download if files haven't changed
|
|
405
|
+
|
|
406
|
+
HERE
|
|
407
|
+
exit
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def display_push_help_and_exit
|
|
411
|
+
display_banner
|
|
412
|
+
|
|
413
|
+
puts <<HERE
|
|
414
|
+
#{@pastel.green.bold 'push'} - Recursively upload a local directory to your Neocities site
|
|
415
|
+
|
|
416
|
+
#{@pastel.dim 'Examples:'}
|
|
417
|
+
|
|
418
|
+
#{@pastel.green '$ neocities push .'} Recursively upload current directory.
|
|
419
|
+
|
|
420
|
+
#{@pastel.green '$ neocities push -e node_modules -e secret.txt .'} Exclude certain files from push
|
|
421
|
+
|
|
422
|
+
#{@pastel.green '$ neocities push --no-gitignore .'} Don't use .gitignore to exclude files
|
|
423
|
+
|
|
424
|
+
#{@pastel.green '$ neocities push --ignore-dotfiles .'} Ignore files with '.' at the beginning (for example, '.git/')
|
|
425
|
+
|
|
426
|
+
#{@pastel.green '$ neocities push --dry-run .'} Just show what would be uploaded
|
|
427
|
+
|
|
428
|
+
#{@pastel.green '$ neocities push --optimized .'} Do not upload unchanged files.#{' '}
|
|
429
|
+
|
|
430
|
+
#{@pastel.green '$ neocities push --prune .'} Delete site files not in dir (be careful!)
|
|
431
|
+
|
|
432
|
+
HERE
|
|
433
|
+
exit
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def display_info_help_and_exit
|
|
437
|
+
display_banner
|
|
438
|
+
|
|
439
|
+
puts <<HERE
|
|
440
|
+
#{@pastel.green.bold 'info'} - Get site info
|
|
441
|
+
|
|
442
|
+
#{@pastel.dim 'Examples:'}
|
|
443
|
+
|
|
444
|
+
#{@pastel.green '$ neocities info fauux'} Gets info for 'fauux' site
|
|
445
|
+
|
|
446
|
+
HERE
|
|
447
|
+
exit
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
def display_logout_help_and_exit
|
|
451
|
+
display_banner
|
|
452
|
+
|
|
453
|
+
puts <<HERE
|
|
454
|
+
#{@pastel.green.bold 'logout'} - Remove the site api key from the config
|
|
455
|
+
|
|
456
|
+
#{@pastel.dim 'Examples:'}
|
|
457
|
+
|
|
458
|
+
#{@pastel.green '$ neocities logout -y'}
|
|
459
|
+
|
|
460
|
+
HERE
|
|
461
|
+
exit
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def display_banner
|
|
465
|
+
puts <<HERE
|
|
466
|
+
|
|
467
|
+
|\\---/|
|
|
468
|
+
| #{PENELOPE_EYES.sample}_#{PENELOPE_EYES.sample} | #{@pastel.on_red.bold ' Neocities red '}
|
|
469
|
+
\\_#{PENELOPE_MOUTHS.sample}_/
|
|
470
|
+
|
|
471
|
+
HERE
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def display_help_and_exit
|
|
475
|
+
display_banner
|
|
476
|
+
puts <<HERE
|
|
477
|
+
#{@pastel.dim 'Subcommands:'}
|
|
478
|
+
push Recursively upload a local directory to your site
|
|
479
|
+
upload Upload individual files to your Neocities site
|
|
480
|
+
delete Delete files from your Neocities site
|
|
481
|
+
list List files from your Neocities site
|
|
482
|
+
info Information and stats for your site
|
|
483
|
+
logout Remove the site api key from the config
|
|
484
|
+
version Unceremoniously display version and self destruct
|
|
485
|
+
pull Get the most recent version of files from your site
|
|
486
|
+
pizza Order a free pizza
|
|
487
|
+
|
|
488
|
+
HERE
|
|
489
|
+
exit
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def self.app_config_path(name)
|
|
493
|
+
platform = case RUBY_PLATFORM
|
|
494
|
+
when /win32/
|
|
495
|
+
:win32
|
|
496
|
+
when /darwin/
|
|
497
|
+
:darwin
|
|
498
|
+
when /linux/
|
|
499
|
+
:linux
|
|
500
|
+
else
|
|
501
|
+
:unknown
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
case platform
|
|
505
|
+
when :linux
|
|
506
|
+
return File.join(ENV['XDG_CONFIG_HOME'], name) if ENV['XDG_CONFIG_HOME']
|
|
507
|
+
|
|
508
|
+
File.join(ENV['HOME'], '.config', name) if ENV['HOME']
|
|
509
|
+
when :darwin
|
|
510
|
+
File.join(ENV['HOME'], 'Library', 'Application Support', name)
|
|
511
|
+
else
|
|
512
|
+
# Windows platform detection is weird, just look for the env variables
|
|
513
|
+
return File.join(ENV['LOCALAPPDATA'], name) if ENV['LOCALAPPDATA']
|
|
514
|
+
|
|
515
|
+
return File.join(ENV['USERPROFILE'], 'Local Settings', 'Application Data', name) if ENV['USERPROFILE']
|
|
516
|
+
|
|
517
|
+
# Should work for the BSDs
|
|
518
|
+
File.join(ENV['HOME'], ".#{name}") if ENV['HOME']
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|