Icarus-Mod-Tools 1.3.5 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28209aff7606ef684d02fae74f71d498986d7d2f9d1628a84bc32dd2670c6515
4
- data.tar.gz: 26264df40cf51c3f13255262669b4615387f90010a3fec39be407c3cf3c1719b
3
+ metadata.gz: 454c2e99f2453a91be33c028cc37cdd9316527aa45aac5f991f289a1e66c7d59
4
+ data.tar.gz: fdd4d5721b78a638f61be06585bb51679472e17ce8085ea4960340aa0f0ddab4
5
5
  SHA512:
6
- metadata.gz: 32b1496f4423e4ad71231b4311061c2baf8f4d053ebbfb3f8461871b1482b589fb4f15defe272da98794157b7ca14b92f9af45c271dedccad5a2dd806078762d
7
- data.tar.gz: bc14687a8e9c9217e486c48f89b63094250119e0d9494027873a56c97daa00b73b2f39315b25cdd413ea2d92cbdfc1da8355276834ea86e4389dbe1af8cab4b8
6
+ metadata.gz: 22ca382cfd35209e8ee6cdf883bdbd51098a7e159c5dfb5bf3f5afdc1a89656989338bf5a3bd1e3df9e4911deef342b4260b63aa4b18c42bd68afff0eddcd511
7
+ data.tar.gz: 99fa6667462a2f5d6e509bb918da9f76bebcde5bf89c41acc9809a1b726251aa189cd37a7d841585534280b4fbfa37c6ad29f8044dcd1a84f871590c53523d78
data/.rubocop.yml CHANGED
@@ -47,3 +47,6 @@ RSpec/MultipleMemoizedHelpers:
47
47
  Style/Documentation:
48
48
  Exclude:
49
49
  - lib/icarus/mod/cli/*.rb # Thor command files
50
+
51
+ Style/OpenStructUse:
52
+ Enabled: false
data/CHANGES.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## History (reverse chronological order)
6
6
 
7
+ ### v1.4 - 2023-03
8
+
9
+ **BREAKING CHANGES!**
10
+
11
+ You'll need to move your ENV variables to a config file. See the README for more details.
12
+
13
+ - Read configuration from `~/.imtconfig.json`
14
+ - bugfixes
15
+
7
16
  ### v1.3 - 2023-02
8
17
 
9
18
  - First public release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- Icarus-Mod-Tools (1.3.5)
4
+ Icarus-Mod-Tools (1.4.0)
5
5
  google-cloud-firestore (~> 2.7)
6
6
  octokit (~> 6.0)
7
7
  thor (~> 1.2)
data/README.md CHANGED
@@ -2,22 +2,49 @@
2
2
 
3
3
  a CLI tool for managing the Icarus Mods Database
4
4
 
5
- ## Installation
5
+ ## Requirements
6
6
 
7
- `gem install icarus-mod-tools`
7
+ To use this app, you'll need to obtain the following:
8
8
 
9
- To use this app, you'll need to obtain and create the following ENV environment variables:
10
-
11
- ```sh
12
- export GITHUB_TOKEN=your_github_token
13
- export GOOGLE_APPLICATION_CREDENTIALS="path/to/your/Google-keyfile"
14
- ```
9
+ - A Github ACCESS_TOKEN (doesn't need access to any repos, this is used purely to make API calls)
10
+ - A Google Cloud Platform credentials `keyfile.json`
11
+ - Ruby 3.1 (or greater)
15
12
 
16
13
  If you aren't sure how to obtain these credentials, please see:
17
14
 
18
15
  - [Google Cloud Platform](https://cloud.google.com/docs/authentication/getting-started)
19
16
  - [GitHub](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
20
17
 
18
+ I _highly_ recommend using WSL2 on Windows, or a Linux distro on your machine. This app has not been tested on Windows.
19
+
20
+ ## Installation
21
+
22
+ `gem install Icarus-Mod-Tools`
23
+
24
+ ## Configuration
25
+
26
+ Create a file called `.imtconfig.json` in your home directory with the following, replacing the CAPITALIZED values with the values provided by the above links:
27
+
28
+ ```json
29
+ {
30
+ "firebase": {
31
+ "credentials": {
32
+ "copy your Google Cloud Platform keyfile.json here and remove this line": null
33
+ },
34
+ "collections": {
35
+ "modinfo": "meta/modinfo",
36
+ "repositories": "meta/repos",
37
+ "mods": "mods"
38
+ }
39
+ },
40
+ "github": {
41
+ "token": "YOUR-GITHUB-TOKEN"
42
+ }
43
+ }
44
+ ```
45
+
46
+ _Hint: Copy the contents of your Google Cloud Platform `keyfile.json` into the `credentials` section of the above file._
47
+
21
48
  ## Usage
22
49
 
23
50
  imt [options] [command]
data/exe/imt CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "cli/base"
4
+ require "cli/command"
5
5
 
6
- Icarus::Mod::CLI::Base.start
6
+ Icarus::Mod::CLI::Command.start
@@ -0,0 +1,24 @@
1
+ {
2
+ "firebase": {
3
+ "credentials": {
4
+ "type": "service_account",
5
+ "project_id": "projectdaedalus-fb09f",
6
+ "private_key_id": "YOUR-PRIVATE-KEY-ID",
7
+ "private_key": "YOUR-PRIVATE-KEY",
8
+ "client_email": "YOUR-CLIENT-EMAIL",
9
+ "client_id": "YOUR-CLIENT-ID",
10
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
11
+ "token_uri": "https://oauth2.googleapis.com/token",
12
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
13
+ "client_x509_cert_url": "YOUR-x509-CERT-URL"
14
+ },
15
+ "collections": {
16
+ "modinfo": "meta/modinfo",
17
+ "repositories": "meta/repos",
18
+ "mods": "mods"
19
+ }
20
+ },
21
+ "github": {
22
+ "token": "YOUR-GITHUB-TOKEN"
23
+ }
24
+ }
@@ -6,7 +6,7 @@ module Icarus
6
6
  module Mod
7
7
  module CLI
8
8
  # Sync CLI command definitions
9
- class Add < SubCommandBase
9
+ class Add < SubcommandBase
10
10
  desc "modinfo", "Adds an entry to 'meta/modinfo/list'"
11
11
  def modinfo(item)
12
12
  firestore = Firestore.new
@@ -7,66 +7,19 @@ require "thor"
7
7
  module Icarus
8
8
  module Mod
9
9
  module CLI
10
- # Base class for all subcommands
11
- class SubCommandBase < Thor
12
- class_option :verbose,
13
- aliases: "-v",
14
- type: :boolean,
15
- repeatable: true,
16
- default: [true],
17
- desc: "Increase verbosity. May be repeated for even more verbosity."
18
-
19
- no_commands do
20
- def check_false
21
- options[:verbose] = [] if options[:verbose].include?(false)
22
- end
23
-
24
- def verbose
25
- check_false
26
- options[:verbose]&.count || 0
27
- end
28
-
29
- def verbose?
30
- check_false
31
- options[:verbose]&.count&.positive?
32
- end
33
- end
34
-
35
- def self.banner(command, _namespace = nil, _subcommand = false) # rubocop:disable Style/OptionalBooleanParameter
36
- "#{basename} #{subcommand_prefix} #{command.usage}"
37
- end
38
-
39
- def self.subcommand_prefix
40
- name.gsub(/.*::/, "").gsub(/^[A-Z]/) { |match| match[0].downcase }.gsub(/[A-Z]/) { |match| "-#{match[0].downcase}" }
41
- end
42
- end
10
+ # The Base CLI class for Icarus Mod Tools. This is inherited by all subcommands.
11
+ class Base < Thor
12
+ class_option :config,
13
+ aliases: "-C", type: :string, default: File.join(Dir.home, "/.imtconfig.json"),
14
+ desc: "Path to the config file"
43
15
 
44
- # Require subcommands after the SubCommandBase class is defined
45
- require "cli/sync"
46
- require "cli/list"
47
- require "cli/add"
16
+ class_option :version,
17
+ aliases: "-V", type: :boolean,
18
+ desc: "Print the version and exit"
48
19
 
49
- # The main CLI for Icarus Mod Tools
50
- class Base < Thor
51
20
  def self.exit_on_failure?
52
21
  true
53
22
  end
54
-
55
- map %w[--version -V] => :__print_version
56
-
57
- desc "--version, -V", "print the version and exit"
58
- def __print_version
59
- puts "IcarusModTool (imt) v#{Icarus::Mod::VERSION}"
60
- end
61
-
62
- desc "sync", "Syncs the databases"
63
- subcommand "sync", Sync
64
-
65
- desc "list", "Lists the databases"
66
- subcommand "list", List
67
-
68
- desc "add", "Adds entries to the databases"
69
- subcommand "add", Add
70
23
  end
71
24
  end
72
25
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cli/base"
4
+ require "cli/subcommand_base"
5
+ require "cli/sync"
6
+ require "cli/list"
7
+ require "cli/add"
8
+
9
+ module Icarus
10
+ module Mod
11
+ module CLI
12
+ # The main CLI Command class for Icarus Mod Tools
13
+ class Command < Base
14
+ def initialize(*args)
15
+ super
16
+
17
+ if options[:version]
18
+ puts "IcarusModTool (imt) v#{Icarus::Mod::VERSION}"
19
+ exit 0
20
+ end
21
+
22
+ unless File.exist?(options[:config])
23
+ warn "Could not find or read Config from '#{options[:config]}' - please create it or specify a different path with -C"
24
+ exit 1
25
+ end
26
+
27
+ Icarus::Mod::Config.read(options[:config])
28
+ end
29
+
30
+ desc "sync", "Syncs the databases"
31
+ subcommand "sync", Sync
32
+
33
+ desc "list", "Lists the databases"
34
+ subcommand "list", List
35
+
36
+ desc "add", "Adds entries to the databases"
37
+ subcommand "add", Add
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,15 +7,19 @@ module Icarus
7
7
  module Mod
8
8
  module CLI
9
9
  # Sync CLI command definitions
10
- class List < SubCommandBase
10
+ class List < SubcommandBase
11
11
  desc "modinfo", "Displays data from 'meta/modinfo/list'"
12
12
  def modinfo
13
- puts Firestore.new.list(:modinfo)
13
+ modinfos = Firestore.new.list(:modinfo)
14
+ puts modinfos
15
+ puts "Total: #{modinfos.count}" if verbose > 1
14
16
  end
15
17
 
16
18
  desc "repos", "Displays data from 'meta/repos/list'"
17
19
  def repos
18
- puts Firestore.new.list(:repositories)
20
+ repos = Firestore.new.list(:repositories)
21
+ puts repos
22
+ puts "Total: #{repos.count}" if verbose > 1
19
23
  end
20
24
 
21
25
  desc "mods", "Displays data from 'mods'"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cli/base"
4
+
5
+ module Icarus
6
+ module Mod
7
+ module CLI
8
+ # Base class for all subcommands
9
+ class SubcommandBase < Base
10
+ class_option :verbose,
11
+ aliases: "-v", type: :boolean, repeatable: true, default: [true],
12
+ desc: "Increase verbosity. May be repeated for even more verbosity."
13
+
14
+ no_commands do
15
+ def check_false
16
+ options[:verbose] = [] if options[:verbose].include?(false)
17
+ end
18
+
19
+ def verbose
20
+ check_false
21
+ options[:verbose]&.count || 0
22
+ end
23
+
24
+ def verbose?
25
+ check_false
26
+ options[:verbose]&.count&.positive?
27
+ end
28
+ end
29
+
30
+ # rubocop:disable Style/OptionalBooleanParameter
31
+ def self.banner(command, _namespace = nil, _subcommand = false)
32
+ "#{basename} #{subcommand_prefix} #{command.usage}"
33
+ end
34
+ # rubocop:enable Style/OptionalBooleanParameter
35
+
36
+ def self.subcommand_prefix
37
+ name.gsub(/.*::/, "").gsub(/^[A-Z]/) { |match| match[0].downcase }.gsub(/[A-Z]/) { |match| "-#{match[0].downcase}" }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -7,7 +7,7 @@ module Icarus
7
7
  module Mod
8
8
  module CLI
9
9
  # Sync CLI command definitions
10
- class Sync < SubCommandBase
10
+ class Sync < SubcommandBase
11
11
  desc "modinfo", "Reads from 'meta/repos/list' and Syncs any modinfo files we find (github only for now)"
12
12
  def modinfo
13
13
  modinfo_sync = Icarus::Mod::Tools::ModinfoSync.new
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Icarus
6
+ module Mod
7
+ # Reads the configuration file
8
+ class Config
9
+ class << self
10
+ def config
11
+ return @config if @config
12
+
13
+ read
14
+ end
15
+
16
+ def read(config_file = self.config_file)
17
+ @config = JSON.parse(File.read(config_file), object_class: OpenStruct)
18
+ end
19
+
20
+ def firebase
21
+ @config.firebase
22
+ end
23
+
24
+ def github
25
+ @config.github
26
+ end
27
+
28
+ private
29
+
30
+ def config_file
31
+ @config_file ||= File.join(Dir.home, "/.imtconfig.json")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -7,16 +7,11 @@ module Icarus
7
7
  module Mod
8
8
  # Helper methods for interacting with the Firestore API
9
9
  class Firestore
10
- attr_reader :client
11
-
12
- COLLECTIONS = {
13
- modinfo: "meta/modinfo",
14
- repositories: "meta/repos",
15
- mods: "mods"
16
- }.freeze
10
+ attr_reader :client, :collections
17
11
 
18
12
  def initialize
19
- @client = Google::Cloud::Firestore.new(project_id: "projectdaedalus-fb09f", credentials: ENV.fetch("GOOGLE_APPLICATION_CREDENTIALS", nil))
13
+ @client = Google::Cloud::Firestore.new(credentials: Config.firebase.credentials.to_h)
14
+ @collections = Config.firebase.collections
20
15
  end
21
16
 
22
17
  def repos
@@ -31,18 +26,18 @@ module Icarus
31
26
  @mods ||= list(:mods)
32
27
  end
33
28
 
34
- def find_mod(field, value)
35
- mods.find { |mod| mod.send(field) == value }
29
+ def find_mod(name:, author:)
30
+ mods.find { |mod| mod.name == name && mod.author == author }
36
31
  end
37
32
 
38
33
  def list(type)
39
34
  case type
40
35
  when :modinfo
41
- @client.doc(COLLECTIONS[:modinfo]).get[:list]
36
+ @client.doc(collections.modinfo).get[:list]
42
37
  when :repositories
43
- @client.doc(COLLECTIONS[:repositories]).get[:list]
38
+ @client.doc(collections.repositories).get[:list]
44
39
  when :mods
45
- @client.col(COLLECTIONS[:mods]).get.map do |doc|
40
+ @client.col(collections.mods).get.map do |doc|
46
41
  Icarus::Mod::Tools::Modinfo.new(doc.data, id: doc.document_id, created: doc.create_time, updated: doc.update_time)
47
42
  end
48
43
  else
@@ -51,11 +46,11 @@ module Icarus
51
46
  end
52
47
 
53
48
  def update_or_create_mod(payload, merge:)
54
- doc_id = payload.id || find_mod(:name, payload.name)&.id
49
+ doc_id = payload.id || find_mod(name: payload.name, author: payload.author)&.id
55
50
 
56
- return @client.doc("#{COLLECTIONS[:mods]}/#{doc_id}").set(payload.to_h, merge:) if doc_id
51
+ return @client.doc("#{collections.mods}/#{doc_id}").set(payload.to_h, merge:) if doc_id
57
52
 
58
- @client.col(COLLECTIONS[:mods]).add(payload.to_h)
53
+ @client.col(collections.mods).add(payload.to_h)
59
54
  end
60
55
 
61
56
  def update(type, payload, merge: false)
@@ -64,9 +59,9 @@ module Icarus
64
59
  case type
65
60
  when :modinfo
66
61
  update_array = (modinfo_array + [payload]).flatten.uniq
67
- response = @client.doc(COLLECTIONS[:modinfo]).set({ list: update_array }, merge:) if update_array.any?
62
+ response = @client.doc(collections.modinfo).set({ list: update_array }, merge:) if update_array.any?
68
63
  when :repositories
69
- response = @client.doc(COLLECTIONS[:repositories]).set({ list: payload }, merge:)
64
+ response = @client.doc(collections.repositories).set({ list: payload }, merge:)
70
65
  when :mod
71
66
  response = update_or_create_mod(payload, merge:)
72
67
  else
@@ -79,7 +74,7 @@ module Icarus
79
74
  def delete(type, payload)
80
75
  case type
81
76
  when :mod
82
- response = @client.doc("#{COLLECTIONS[:mods]}/#{payload.id}").delete
77
+ response = @client.doc("#{collections.mods}/#{payload.id}").delete
83
78
  else
84
79
  raise "Invalid type: #{type}"
85
80
  end
@@ -10,7 +10,7 @@ module Icarus
10
10
 
11
11
  def initialize(repo = nil)
12
12
  self.repository = repo if repo
13
- @client = Octokit::Client.new(access_token: ENV.fetch("GITHUB_TOKEN", nil))
13
+ @client = Octokit::Client.new(access_token: Config.github.token)
14
14
  @resources = []
15
15
  end
16
16
 
@@ -28,7 +28,7 @@ module Icarus
28
28
  end
29
29
 
30
30
  def find_mod(modinfo)
31
- @firestore.find_mod(:name, modinfo.name)&.id
31
+ @firestore.find_mod(name: modinfo.name, author: modinfo.author)&.id
32
32
  end
33
33
 
34
34
  def find_modinfo(modinfo)
@@ -20,6 +20,12 @@ module Icarus
20
20
  @data = data.is_a?(String) ? JSON.parse(data, symbolize_names: true) : data
21
21
  end
22
22
 
23
+ # rubocop:disable Naming/MethodName
24
+ def fileType
25
+ @data[:fileType] || "pak"
26
+ end
27
+ # rubocop:enable Naming/MethodName
28
+
23
29
  def to_json(*args)
24
30
  JSON.generate(@data, *args)
25
31
  end
@@ -28,13 +34,6 @@ module Icarus
28
34
  @data || {}
29
35
  end
30
36
 
31
- def to_s
32
- format(
33
- "%-<name>30s %-<author>20s v%-<version>10s %<description>s",
34
- name:, author:, version: (version || "None"), description:
35
- )
36
- end
37
-
38
37
  def method_missing(method_name, *_args, &)
39
38
  to_h[method_name.to_sym]&.strip
40
39
  end
@@ -7,14 +7,14 @@ require "json"
7
7
  module Icarus
8
8
  module Mod
9
9
  module Tools
10
+ class RequestFailed < StandardError; end
11
+
10
12
  # Sync helper methods
11
13
  module SyncHelpers
12
- class RequestFailed < StandardError; end
13
-
14
14
  def retrieve_from_url(url)
15
15
  res = Net::HTTP.get_response(URI(url))
16
16
 
17
- raise RequestFailed, "HTTP Request failed for #{url} (#{res.code}): #{res.message}" unless res&.code == "200"
17
+ raise Icarus::Mod::Tools::RequestFailed, "HTTP Request failed for #{url} (#{res.code}): #{res.message}" unless res&.code == "200"
18
18
 
19
19
  JSON.parse(res.body, symbolize_names: true)
20
20
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "firestore"
4
- require "github"
3
+ require "config"
5
4
 
6
5
  module Icarus
7
6
  module Mod
8
7
  module Tools
9
8
  class Error < StandardError; end
9
+
10
+ # Icarus::Mod::Config.read
10
11
  end
11
12
  end
12
13
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Icarus
4
4
  module Mod
5
- VERSION = "1.3.5"
5
+ VERSION = "1.4.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Icarus-Mod-Tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donovan Young
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-02 00:00:00.000000000 Z
11
+ date: 2023-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-cloud-firestore
@@ -71,10 +71,14 @@ files:
71
71
  - Rakefile
72
72
  - exe/imt
73
73
  - icarus-mod-tools.gemspec
74
+ - imtconfig.sample.json
74
75
  - lib/icarus/mod/cli/add.rb
75
76
  - lib/icarus/mod/cli/base.rb
77
+ - lib/icarus/mod/cli/command.rb
76
78
  - lib/icarus/mod/cli/list.rb
79
+ - lib/icarus/mod/cli/subcommand_base.rb
77
80
  - lib/icarus/mod/cli/sync.rb
81
+ - lib/icarus/mod/config.rb
78
82
  - lib/icarus/mod/firestore.rb
79
83
  - lib/icarus/mod/github.rb
80
84
  - lib/icarus/mod/tools.rb