nauvisian 0.1.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/.rspec +3 -0
- data/.rubocop.yml +29 -0
- data/.rubocop_todo.yml +26 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +141 -0
- data/LICENSE.txt +21 -0
- data/README.md +55 -0
- data/Rakefile +15 -0
- data/exe/nvsn +7 -0
- data/lib/nauvisian/api.rb +68 -0
- data/lib/nauvisian/cache/file_system.rb +55 -0
- data/lib/nauvisian/cache.rb +3 -0
- data/lib/nauvisian/cli/commands/mod/disable.rb +32 -0
- data/lib/nauvisian/cli/commands/mod/download.rb +34 -0
- data/lib/nauvisian/cli/commands/mod/enable.rb +32 -0
- data/lib/nauvisian/cli/commands/mod/info.rb +39 -0
- data/lib/nauvisian/cli/commands/mod/installed.rb +33 -0
- data/lib/nauvisian/cli/commands/mod/latest.rb +30 -0
- data/lib/nauvisian/cli/commands/mod/settings/dump.rb +30 -0
- data/lib/nauvisian/cli/commands/mod/versions.rb +31 -0
- data/lib/nauvisian/cli/commands/save/mod/list.rb +35 -0
- data/lib/nauvisian/cli/commands/save/mod/sync.rb +99 -0
- data/lib/nauvisian/cli/download_helper.rb +35 -0
- data/lib/nauvisian/cli/lister.rb +66 -0
- data/lib/nauvisian/cli/message_helper.rb +18 -0
- data/lib/nauvisian/cli.rb +36 -0
- data/lib/nauvisian/credential.rb +23 -0
- data/lib/nauvisian/deserializer.rb +96 -0
- data/lib/nauvisian/downloader.rb +57 -0
- data/lib/nauvisian/error.rb +16 -0
- data/lib/nauvisian/mod/detail.rb +15 -0
- data/lib/nauvisian/mod/release.rb +13 -0
- data/lib/nauvisian/mod.rb +20 -0
- data/lib/nauvisian/mod_list.rb +71 -0
- data/lib/nauvisian/mod_settings.rb +46 -0
- data/lib/nauvisian/platform.rb +78 -0
- data/lib/nauvisian/progress/bar.rb +24 -0
- data/lib/nauvisian/progress/null.rb +19 -0
- data/lib/nauvisian/progress.rb +4 -0
- data/lib/nauvisian/save.rb +89 -0
- data/lib/nauvisian/serializer.rb +111 -0
- data/lib/nauvisian/uri/s3.rb +22 -0
- data/lib/nauvisian/version.rb +6 -0
- data/lib/nauvisian/version24.rb +33 -0
- data/lib/nauvisian/version64.rb +33 -0
- data/lib/nauvisian.rb +33 -0
- data/nauvisian.gemspec +45 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e928d3061730068999c84496aec1c8eb57ccc08e143e0fc33bfbd10f5b16c92d
|
4
|
+
data.tar.gz: 5f0a59c8c77bc0d09ac5a34b8661d34f487898183c9e6fe0b5f1f7fb4a5243ba
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 040d1375254e5d5d7d594cb3071c13b28c18ea945b9244c49ca0bb692c7cd4c05199f5be85bb88c67926636e126870d7cd237769b5d1cd56de95c05e758b9e8f
|
7
|
+
data.tar.gz: 61e66892b9b1e54d5a12567b61f205e637c9108fece1c3de80fc08d1140538da67eab97c537810b26f7b547bcface784b7f15d72d5cd01d12164639bbfc17eef
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
inherit_from:
|
2
|
+
- .rubocop/bundler.yml
|
3
|
+
- .rubocop/gemspec.yml
|
4
|
+
- .rubocop/layout.yml
|
5
|
+
- .rubocop/lint.yml
|
6
|
+
- .rubocop/metrics.yml
|
7
|
+
- .rubocop/naming.yml
|
8
|
+
- .rubocop/performance.yml
|
9
|
+
- .rubocop/rspec.yml
|
10
|
+
- .rubocop/security.yml
|
11
|
+
- .rubocop/style.yml
|
12
|
+
- .rubocop_todo.yml
|
13
|
+
|
14
|
+
require:
|
15
|
+
- rubocop-performance
|
16
|
+
- rubocop-rake
|
17
|
+
- rubocop-rspec
|
18
|
+
|
19
|
+
AllCops:
|
20
|
+
DisplayCopNames: true
|
21
|
+
DisplayStyleGuide: true
|
22
|
+
EnabledByDefault: true
|
23
|
+
Exclude:
|
24
|
+
- bin/**/*
|
25
|
+
- vendor/**/*
|
26
|
+
ExtraDetails: true
|
27
|
+
NewCops: enable
|
28
|
+
TargetRubyVersion: 3.2
|
29
|
+
UseCache: true
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Layout/LineLength:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Metrics/AbcSize:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/MethodLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
RSpec/NestedGroups:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
RSpec/ExampleLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
RSpec/MultipleExpectations:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
RSpec/PendingWithoutReason:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/Documentation:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/DocumentationMethod:
|
26
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "typeprof"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :development, :test do
|
12
|
+
gem "debug"
|
13
|
+
gem "rake"
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem "fabrication", require: false
|
18
|
+
gem "faker", require: false
|
19
|
+
gem "rspec", require: false
|
20
|
+
gem "rubocop", require: false
|
21
|
+
gem "rubocop-performance", require: false
|
22
|
+
gem "rubocop-rake", require: false
|
23
|
+
gem "rubocop-rspec", require: false
|
24
|
+
gem "simplecov", require: false
|
25
|
+
gem "webmock", require: false
|
26
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nauvisian (0.1.0)
|
5
|
+
aws-sdk-s3 (~> 1.0)
|
6
|
+
dry-cli (~> 1.0)
|
7
|
+
dry-inflector (~> 1.0)
|
8
|
+
rack (~> 3.0)
|
9
|
+
ruby-progressbar (~> 1.11)
|
10
|
+
rubyzip (~> 2.3)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
addressable (2.8.4)
|
16
|
+
public_suffix (>= 2.0.2, < 6.0)
|
17
|
+
ast (2.4.2)
|
18
|
+
aws-eventstream (1.2.0)
|
19
|
+
aws-partitions (1.765.0)
|
20
|
+
aws-sdk-core (3.172.0)
|
21
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
22
|
+
aws-partitions (~> 1, >= 1.651.0)
|
23
|
+
aws-sigv4 (~> 1.5)
|
24
|
+
jmespath (~> 1, >= 1.6.1)
|
25
|
+
aws-sdk-kms (1.64.0)
|
26
|
+
aws-sdk-core (~> 3, >= 3.165.0)
|
27
|
+
aws-sigv4 (~> 1.1)
|
28
|
+
aws-sdk-s3 (1.122.0)
|
29
|
+
aws-sdk-core (~> 3, >= 3.165.0)
|
30
|
+
aws-sdk-kms (~> 1)
|
31
|
+
aws-sigv4 (~> 1.4)
|
32
|
+
aws-sigv4 (1.5.2)
|
33
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
34
|
+
concurrent-ruby (1.2.2)
|
35
|
+
crack (0.4.5)
|
36
|
+
rexml
|
37
|
+
debug (1.8.0)
|
38
|
+
irb (>= 1.5.0)
|
39
|
+
reline (>= 0.3.1)
|
40
|
+
diff-lcs (1.5.0)
|
41
|
+
docile (1.4.0)
|
42
|
+
dry-cli (1.0.0)
|
43
|
+
dry-inflector (1.0.0)
|
44
|
+
fabrication (2.30.0)
|
45
|
+
faker (3.2.0)
|
46
|
+
i18n (>= 1.8.11, < 2)
|
47
|
+
hashdiff (1.0.1)
|
48
|
+
i18n (1.13.0)
|
49
|
+
concurrent-ruby (~> 1.0)
|
50
|
+
io-console (0.6.0)
|
51
|
+
irb (1.6.4)
|
52
|
+
reline (>= 0.3.0)
|
53
|
+
jmespath (1.6.2)
|
54
|
+
json (2.6.3)
|
55
|
+
parallel (1.23.0)
|
56
|
+
parser (3.2.2.1)
|
57
|
+
ast (~> 2.4.1)
|
58
|
+
public_suffix (5.0.1)
|
59
|
+
rack (3.0.7)
|
60
|
+
rainbow (3.1.1)
|
61
|
+
rake (13.0.6)
|
62
|
+
rbs (3.1.0)
|
63
|
+
regexp_parser (2.8.0)
|
64
|
+
reline (0.3.3)
|
65
|
+
io-console (~> 0.5)
|
66
|
+
rexml (3.2.5)
|
67
|
+
rspec (3.12.0)
|
68
|
+
rspec-core (~> 3.12.0)
|
69
|
+
rspec-expectations (~> 3.12.0)
|
70
|
+
rspec-mocks (~> 3.12.0)
|
71
|
+
rspec-core (3.12.2)
|
72
|
+
rspec-support (~> 3.12.0)
|
73
|
+
rspec-expectations (3.12.3)
|
74
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
75
|
+
rspec-support (~> 3.12.0)
|
76
|
+
rspec-mocks (3.12.5)
|
77
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
78
|
+
rspec-support (~> 3.12.0)
|
79
|
+
rspec-support (3.12.0)
|
80
|
+
rubocop (1.51.0)
|
81
|
+
json (~> 2.3)
|
82
|
+
parallel (~> 1.10)
|
83
|
+
parser (>= 3.2.0.0)
|
84
|
+
rainbow (>= 2.2.2, < 4.0)
|
85
|
+
regexp_parser (>= 1.8, < 3.0)
|
86
|
+
rexml (>= 3.2.5, < 4.0)
|
87
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
88
|
+
ruby-progressbar (~> 1.7)
|
89
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
90
|
+
rubocop-ast (1.28.1)
|
91
|
+
parser (>= 3.2.1.0)
|
92
|
+
rubocop-capybara (2.18.0)
|
93
|
+
rubocop (~> 1.41)
|
94
|
+
rubocop-factory_bot (2.22.0)
|
95
|
+
rubocop (~> 1.33)
|
96
|
+
rubocop-performance (1.17.1)
|
97
|
+
rubocop (>= 1.7.0, < 2.0)
|
98
|
+
rubocop-ast (>= 0.4.0)
|
99
|
+
rubocop-rake (0.6.0)
|
100
|
+
rubocop (~> 1.0)
|
101
|
+
rubocop-rspec (2.22.0)
|
102
|
+
rubocop (~> 1.33)
|
103
|
+
rubocop-capybara (~> 2.17)
|
104
|
+
rubocop-factory_bot (~> 2.22)
|
105
|
+
ruby-progressbar (1.13.0)
|
106
|
+
rubyzip (2.3.2)
|
107
|
+
simplecov (0.22.0)
|
108
|
+
docile (~> 1.1)
|
109
|
+
simplecov-html (~> 0.11)
|
110
|
+
simplecov_json_formatter (~> 0.1)
|
111
|
+
simplecov-html (0.12.3)
|
112
|
+
simplecov_json_formatter (0.1.4)
|
113
|
+
typeprof (0.21.7)
|
114
|
+
rbs (>= 1.8.1)
|
115
|
+
unicode-display_width (2.4.2)
|
116
|
+
webmock (3.18.1)
|
117
|
+
addressable (>= 2.8.0)
|
118
|
+
crack (>= 0.3.2)
|
119
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
120
|
+
|
121
|
+
PLATFORMS
|
122
|
+
arm64-darwin-21
|
123
|
+
x86_64-linux
|
124
|
+
|
125
|
+
DEPENDENCIES
|
126
|
+
debug
|
127
|
+
fabrication
|
128
|
+
faker
|
129
|
+
nauvisian!
|
130
|
+
rake
|
131
|
+
rspec
|
132
|
+
rubocop
|
133
|
+
rubocop-performance
|
134
|
+
rubocop-rake
|
135
|
+
rubocop-rspec
|
136
|
+
simplecov
|
137
|
+
typeprof
|
138
|
+
webmock
|
139
|
+
|
140
|
+
BUNDLED WITH
|
141
|
+
2.4.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 OZAWA Sakuro
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Nauvisian
|
2
|
+
|
3
|
+
A library and CLI tool for the management of [Factorio](https://factorio.com) MODs and saves.
|
4
|
+
|
5
|
+
It eases downloading MODs, enabling/disabling locally installed MODs and synchroning MODs and settings with save files.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
10
|
+
|
11
|
+
$ bundle add nauvisian
|
12
|
+
|
13
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
14
|
+
|
15
|
+
$ gem install nauvisian
|
16
|
+
|
17
|
+
## CLI Usage
|
18
|
+
|
19
|
+
- `nvsn mod disable MOD`
|
20
|
+
Disable an installed MOD
|
21
|
+
- `nvsn mod download MOD` 🔐
|
22
|
+
Download a MOD to the current directory
|
23
|
+
- `nvsn mod enable MOD`
|
24
|
+
Enable an installed MOD
|
25
|
+
- `nvsn mod info MOD` 🖧
|
26
|
+
Show info of MOD
|
27
|
+
- `nvsn mod installed`
|
28
|
+
List installed MODs
|
29
|
+
- `nvsn mod latest MOD` 🖧
|
30
|
+
Show the latest version of MOD
|
31
|
+
- `nvsn mod versions MOD` 🖧
|
32
|
+
List available versions of MOD
|
33
|
+
- `nvsn mod settings dump`
|
34
|
+
Dump MOD settings
|
35
|
+
- `nvsn save mod list SAVE`
|
36
|
+
List MODs used in the given SAVE
|
37
|
+
- `nvsn save mod sync SAVE` 🔐
|
38
|
+
Synchronize MODs and startup settings with the given SAVE
|
39
|
+
|
40
|
+
For options recognized by the commands above, try the command with `--help`.
|
41
|
+
|
42
|
+
- Commands with 🔐 requires the credenail information generally found in your `player-data.json`
|
43
|
+
- Commands with 🖧 accesses MOD portal's public API
|
44
|
+
|
45
|
+
## Development
|
46
|
+
|
47
|
+
After checking out the repo, run `bin/setup` to install dependencies. It also copies currently installed MODs and saves into the workspace.
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sakuro/nauvisian.
|
52
|
+
|
53
|
+
## License
|
54
|
+
|
55
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/clean"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "rubocop/rake_task"
|
7
|
+
|
8
|
+
CLEAN.add("coverage")
|
9
|
+
CLEAN.add(".rspec_status")
|
10
|
+
CLOBBER.add("*.zip")
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new(:spec)
|
13
|
+
RuboCop::RakeTask.new
|
14
|
+
|
15
|
+
task default: %i[spec rubocop]
|
data/exe/nvsn
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "open-uri"
|
5
|
+
|
6
|
+
require "rack/utils"
|
7
|
+
|
8
|
+
require "nauvisian/error"
|
9
|
+
|
10
|
+
module Nauvisian
|
11
|
+
# Mod Portal API
|
12
|
+
# https://wiki.factorio.com/Mod_portal_API
|
13
|
+
class API
|
14
|
+
class Error < Nauvisian::Error; end
|
15
|
+
|
16
|
+
MOD_PORTAL_ENDPOINT_URI = URI("https://mods.factorio.com").freeze
|
17
|
+
private_constant :MOD_PORTAL_ENDPOINT_URI
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@cache = Nauvisian::Cache::FileSystem.new(name: "api")
|
21
|
+
end
|
22
|
+
|
23
|
+
def detail(mod)
|
24
|
+
with_error_handling(mod) do
|
25
|
+
path = "/api/mods/#{mod.name}/full"
|
26
|
+
raw_data = get(path)
|
27
|
+
data = raw_data.slice(:downloads_count, :name, :owner, :summary, :title, :category, :description)
|
28
|
+
Nauvisian::Mod::Detail[created_at: Time.parse(raw_data[:created_at]), **data]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def releases(mod)
|
33
|
+
with_error_handling(mod) do
|
34
|
+
path = "/api/mods/#{mod.name}"
|
35
|
+
raw_data = get(path)
|
36
|
+
parse_releases(raw_data[:releases], mod:)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private def with_error_handling(mod)
|
41
|
+
yield
|
42
|
+
rescue OpenURI::HTTPError => e
|
43
|
+
case e.io.status
|
44
|
+
in ["404", _]
|
45
|
+
raise Nauvisian::ModNotFound, mod
|
46
|
+
else
|
47
|
+
raise Nauvisian::API::Error, e.io.status
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private def parse_releases(raw_releases, mod:)
|
52
|
+
raw_releases.map do |raw_release|
|
53
|
+
data = raw_release.slice(:file_name, :sha1)
|
54
|
+
data[:download_url] = MOD_PORTAL_ENDPOINT_URI + raw_release[:download_url]
|
55
|
+
data[:version] = Nauvisian::Version24[raw_release[:version]]
|
56
|
+
data[:released_at] = Time.parse(raw_release[:released_at])
|
57
|
+
Nauvisian::Mod::Release[mod:, **data]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private def get(path, **params)
|
62
|
+
request_url = MOD_PORTAL_ENDPOINT_URI + path
|
63
|
+
request_url.query = Rack::Utils.build_nested_query(params)
|
64
|
+
data = @cache.fetch(request_url) { request_url.read }
|
65
|
+
JSON.parse(data, symbolize_names: true)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/md5"
|
4
|
+
require "pathname"
|
5
|
+
|
6
|
+
module Nauvisian
|
7
|
+
module Cache
|
8
|
+
class FileSystem
|
9
|
+
MINIMUM_TTL = 5 * 60 # 5 minutes
|
10
|
+
private_constant :MINIMUM_TTL
|
11
|
+
|
12
|
+
def self.cache_root
|
13
|
+
Pathname(ENV.fetch("XDG_CACHE_HOME", Nauvisian.platform.home_directory / ".cache")) / "nauvisian"
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(name:, ttl: MINIMUM_TTL)
|
17
|
+
raise ArgumentError, "ttl is too small (must be >= #{MINIMUM_TTL})" if ttl < MINIMUM_TTL
|
18
|
+
|
19
|
+
@cache_directory = self.class.cache_root / name
|
20
|
+
@ttl = ttl
|
21
|
+
end
|
22
|
+
|
23
|
+
private attr_reader :root
|
24
|
+
|
25
|
+
def fetch(key)
|
26
|
+
path = generate_path(key)
|
27
|
+
return path.binread if path.exist? && !stale?(path, Time.now)
|
28
|
+
|
29
|
+
yield.tap {|content| store(path, content) }
|
30
|
+
end
|
31
|
+
|
32
|
+
private def generate_path(key)
|
33
|
+
digest = Digest::MD5.hexdigest(key.to_s)
|
34
|
+
@cache_directory.join(digest[0..1], digest[2..3], digest[4..])
|
35
|
+
end
|
36
|
+
|
37
|
+
private def stale?(path, time)
|
38
|
+
time - path.mtime > @ttl
|
39
|
+
end
|
40
|
+
|
41
|
+
private def store(path, content)
|
42
|
+
dir = path.dirname
|
43
|
+
dir.mkpath
|
44
|
+
|
45
|
+
# Store into a temporary file
|
46
|
+
tmp = Tempfile.create(".cache-", dir, mode: IO::BINARY | IO::CREAT)
|
47
|
+
tmp.write(content)
|
48
|
+
tmp.close
|
49
|
+
|
50
|
+
# Rename to the desired path
|
51
|
+
File.rename(tmp.path, path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../message_helper"
|
4
|
+
|
5
|
+
module Nauvisian
|
6
|
+
module CLI
|
7
|
+
module Commands
|
8
|
+
module Mod
|
9
|
+
class Disable < Dry::CLI::Command
|
10
|
+
include MessageHelper
|
11
|
+
|
12
|
+
desc "Disable an installed MOD"
|
13
|
+
argument :mod, desc: "Target MOD", required: true
|
14
|
+
|
15
|
+
option :mod_directory, desc: "Directory where MODs are installed", required: false, default: Nauvisian.platform.mod_directory.to_s
|
16
|
+
|
17
|
+
def call(mod:, **options)
|
18
|
+
mod_directory = Pathname(options[:mod_directory])
|
19
|
+
mod_list_path = mod_directory / "mod-list.json"
|
20
|
+
list = Nauvisian::ModList.load(mod_list_path)
|
21
|
+
mod = Nauvisian::Mod[name: mod]
|
22
|
+
list.disable(mod)
|
23
|
+
list.save(mod_list_path)
|
24
|
+
rescue Nauvisian::ModNotFound
|
25
|
+
message "❌ You can't disable a MOD which is not in the MOD list (#{mod.name})"
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../download_helper"
|
4
|
+
require_relative "../../message_helper"
|
5
|
+
|
6
|
+
module Nauvisian
|
7
|
+
module CLI
|
8
|
+
module Commands
|
9
|
+
module Mod
|
10
|
+
class Download < Dry::CLI::Command
|
11
|
+
include DownloadHelper
|
12
|
+
include MessageHelper
|
13
|
+
|
14
|
+
desc "Download a MOD to the current directory"
|
15
|
+
argument :mod, desc: "Target MOD", required: true
|
16
|
+
option :version, desc: "Version to download (default: latest)"
|
17
|
+
option :user, desc: "The user at MOD Portal"
|
18
|
+
option :token, desc: "The token at MOD Portal"
|
19
|
+
|
20
|
+
def call(mod:, **options)
|
21
|
+
credential = find_credential(**options.slice(:user, :token))
|
22
|
+
release = find_release(Nauvisian::Mod[name: mod], version: options.key?(:version) ? Nauvisian::Version24[options[:version]] : nil)
|
23
|
+
|
24
|
+
downloader = Nauvisian::Downloader.new(credential:, progress: Nauvisian::Progress::Bar)
|
25
|
+
downloader.download(release, release.file_name)
|
26
|
+
rescue => e
|
27
|
+
message(e)
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../message_helper"
|
4
|
+
|
5
|
+
module Nauvisian
|
6
|
+
module CLI
|
7
|
+
module Commands
|
8
|
+
module Mod
|
9
|
+
class Enable < Dry::CLI::Command
|
10
|
+
include MessageHelper
|
11
|
+
|
12
|
+
desc "Enable an installed MOD"
|
13
|
+
argument :mod, desc: "Target MOD", required: true
|
14
|
+
|
15
|
+
option :mod_directory, desc: "Directory where MODs are installed", required: false, default: Nauvisian.platform.mod_directory.to_s
|
16
|
+
|
17
|
+
def call(mod:, **options)
|
18
|
+
mod_directory = Pathname(options[:mod_directory])
|
19
|
+
mod_list_path = mod_directory / "mod-list.json"
|
20
|
+
list = Nauvisian::ModList.load(mod_list_path)
|
21
|
+
mod = Nauvisian::Mod[name: mod]
|
22
|
+
list.enable(mod)
|
23
|
+
list.save(mod_list_path)
|
24
|
+
rescue Nauvisian::ModNotFound
|
25
|
+
message "❌ You can't enable a MOD which is not in the MOD list (#{mod.name})"
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../message_helper"
|
4
|
+
|
5
|
+
module Nauvisian
|
6
|
+
module CLI
|
7
|
+
module Commands
|
8
|
+
module Mod
|
9
|
+
class Info < Dry::CLI::Command
|
10
|
+
include MessageHelper
|
11
|
+
|
12
|
+
desc "Show info of MOD"
|
13
|
+
argument :mod, desc: "Target MOD", required: true
|
14
|
+
|
15
|
+
def call(mod:, **)
|
16
|
+
api = Nauvisian::API.new
|
17
|
+
mod = Nauvisian::Mod[name: mod]
|
18
|
+
detail = api.detail(mod)
|
19
|
+
|
20
|
+
puts <<~DETAIL
|
21
|
+
Name: #{detail.name}
|
22
|
+
Category: #{detail.category}
|
23
|
+
Downloads: #{detail.downloads_count}
|
24
|
+
URL: #{detail.url}
|
25
|
+
Title: #{detail.title}
|
26
|
+
Summary: #{detail.summary}
|
27
|
+
Owner: #{detail.owner}
|
28
|
+
Created at: #{detail.created_at}
|
29
|
+
Description: #{detail.description}
|
30
|
+
DETAIL
|
31
|
+
rescue => e
|
32
|
+
message(e)
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../lister"
|
4
|
+
require_relative "../../message_helper"
|
5
|
+
|
6
|
+
module Nauvisian
|
7
|
+
module CLI
|
8
|
+
module Commands
|
9
|
+
module Mod
|
10
|
+
class Installed < Dry::CLI::Command
|
11
|
+
include MessageHelper
|
12
|
+
|
13
|
+
desc "List installed MODs"
|
14
|
+
option :format, default: "plain", values: Nauvisian::CLI::Lister.all, desc: "Output format"
|
15
|
+
option :mod_directory, desc: "Directory where MODs are installed", required: false, default: Nauvisian.platform.mod_directory.to_s
|
16
|
+
|
17
|
+
def call(*, **options)
|
18
|
+
mod_directory = Pathname(options[:mod_directory])
|
19
|
+
mod_list_path = mod_directory / "mod-list.json"
|
20
|
+
mods = Nauvisian::ModList.load(mod_list_path).sort
|
21
|
+
rows = mods.map {|mod, enabled| {"Name" => mod.name, "Enabled" => enabled} }
|
22
|
+
|
23
|
+
lister = Nauvisian::CLI::Lister.for(options[:format].to_sym).new(%w(Name Enabled))
|
24
|
+
lister.list(rows)
|
25
|
+
rescue => e
|
26
|
+
message(e)
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../message_helper"
|
4
|
+
|
5
|
+
module Nauvisian
|
6
|
+
module CLI
|
7
|
+
module Commands
|
8
|
+
module Mod
|
9
|
+
class Latest < Dry::CLI::Command
|
10
|
+
include MessageHelper
|
11
|
+
|
12
|
+
desc "Show the latest version of MOD"
|
13
|
+
argument :mod, desc: "Target MOD", required: true
|
14
|
+
|
15
|
+
def call(mod:, **)
|
16
|
+
api = Nauvisian::API.new
|
17
|
+
mod = Nauvisian::Mod[name: mod]
|
18
|
+
releases = api.releases(mod)
|
19
|
+
latest = releases.max_by(&:released_at)
|
20
|
+
|
21
|
+
puts latest.version
|
22
|
+
rescue => e
|
23
|
+
message(e)
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|