organo 0.4.2 → 0.4.3

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: e70b5a09a3a28bf6f802fd6a0be5026afc63013a9243242330595367d2577f4e
4
- data.tar.gz: ea99ab4c465f05869b40d13b6a36df11fdf4d89eb477495a211c5f404b0cd59e
3
+ metadata.gz: 60bfda0078d17b33a65c93c0ce7204328fd10e55cdb64d699c03a8b5a4ab8c81
4
+ data.tar.gz: 5742128565877f12aa6b6b211179d79840d2b05a8858aaeda009113bd39634d5
5
5
  SHA512:
6
- metadata.gz: 3ec4a7eb0cdefc58c92a44b15472a60e138c846ca27730f553ec48dc304fca6fc554d2ea5632ad6482d8e9789b73cd0fbc5ec1dc9f0f3e2c919703e894752d32
7
- data.tar.gz: 8ad3e6dc015be8e8d790755b99df1a95c04327150be9dea253d0018720345e7a97c2198f34e7e0d6d452bc56a2e88e01994458b3db0d87d485adaf36a1228911
6
+ metadata.gz: 97934394e6a32b27014db664f8f49dab8edab63b6bec65d38a49cc47bf5ad3c598c93d33aa50ce591d11677a7bfdb48b07d9c97e83cd1c773036e135bf6053eb
7
+ data.tar.gz: 5a958e6cb4cc9db14f4fa612b395ed98959a6ccec21955d5aa0cd8b039e0dd62fe156ec87b9fb09ad93aa8e90f2d913dff76c9ddd2efd9efc84af237621e956e
data/doc/anime.md CHANGED
@@ -46,5 +46,5 @@ organo anime update image MAL_ID [...]
46
46
 
47
47
  Updates the `search_query` column of anime to specified string.
48
48
  ```shell
49
- organo anime update query MAL_ID SEARCH_QUERY
49
+ organo anime update search_query MAL_ID SEARCH_QUERY
50
50
  ```
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+ require 'httparty'
5
+ require_relative 'query'
6
+ require_relative 'tools/writer'
7
+ require_relative 'tools/string_utils'
8
+
9
+ module Organo
10
+ class AnimeDatabase
11
+ private_class_method :new
12
+
13
+ def self.instance
14
+ @instance.nil? ? new : @instance
15
+ end
16
+
17
+ def initialize
18
+ @database = Sequel.sqlite(Config::DATABASE_FILE)
19
+
20
+ unless @database.table_exists?(:shows)
21
+ @database.create_table(:shows) do
22
+ Integer :mal_id
23
+ String :slug, unique: true, null: true
24
+ String :title
25
+ String :img_url
26
+ String :search_query, null: true
27
+ Boolean :is_sequel
28
+ primary_key %i[mal_id]
29
+ end
30
+ end
31
+
32
+ unless @database.table_exists?(:sequels)
33
+ @database.create_table(:sequels) do
34
+ Integer :parent_id
35
+ Integer :child_id
36
+ String :type, default: 'season'
37
+ Integer :type_num, default: 0
38
+ String :subtype, default: ''
39
+ Integer :subtype_num, default: 0
40
+ Integer :subtype_selector, default: -1
41
+ primary_key %i[parent_id child_id]
42
+ end
43
+ end
44
+ end
45
+
46
+ ##
47
+ # Get database entry of show using the specified MyAnimeList ID
48
+ def anime_show(mal_id)
49
+ show_by_id(mal_id).first
50
+ end
51
+
52
+ ##
53
+ # Adds show entry to the database using the specified MyAnimeList ID
54
+ def anime_add(mal_id)
55
+ show = show_by_id(mal_id).first
56
+ if show.nil?
57
+ show_json = Query.get_anime_by_id(mal_id)
58
+ @database.transaction do
59
+ @database.after_commit do
60
+ puts 'Added show to the database.'
61
+ end
62
+ @database.after_rollback do
63
+ puts 'An error occurred. No change was made.'
64
+ end
65
+ @database.from(:shows).insert(
66
+ mal_id: show_json['mal_id'].to_i,
67
+ slug: generate_unique_slug(show_json['title']),
68
+ title: show_json['title'],
69
+ img_url: show_json['images']['jpg']['image_url'],
70
+ search_query: show_json['title'].gsub(':', ' -'),
71
+ is_sequel: false
72
+ )
73
+ end
74
+ else
75
+ puts 'This show already exists in the database.'
76
+ end
77
+ show_by_id(mal_id).first
78
+ end
79
+
80
+ ##
81
+ # Removes show entry from the database using the specified MyAnimeList ID
82
+ def anime_remove(mal_id)
83
+ show = show_by_id(mal_id).first
84
+ if show.nil?
85
+ puts 'This show doesn\'t exist in the database.'
86
+ else
87
+ @database.transaction do
88
+ show_by_id(mal_id).delete
89
+ puts 'The show was removed from the database.'
90
+ end
91
+ end
92
+ show
93
+ end
94
+
95
+ ##
96
+ # Edits anime entry with specified params
97
+ def anime_update(mal_id, params)
98
+ anime = show_by_id(mal_id)
99
+
100
+ if anime.first.nil?
101
+ puts "Specified show doesn't exist."
102
+ elsif params.empty?
103
+ puts 'No change was made.'
104
+ else
105
+ @database.transaction do
106
+ @database.after_commit do
107
+ puts 'Show values changed.'
108
+ end
109
+ @database.after_rollback do
110
+ puts 'An error occurred. No change was made.'
111
+ end
112
+ anime.update(params)
113
+ end
114
+ end
115
+ anime
116
+ end
117
+
118
+ def anime_update_image(mal_id_list)
119
+ mal_id_list.each do |mal_id|
120
+ show = show_by_id(mal_id)
121
+ api_image = Query.get_anime_image(mal_id)
122
+ if show.count.positive?
123
+ show.update(img_url: api_image)
124
+ puts 'Updated image.'
125
+ puts show.first
126
+ else
127
+ puts "MAL ID #{mal_id} doesn't exist in the database."
128
+ end
129
+ end
130
+ end
131
+
132
+ def anime_find_broken_links
133
+ shows = @database.from(:shows)
134
+ broken_list = []
135
+ shows.each do |show|
136
+ response = HTTParty.get(show[:img_url])
137
+ next unless response.code == 404
138
+
139
+ broken_list.push(show[:mal_id])
140
+ end
141
+ broken_list
142
+ end
143
+
144
+ ##
145
+ # Adds sequel entry for parent and child show
146
+ def sequel_set(parent_id, child_id, type, type_num, subtype, subtype_num, subtype_selector)
147
+ parent_show = show_by_id(parent_id)
148
+ child_show = show_by_id(child_id)
149
+ if !parent_show.first.nil? && !child_show.first.nil?
150
+ if @database.from(:sequels).where(parent_id: child_id).count.zero?
151
+ @database.from(:sequels).insert(
152
+ parent_id: parent_id,
153
+ child_id: child_id,
154
+ type: type,
155
+ type_num: type_num,
156
+ subtype: subtype,
157
+ subtype_num: subtype_num,
158
+ subtype_selector: subtype_selector
159
+ )
160
+ child_show.update(slug: nil, is_sequel: true)
161
+ puts 'Added sequel to the database.'
162
+ else
163
+ puts "Can't add sequel to database."
164
+ puts "#{child_show.first[:title]}(#{child_show.first[:mal_id]}) is already a parent for sequels."
165
+ end
166
+ else
167
+ puts "Can't add sequel to database."
168
+ puts "Parent MAL_ID #{parent_id} doesn't exist in the database." if parent_show.first.nil?
169
+ puts "Child MAL_ID #{child_id} doesn't exist in the database." if child_show.first.nil?
170
+ end
171
+ sequel_by_id(parent_id, child_id)
172
+ end
173
+
174
+ ##
175
+ # Edits sequel entry with specified params
176
+ def sequel_update(parent_id, child_id, params)
177
+ sequel = sequel_by_id(parent_id, child_id)
178
+
179
+ if sequel.first.nil?
180
+ puts "Specified sequel doesn't exist."
181
+ elsif params.empty?
182
+ puts 'No change was made.'
183
+ else
184
+ @database.transaction do
185
+ @database.after_commit do
186
+ puts 'Sequel values changed.'
187
+ end
188
+ @database.after_rollback do
189
+ puts 'An error occurred. No change was made.'
190
+ end
191
+ sequel.update(params)
192
+ end
193
+ end
194
+ sequel
195
+ end
196
+
197
+ ##
198
+ # Removes sequel entry from database
199
+ def sequel_remove(parent_id, child_id)
200
+ sequel = sequel_by_id(parent_id, child_id)
201
+ if sequel.first.nil?
202
+ puts "Specified sequel doesn't exist."
203
+ else
204
+ @database.transaction do
205
+ @database.after_commit do
206
+ puts 'Sequel entry was removed.'
207
+ end
208
+ @database.after_rollback do
209
+ puts 'An error occurred. No change was made.'
210
+ end
211
+ child_show = show_by_id(sequel.first[:child_id])
212
+ child_show.update(
213
+ slug: generate_unique_slug(child_show.first[:title]),
214
+ is_sequel: false
215
+ )
216
+ sequel.delete
217
+ end
218
+ end
219
+ sequel
220
+ end
221
+
222
+ def statistics
223
+ puts "Total show count: #{@database.from(:shows).count}"
224
+ puts "Non-sequel show count #{@database.from(:shows).where(is_sequel: false).count}"
225
+ puts "Sequel show count: #{@database.from(:sequels).count}"
226
+ end
227
+
228
+ private
229
+
230
+ def generate_unique_slug(title)
231
+ slug = StringUtils.create_slug(title)
232
+ slug_results_size = shows_by_slug(slug).count
233
+ slug += "-#{slug_results_size + 1}" if slug_results_size.positive?
234
+ slug
235
+ end
236
+
237
+ def show_by_id(mal_id)
238
+ @database.from(:shows).where(mal_id: mal_id)
239
+ end
240
+
241
+ def shows_by_slug(slug)
242
+ @database.from(:shows).where(slug: slug)
243
+ end
244
+
245
+ def sequel_by_id(parent_id, child_id)
246
+ @database.from(:sequels).where(parent_id: parent_id, child_id: child_id)
247
+ end
248
+
249
+ def sequels_by_parent_id(parent_id)
250
+ @database.from(:sequels).where(parent_id: parent_id)
251
+ end
252
+ end
253
+ end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../query'
4
- require_relative '../../tools/string_utils'
5
- require 'sequel'
3
+ require_relative '../../anime_database'
6
4
 
7
5
  module Organo
8
6
  module CLI
@@ -14,27 +12,11 @@ module Organo
14
12
  argument :mal_id, type: :integer, required: true, desc: 'MyAnimeList ID'
15
13
 
16
14
  def call(mal_id:, **)
17
- db = Sequel.sqlite('./dkb_edited.db')
18
- shows = db.from(:shows).where(mal_id: mal_id)
19
- if shows.count.zero?
20
- show_json = Query.get_anime_by_id(mal_id)
21
- db.from(:shows).insert(
22
- mal_id: show_json['mal_id'].to_i,
23
- slug: StringUtils.create_slug(show_json['title']),
24
- title: show_json['title'],
25
- img_url: show_json['images']['jpg']['image_url'],
26
- search_query: show_json['title'].gsub(':', ' -'),
27
- is_sequel: false
28
- )
29
- shows = db.from(:shows).where(mal_id: mal_id)
30
- puts 'Show has been added to database'
31
- else
32
- puts 'This show already exists'
33
- end
34
- puts shows.first
15
+ anime = AnimeDatabase.instance.anime_add(mal_id)
16
+ puts (anime.nil? ? 'Could not add the specified show to the database.' : anime)
35
17
  end
36
- end
37
18
 
19
+ end
38
20
  end
39
21
  end
40
22
  end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'httparty'
4
- require 'sequel'
5
-
6
3
  module Organo
7
4
  module CLI
8
5
  module Commands
@@ -12,15 +9,7 @@ module Organo
12
9
  desc 'Get list of anime IDs that have broken links'
13
10
 
14
11
  def call(*)
15
- db = Sequel.sqlite('dkb_edited.db')
16
- shows = db.from(:shows)
17
- broken_list = []
18
- shows.each do |show|
19
- response = HTTParty.get(show[:img_url])
20
- next unless response.code == 404
21
-
22
- broken_list.push(show[:mal_id])
23
- end
12
+ broken_list = AnimeDatabase.instance.anime_find_broken_links
24
13
  puts broken_list.join(' ') unless broken_list.empty?
25
14
  end
26
15
  end
@@ -1,25 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sequel'
3
+ require_relative '../../anime_database'
4
4
 
5
5
  module Organo
6
6
  module CLI
7
7
  module Commands
8
8
  module Anime
9
9
  class RemoveEntry < Dry::CLI::Command
10
- desc 'Remove anime entry from files'
10
+ desc 'Remove anime entry from database'
11
11
  argument :mal_id, type: :integer, required: true, desc: 'MyAnimeList ID'
12
12
 
13
13
  def call(mal_id:, **)
14
- db = Sequel.sqlite('./dkb_edited.db')
15
- shows = db.from(:shows).where(mal_id: mal_id)
16
- if shows.count.zero?
17
- puts 'This show doesn\'t exist.'
18
- else
19
- puts 'Removed show.'
20
- puts shows.first
21
- shows.delete
22
- end
14
+ anime = AnimeDatabase.instance.anime_remove(mal_id)
15
+ puts anime unless anime.nil?
23
16
  end
24
17
  end
25
18
 
@@ -12,13 +12,8 @@ module Organo
12
12
  argument :mal_id, type: :integer, required: true, desc: 'MyAnimeList ID'
13
13
 
14
14
  def call(mal_id:, **)
15
- db = Sequel.sqlite('dkb_edited.db')
16
- show = db.from(:shows).where(mal_id: mal_id)
17
- if show.count.positive?
18
- puts show.first
19
- else
20
- puts "ID #{mal_id} doesn't exist in the database."
21
- end
15
+ anime = AnimeDatabase.instance.anime_show(mal_id)
16
+ puts (anime.nil? ? "MAL_ID #{mal_id} doesn't exist in the database." : anime)
22
17
  end
23
18
  end
24
19
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../anime_database'
4
+
5
+ module Organo
6
+ module CLI
7
+ module Commands
8
+ module Anime
9
+
10
+ class UpdateEntry < Dry::CLI::Command
11
+ desc 'Update anime entry'
12
+ argument :mal_id, type: :integer, required: true, desc: 'MyAnimeList ID'
13
+ option :slug, type: :string, desc: 'Lowercase string for building website routes'
14
+ option :title, type: :string, desc: 'Title'
15
+ option :img_url, type: :string, desc: 'URL of the cover image'
16
+ option :search_query, type: :string, desc: 'Nyaa search query'
17
+
18
+ def call(mal_id:, **options)
19
+ anime = AnimeDatabase.instance.anime_update(mal_id, options)
20
+ puts anime.first unless anime.first.nil?
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -13,18 +13,7 @@ module Organo
13
13
  argument :mal_id_list, type: :array, required: true, desc: 'MyAnimeList ID list'
14
14
 
15
15
  def call(mal_id_list:, **)
16
- db = Sequel.sqlite('dkb_edited.db')
17
- mal_id_list.each do |mal_id|
18
- show = db.from(:shows).where(mal_id: mal_id)
19
- api_image = Query.get_anime_image(mal_id)
20
- if show.count.positive?
21
- show.update(img_url: api_image)
22
- puts "Updated image of #{show.first[:title]} (#{mal_id})"
23
- puts api_image
24
- else
25
- puts "ID #{mal_id} doesn't exist in the database."
26
- end
27
- end
16
+ AnimeDatabase.instance.anime_update_image(mal_id_list)
28
17
  end
29
18
  end
30
19
 
@@ -1,43 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sequel'
4
-
5
3
  module Organo
6
4
  module CLI
7
5
  module Commands
8
6
 
9
7
  class Init < Dry::CLI::Command
10
- desc 'Initialize database'
8
+ desc 'Initialize organo directory'
11
9
 
12
10
  def call(*)
13
11
  Dir.mkdir './.organo' unless File.exist?('./.organo')
14
-
15
- db = Sequel.sqlite('dkb_edited.db')
16
- unless db.table_exists?(:shows)
17
- db.create_table(:shows) do
18
- Integer :mal_id
19
- String :slug, unique: true, null: true
20
- String :title
21
- String :img_url
22
- String :search_query, null: true
23
- Boolean :is_sequel
24
- primary_key %i[mal_id]
25
- end
26
- end
27
-
28
- unless db.table_exists?(:sequels)
29
- db.create_table(:sequels) do
30
- Integer :parent_id
31
- Integer :child_id
32
- String :type, default: 'season'
33
- Integer :type_num, default: 0
34
- String :subtype, default: ''
35
- Integer :subtype_num, default: 0
36
- Integer :subtype_selector, default: -1
37
- primary_key %i[parent_id child_id]
38
- end
39
- end
40
-
41
12
  end
42
13
  end
43
14
 
@@ -16,19 +16,27 @@ module Organo
16
16
  option :directory, type: :string, default: '', desc: 'FTP directory'
17
17
 
18
18
  def call(env:, url:, username:, password:, directory:, **)
19
- config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : []
20
- section = config.find { |option| option['section'] == 'remotes' }
21
- remote = { env: env, url: url, username: username, password: password, directory: directory }
22
- if section.nil?
23
- section = { section: 'remotes', entries: [] }
24
- config.push(section)
25
- section[:entries].push(remote)
26
- elsif section['entries'].find { |entry| entry['env'] == env }.nil?
27
- section['entries'].push(remote)
19
+ if File.exist?('./.organo')
20
+ config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : []
21
+ section = config.find { |option| option['section'] == 'remotes' }
22
+ remote = {
23
+ env: env, url: url, username: username, password: password,
24
+ directory: directory, database_filename: Config::DATABASE_FILE
25
+ }
26
+ if section.nil?
27
+ section = { section: 'remotes', entries: [] }
28
+ config.push(section)
29
+ section[:entries].push(remote)
30
+ elsif section['entries'].find { |entry| entry['env'] == env }.nil?
31
+ section['entries'].push(remote)
32
+ else
33
+ puts 'Environment name is already used'
34
+ end
35
+ File.write(Config::DEFAULT_FILE, JSON.pretty_generate(config))
28
36
  else
29
- puts 'Environment name is already used'
37
+ puts 'This directory is not initialized.'
38
+ puts 'Run command `organo init` to create the configuration directory.'
30
39
  end
31
- File.write(Config::DEFAULT_FILE, JSON.pretty_generate(config))
32
40
  end
33
41
  end
34
42
 
@@ -13,25 +13,30 @@ module Organo
13
13
  argument :env, type: :string, required: true, desc: 'Environment'
14
14
 
15
15
  def call(env:, **)
16
- config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
17
- section = config.find { |option| option['section'] == 'remotes' }
18
- if section.nil?
19
- puts 'No remote is configured in the configuration file'
20
- else
21
- credentials = section['entries'].find { |entry| entry['env'] == env }
22
- if credentials.nil?
23
- puts 'Could not find the specified environment'
16
+ if File.exist?('./.organo')
17
+ config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
18
+ section = config.find { |option| option['section'] == 'remotes' }
19
+ if section.nil?
20
+ puts 'No remote is configured in the configuration file'
24
21
  else
25
- Net::FTP.open(credentials['url']) do |ftp|
26
- ftp.login(credentials['username'], credentials['password'])
27
- ftp.chdir(credentials['directory'])
28
- if File.exist?('dkb_edited.db')
29
- File.delete('dkb_edited.db.old') if File.exist?('dkb_edited.db.old')
30
- File.rename('dkb_edited.db', 'dkb_edited.db.old')
22
+ credentials = section['entries'].find { |entry| entry['env'] == env }
23
+ if credentials.nil?
24
+ puts 'Could not find the specified environment'
25
+ else
26
+ Net::FTP.open(credentials['url']) do |ftp|
27
+ ftp.login(credentials['username'], credentials['password'])
28
+ ftp.chdir(credentials['directory'])
29
+ if File.exist?(Config::DATABASE_FILE)
30
+ File.delete("#{Config::DATABASE_FILE}.old") if File.exist?("#{Config::DATABASE_FILE}.old")
31
+ File.rename(Config::DATABASE_FILE, "#{Config::DATABASE_FILE}.old")
32
+ end
33
+ ftp.getbinaryfile(credentials['database_filename'], Config::DATABASE_FILE)
31
34
  end
32
- ftp.getbinaryfile('dkb_edited.db')
33
35
  end
34
36
  end
37
+ else
38
+ puts 'This directory is not initialized.'
39
+ puts 'Run command `organo init` to create the configuration directory.'
35
40
  end
36
41
  rescue Net::FTPPermError
37
42
  puts 'Login to FTP server failed.'
@@ -12,21 +12,26 @@ module Organo
12
12
  argument :env, type: :string, required: true, desc: 'Remote environment name'
13
13
 
14
14
  def call(env:, **)
15
- config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
16
- unless config.nil?
17
- section = config.find { |option| option['section'] == 'remotes' }
18
- if !section.nil?
19
- index = section['entries'].find_index { |entry| entry['env'] == env }
20
- if index.nil?
21
- puts 'Specified environment does not exist'
22
- elsif !section['entries'].delete_at(index).nil?
23
- puts "Removed \"#{env}\" entry"
15
+ if File.exist?('./.organo')
16
+ config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
17
+ unless config.nil?
18
+ section = config.find { |option| option['section'] == 'remotes' }
19
+ if !section.nil?
20
+ index = section['entries'].find_index { |entry| entry['env'] == env }
21
+ if index.nil?
22
+ puts 'Specified environment does not exist'
23
+ elsif !section['entries'].delete_at(index).nil?
24
+ puts "Removed \"#{env}\" entry"
25
+ end
26
+ else
27
+ puts 'Configuration file does not have a remote'
24
28
  end
25
- else
26
- puts 'Configuration file does not have a remote'
27
29
  end
30
+ File.write(Config::DEFAULT_FILE, JSON.pretty_generate(config))
31
+ else
32
+ puts 'This directory is not initialized.'
33
+ puts 'Run command `organo init` to create the configuration directory.'
28
34
  end
29
- File.write(Config::DEFAULT_FILE, JSON.pretty_generate(config))
30
35
  end
31
36
  end
32
37
 
@@ -12,28 +12,28 @@ module Organo
12
12
  argument :env, type: :string, required: true, desc: 'Environment'
13
13
 
14
14
  def call(env:, **)
15
- config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
16
- section = config.find { |option| option['section'] == 'remotes' }
17
- if section.nil?
18
- puts 'No remote is configured in the configuration file'
19
- else
20
- credentials = section['entries'].find { |entry| entry['env'] == env }
21
- if credentials.nil?
22
- puts 'Could not find the specified environment'
15
+ if File.exist?('./.organo')
16
+ config = File.exist?(Config::DEFAULT_FILE) ? JSON.parse(File.read(Config::DEFAULT_FILE)) : nil
17
+ section = config.find { |option| option['section'] == 'remotes' }
18
+ if section.nil?
19
+ puts 'No remote is configured in the configuration file'
23
20
  else
24
- local_files = Dir['./*.{data,config}.json']
25
- local_files.push('./schedule.json')
26
- local_files.push('./dkb_edited.db')
27
- Net::FTP.open(credentials['url']) do |ftp|
28
- ftp.login(credentials['username'], credentials['password'])
29
- ftp.chdir(credentials['directory'])
30
- local_files.each do |file_path|
31
- file_name = File.basename(file_path)
32
- puts "Uploading file: #{file_name}"
33
- ftp.putbinaryfile(file_name)
21
+ credentials = section['entries'].find { |entry| entry['env'] == env }
22
+ if credentials.nil?
23
+ puts 'Could not find the specified environment'
24
+ else
25
+ local_file = Config::DATABASE_FILE
26
+ Net::FTP.open(credentials['url']) do |ftp|
27
+ ftp.login(credentials['username'], credentials['password'])
28
+ ftp.chdir(credentials['directory'])
29
+ puts "Uploading file: #{local_file}"
30
+ ftp.putbinaryfile(local_file, credentials['database_filename'])
34
31
  end
35
32
  end
36
33
  end
34
+ else
35
+ puts 'This directory is not initialized.'
36
+ puts 'Run command `organo init` to create the configuration directory.'
37
37
  end
38
38
  rescue Net::FTPPermError
39
39
  puts 'Login to FTP server failed.'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../anime_database'
4
+
5
+ module Organo
6
+ module CLI
7
+ module Commands
8
+ module AnimeSequel
9
+
10
+ class RemoveEntry < Dry::CLI::Command
11
+ desc 'Remove sequel entry from database'
12
+ argument :parent_id, type: :integer, required: true, desc: 'Parent MyAnimeList ID'
13
+ argument :child_id, type: :integer, required: true, desc: 'Child MyAnimeList ID'
14
+
15
+ def call(parent_id:, child_id:, **)
16
+ sequel = AnimeDatabase.instance.sequel_remove(parent_id, child_id)
17
+ puts sequel.first unless sequel.first.nil?
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../anime_database'
4
+
5
+ module Organo
6
+ module CLI
7
+ module Commands
8
+ module AnimeSequel
9
+
10
+ class SetEntry < Dry::CLI::Command
11
+ desc 'Set show entry as sequel to another show'
12
+ argument :parent_id, type: :integer, required: true, desc: 'Anime MyAnimeList ID'
13
+ argument :child_id, type: :integer, required: true, desc: 'Sequel MyAnimeList ID'
14
+ argument :type, type: :string, required: false, default: 'season', values: %w[season movie ova], desc: 'Type of sequel (season, movie, ova)'
15
+ argument :type_num, type: :integer, required: false, default: 0, desc: 'The sequel type number'
16
+ argument :subtype, type: :string, required: false, default: '', values: %w[part special ova], desc: 'Type of sequel (part, special, ova)'
17
+ argument :subtype_num, type: :integer, required: false, default: 0, desc: 'The sequel subtype number'
18
+ argument :subtype_selector, type: :integer, required: false, default: -1, desc: 'The sequel subtype selector'
19
+
20
+ def call(parent_id:, child_id:, type:, type_num:, subtype:, subtype_num:, subtype_selector:, **)
21
+ sequel = AnimeDatabase.instance.sequel_set(parent_id, child_id, type, type_num, subtype, subtype_num, subtype_selector)
22
+ puts sequel.first unless sequel.first.nil?
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../anime_database'
4
+
5
+ module Organo
6
+ module CLI
7
+ module Commands
8
+ module AnimeSequel
9
+
10
+ class UpdateEntry < Dry::CLI::Command
11
+ desc 'Update sequel entry'
12
+ argument :parent_id, type: :integer, required: true, desc: 'Anime MyAnimeList ID'
13
+ argument :child_id, type: :integer, required: true, desc: 'Sequel MyAnimeList ID'
14
+ option :type, type: :string, values: %w[season movie ova], desc: 'Type of sequel (season, movie, ova)'
15
+ option :type_num, type: :integer, desc: 'The sequel type number'
16
+ option :subtype, type: :string, values: %w[part special ova], desc: 'Type of sequel (part, special, ova)'
17
+ option :subtype_num, type: :integer, desc: 'The sequel subtype number'
18
+ option :subtype_selector, type: :integer, desc: 'The sequel subtype selector'
19
+
20
+ def call(parent_id:, child_id:, **options)
21
+ sequel = AnimeDatabase.instance.sequel_update(parent_id, child_id, options)
22
+ puts sequel.first unless sequel.first.nil?
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sequel'
3
+ require_relative '../anime_database'
4
4
 
5
5
  module Organo
6
6
  module CLI
@@ -10,10 +10,7 @@ module Organo
10
10
  desc 'Get statistics from data'
11
11
 
12
12
  def call(*)
13
- db = Sequel.sqlite('dkb_edited.db')
14
- puts "Total show count: #{db.from(:shows).count}"
15
- puts "Non-sequel show count #{db.from(:shows).where(is_sequel: false).count}"
16
- puts "Sequel show count: #{db.from(:sequels).count}"
13
+ AnimeDatabase.instance.statistics
17
14
  end
18
15
  end
19
16
 
data/lib/organo/config.rb CHANGED
@@ -3,6 +3,6 @@
3
3
  module Organo
4
4
  class Config
5
5
  DEFAULT_FILE = './.organo/config.json'
6
- DEFAULT_DIR = './.organo/datafiles'
6
+ DATABASE_FILE = './organo.db'
7
7
  end
8
8
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Organo
4
- VERSION = '0.4.2'
4
+ VERSION = '0.4.3'
5
5
  end
data/lib/organo.rb CHANGED
@@ -8,10 +8,12 @@ require_relative 'organo/commands/statistics'
8
8
  require_relative 'organo/commands/anime/anime_show'
9
9
  require_relative 'organo/commands/anime/anime_add'
10
10
  require_relative 'organo/commands/anime/anime_remove'
11
- require_relative 'organo/commands/anime/anime_set_sequel'
12
11
  require_relative 'organo/commands/anime/anime_find_broken_links'
13
12
  require_relative 'organo/commands/anime/anime_update_image'
14
- require_relative 'organo/commands/anime/anime_update_query'
13
+ require_relative 'organo/commands/anime/anime_update'
14
+ require_relative 'organo/commands/sequel/sequel_set'
15
+ require_relative 'organo/commands/sequel/sequel_remove'
16
+ require_relative 'organo/commands/sequel/sequel_update'
15
17
  require_relative 'organo/commands/remote/remote_add'
16
18
  require_relative 'organo/commands/remote/remote_remove'
17
19
  require_relative 'organo/commands/remote/remote_download'
@@ -33,16 +35,20 @@ module Organo
33
35
  register 'anime show', Organo::CLI::Commands::Anime::ShowEntry
34
36
  register 'anime add', Organo::CLI::Commands::Anime::AddEntry
35
37
  register 'anime remove', Organo::CLI::Commands::Anime::RemoveEntry
36
- register 'anime set_sequel', Organo::CLI::Commands::Anime::SequelEntry
37
38
  register 'anime find_broken_links', Organo::CLI::Commands::Anime::FindBrokenLinks
39
+ register 'anime update', Organo::CLI::Commands::Anime::UpdateEntry
38
40
  register 'anime update image', Organo::CLI::Commands::Anime::UpdateImage
39
- register 'anime update search_query', Organo::CLI::Commands::Anime::UpdateSearchQuery
41
+
42
+ # Sequel commands
43
+ register 'sequel set', Organo::CLI::Commands::AnimeSequel::SetEntry
44
+ register 'sequel remove', Organo::CLI::Commands::AnimeSequel::RemoveEntry
45
+ register 'sequel update', Organo::CLI::Commands::AnimeSequel::UpdateEntry
40
46
 
41
47
  # Remote commands
42
48
  register 'remote add', Organo::CLI::Commands::Remote::AddEntry
43
49
  register 'remote remove', Organo::CLI::Commands::Remote::Remove
44
50
  register 'remote download', Organo::CLI::Commands::Remote::Download
45
- register 'remote download', Organo::CLI::Commands::Remote::Upload
51
+ register 'remote upload', Organo::CLI::Commands::Remote::Upload
46
52
 
47
53
  # API commands
48
54
  register 'api get anime', Organo::CLI::Commands::API::Get::Anime
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: organo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Louis-Philippe Fortin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-16 00:00:00.000000000 Z
11
+ date: 2023-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-cli
@@ -113,16 +113,14 @@ files:
113
113
  - doc/schedule.md
114
114
  - exe/organo
115
115
  - lib/organo.rb
116
- - lib/organo/animeschedule_api.rb
116
+ - lib/organo/anime_database.rb
117
117
  - lib/organo/commands/anime/anime_add.rb
118
118
  - lib/organo/commands/anime/anime_find_broken_links.rb
119
119
  - lib/organo/commands/anime/anime_remove.rb
120
- - lib/organo/commands/anime/anime_set_sequel.rb
121
120
  - lib/organo/commands/anime/anime_show.rb
121
+ - lib/organo/commands/anime/anime_update.rb
122
122
  - lib/organo/commands/anime/anime_update_image.rb
123
- - lib/organo/commands/anime/anime_update_query.rb
124
123
  - lib/organo/commands/api/api_get_anime.rb
125
- - lib/organo/commands/api/api_get_schedule.rb
126
124
  - lib/organo/commands/api/api_get_season.rb
127
125
  - lib/organo/commands/api/api_get_sequels.rb
128
126
  - lib/organo/commands/init.rb
@@ -130,7 +128,9 @@ files:
130
128
  - lib/organo/commands/remote/remote_download.rb
131
129
  - lib/organo/commands/remote/remote_remove.rb
132
130
  - lib/organo/commands/remote/remote_upload.rb
133
- - lib/organo/commands/schedule/schedule_create.rb
131
+ - lib/organo/commands/sequel/sequel_remove.rb
132
+ - lib/organo/commands/sequel/sequel_set.rb
133
+ - lib/organo/commands/sequel/sequel_update.rb
134
134
  - lib/organo/commands/statistics.rb
135
135
  - lib/organo/commands/version.rb
136
136
  - lib/organo/config.rb
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Organo
4
- class AnimeScheduleAPI
5
- BASE_URL = 'https://animeschedule.net/api/'
6
-
7
- def self.get_url(endpoint, api_version = 'v3', key = '')
8
- "#{BASE_URL}#{api_version}/#{endpoint}"
9
- end
10
- end
11
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sequel'
4
-
5
- module Organo
6
- module CLI
7
- module Commands
8
- module Anime
9
-
10
- class SequelEntry < Dry::CLI::Command
11
- desc 'Set show entry as sequel to another show'
12
- argument :parent_id, type: :integer, required: true, desc: 'Anime MyAnimeList ID'
13
- argument :child_id, type: :integer, required: true, desc: 'Sequel MyAnimeList ID'
14
- argument :type, type: :string, required: false, default: 'season', values: %w[season movie ova], desc: 'Type of sequel (season, movie, ova)'
15
- argument :type_num, type: :integer, required: false, default: 0, desc: 'The sequel type number'
16
- argument :subtype, type: :string, required: false, default: '', values: %w[part special ova], desc: 'Type of sequel (part, special, ova)'
17
- argument :subtype_num, type: :integer, required: false, default: 0, desc: 'The sequel subtype number'
18
- argument :subtype_selector, type: :integer, required: false, default: -1, desc: 'The sequel subtype selector'
19
-
20
- def call(parent_id:, child_id:, type:, type_num:, subtype:, subtype_num:, subtype_selector:, **)
21
- db = Sequel.sqlite('dkb_edited.db')
22
- parent_show = db.from(:shows).where(mal_id: parent_id)
23
- child_show = db.from(:shows).where(mal_id: child_id)
24
- if parent_show.count.positive? && child_show.count.positive?
25
- if db.from(:sequels).where(parent_id: parent_id, child_id: child_id).count.positive?
26
- puts 'This sequel entry already exist.'
27
- else
28
- db.from(:sequels).insert(
29
- parent_id: parent_id,
30
- child_id: child_id,
31
- type: type,
32
- type_num: type_num,
33
- subtype: subtype,
34
- subtype_num: subtype_num,
35
- subtype_selector: subtype_selector
36
- )
37
- child_show.update(is_sequel: true)
38
- puts "#{child_show.first[:title]}(#{child_show.first[:mal_id]}) is now a sequel to #{parent_show.first[:title]}(#{parent_show.first[:mal_id]})"
39
- end
40
- else
41
- puts "Parent or child show doesn't exist."
42
- end
43
- end
44
-
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sequel'
4
-
5
- module Organo
6
- module CLI
7
- module Commands
8
- module Anime
9
-
10
- class UpdateSearchQuery < Dry::CLI::Command
11
- desc 'Update search query for the specified anime'
12
- argument :mal_id, type: :integer, required: true, desc: 'MyAnimeList ID'
13
- argument :search_query, type: :string, required: true, desc: 'String query for Nyaa Torrents search'
14
-
15
- def call(mal_id:, search_query:, **)
16
- db = Sequel.sqlite('dkb_edited.db')
17
- show = db.from(:shows).where(mal_id: mal_id)
18
- if show.count.positive?
19
- old_query = show.first[:search_query]
20
- show.update(search_query: search_query)
21
- puts "Updated search query of #{show.first[:title]} (#{mal_id})"
22
- puts "#{old_query} --> #{search_query}"
23
- else
24
- puts "ID #{mal_id} doesn't exist in the database."
25
- end
26
- end
27
- end
28
-
29
- end
30
- end
31
- end
32
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../config'
4
- require_relative '../../animeschedule_api'
5
-
6
- module Organo
7
- module CLI
8
- module Commands
9
- module API
10
- module Get
11
-
12
- class Schedule < Dry::CLI::Command
13
- desc 'Get anime release schedule of a specified season'
14
- argument :season, type: :string, required: true, desc: 'Winter, Spring, Summer or Fall'
15
- argument :year, type: :integer, required: true, desc: 'Year'
16
-
17
- def call(season:, year:, **)
18
- # Get the list of anime mal_id
19
- # show_list = Reader.read_file("#{Config::DEFAULT_DIR}/#{year}-#{season.downcase}.json")
20
-
21
- config = JSON.parse(File.read(Config::DEFAULT_FILE))
22
- section = config.find { |option| option['section'] == 'api' }
23
- key = (section['entries'].find { |entry| entry['name'] == 'AnimeSchedule' })['key']
24
-
25
- count = 0
26
- page = 1
27
- total = 0
28
- anime_list = []
29
- loop do
30
- data = JSON.parse(
31
- RestClient.get(
32
- "#{AnimeScheduleAPI.get_url('anime', 'v3')}?mt=all&years=#{year}&seasons=#{season}&media-types=tv&page=#{page}",
33
- { Authorization: "Bearer #{key}" }
34
- )
35
- )
36
- total = data['totalAmount'].to_i
37
- page += 1
38
- count += data['anime'].size
39
- anime_list.concat(data['anime'])
40
- break if count >= total
41
- end
42
-
43
- draft_schedule = []
44
- anime_list.each do |anime|
45
- air_time = DateTime.parse(anime['premier'])
46
- draft_schedule.push(
47
- {
48
- slug: anime['route'],
49
- title: anime['title'],
50
- weekday: air_time.strftime('%A').downcase
51
- }
52
- )
53
- end
54
-
55
- file = File.read('schedule.json')
56
- schedule = JSON.parse(file)
57
- schedule.each do |weekday|
58
- draft_schedule.each do |anime|
59
- next unless anime[:weekday].eql? weekday['weekday']
60
-
61
- weekday['shows'].push(
62
- { slug: anime[:slug], title: anime[:title], time: '' }
63
- )
64
- end
65
- end
66
- Writer.to_file(schedule, 'schedule.json')
67
- end
68
- end
69
-
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,27 +0,0 @@
1
- require 'date'
2
-
3
- module Organo
4
- module CLI
5
- module Commands
6
- module Schedule
7
-
8
- class Create < Dry::CLI::Command
9
- desc 'Initialize directory with default files and directories'
10
-
11
- def call(*)
12
- content = []
13
- Date::DAYNAMES.each do |dname|
14
- content.push({ 'weekday' => dname.downcase, 'shows' => [] } )
15
- end
16
- File.write(
17
- './schedule.json',
18
- JSON.pretty_generate(content)
19
- )
20
- puts 'Created the schedule'
21
- end
22
- end
23
-
24
- end
25
- end
26
- end
27
- end