organo 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e70b5a09a3a28bf6f802fd6a0be5026afc63013a9243242330595367d2577f4e
4
- data.tar.gz: ea99ab4c465f05869b40d13b6a36df11fdf4d89eb477495a211c5f404b0cd59e
3
+ metadata.gz: 8407453ab8286b3b42000a26b2b32fe2aa4dd88958b8aa233fa6fe3913833218
4
+ data.tar.gz: 7dcd6925be753407d8db55a6df822c8482374aefd55dfec953d41ad1ff73de33
5
5
  SHA512:
6
- metadata.gz: 3ec4a7eb0cdefc58c92a44b15472a60e138c846ca27730f553ec48dc304fca6fc554d2ea5632ad6482d8e9789b73cd0fbc5ec1dc9f0f3e2c919703e894752d32
7
- data.tar.gz: 8ad3e6dc015be8e8d790755b99df1a95c04327150be9dea253d0018720345e7a97c2198f34e7e0d6d452bc56a2e88e01994458b3db0d87d485adaf36a1228911
6
+ metadata.gz: ed341b506fedd1e2e537bbcc990b2d9e62d92c57dfde1d3efc9396d1c1610a1b0141b08aba33f332f96cb0d0a5bc05a67ef41fdeada2267da99e789455230f4f
7
+ data.tar.gz: 04edcf3916ccbac568857b46d7893ba72a94347c7f58b3fddca90c17cdbd4f638983d48d869f7e1f284fca203e9a4fa93911761427dcb00d876b096a900efa56
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
 
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'os'
4
+
5
+ module Organo
6
+ module CLI
7
+ module Commands
8
+
9
+ class Dump < Dry::CLI::Command
10
+ desc 'Dump databse to SQL file'
11
+
12
+ def call(*)
13
+ executable = 'sqlite3'
14
+ can_run = false
15
+ win_filepath = "#{File.expand_path('~')}/sqlite-tools/sqlite3.exe"
16
+ if OS.windows? && File.exist?(win_filepath)
17
+ executable = win_filepath
18
+ can_run = true
19
+ elsif OS.linux? && system("which #{executable}")
20
+ can_run = true
21
+ end
22
+ output = 'Unable to run the command.'
23
+ output = `#{executable} #{Config::DATABASE_FILE} .dump > organo_dump.sql` if can_run
24
+ puts output unless output.empty?
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -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.4'
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'
@@ -19,6 +21,7 @@ require_relative 'organo/commands/remote/remote_upload'
19
21
  require_relative 'organo/commands/api/api_get_anime'
20
22
  require_relative 'organo/commands/api/api_get_season'
21
23
  require_relative 'organo/commands/api/api_get_sequels'
24
+ require_relative 'organo/commands/dump'
22
25
 
23
26
  module Organo
24
27
  module CLI
@@ -33,21 +36,28 @@ module Organo
33
36
  register 'anime show', Organo::CLI::Commands::Anime::ShowEntry
34
37
  register 'anime add', Organo::CLI::Commands::Anime::AddEntry
35
38
  register 'anime remove', Organo::CLI::Commands::Anime::RemoveEntry
36
- register 'anime set_sequel', Organo::CLI::Commands::Anime::SequelEntry
37
39
  register 'anime find_broken_links', Organo::CLI::Commands::Anime::FindBrokenLinks
40
+ register 'anime update', Organo::CLI::Commands::Anime::UpdateEntry
38
41
  register 'anime update image', Organo::CLI::Commands::Anime::UpdateImage
39
- register 'anime update search_query', Organo::CLI::Commands::Anime::UpdateSearchQuery
42
+
43
+ # Sequel commands
44
+ register 'sequel set', Organo::CLI::Commands::AnimeSequel::SetEntry
45
+ register 'sequel remove', Organo::CLI::Commands::AnimeSequel::RemoveEntry
46
+ register 'sequel update', Organo::CLI::Commands::AnimeSequel::UpdateEntry
40
47
 
41
48
  # Remote commands
42
49
  register 'remote add', Organo::CLI::Commands::Remote::AddEntry
43
50
  register 'remote remove', Organo::CLI::Commands::Remote::Remove
44
51
  register 'remote download', Organo::CLI::Commands::Remote::Download
45
- register 'remote download', Organo::CLI::Commands::Remote::Upload
52
+ register 'remote upload', Organo::CLI::Commands::Remote::Upload
46
53
 
47
54
  # API commands
48
55
  register 'api get anime', Organo::CLI::Commands::API::Get::Anime
49
56
  register 'api get season', Organo::CLI::Commands::API::Get::Season
50
57
  register 'api get sequels', Organo::CLI::Commands::API::Get::Sequels
58
+
59
+ # SQL dump
60
+ register 'dump', Organo::CLI::Commands::Dump
51
61
  end
52
62
  end
53
63
  end
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.4
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
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.21'
41
+ - !ruby/object:Gem::Dependency
42
+ name: os
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rest-client
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -113,24 +127,25 @@ files:
113
127
  - doc/schedule.md
114
128
  - exe/organo
115
129
  - lib/organo.rb
116
- - lib/organo/animeschedule_api.rb
130
+ - lib/organo/anime_database.rb
117
131
  - lib/organo/commands/anime/anime_add.rb
118
132
  - lib/organo/commands/anime/anime_find_broken_links.rb
119
133
  - lib/organo/commands/anime/anime_remove.rb
120
- - lib/organo/commands/anime/anime_set_sequel.rb
121
134
  - lib/organo/commands/anime/anime_show.rb
135
+ - lib/organo/commands/anime/anime_update.rb
122
136
  - lib/organo/commands/anime/anime_update_image.rb
123
- - lib/organo/commands/anime/anime_update_query.rb
124
137
  - lib/organo/commands/api/api_get_anime.rb
125
- - lib/organo/commands/api/api_get_schedule.rb
126
138
  - lib/organo/commands/api/api_get_season.rb
127
139
  - lib/organo/commands/api/api_get_sequels.rb
140
+ - lib/organo/commands/dump.rb
128
141
  - lib/organo/commands/init.rb
129
142
  - lib/organo/commands/remote/remote_add.rb
130
143
  - lib/organo/commands/remote/remote_download.rb
131
144
  - lib/organo/commands/remote/remote_remove.rb
132
145
  - lib/organo/commands/remote/remote_upload.rb
133
- - lib/organo/commands/schedule/schedule_create.rb
146
+ - lib/organo/commands/sequel/sequel_remove.rb
147
+ - lib/organo/commands/sequel/sequel_set.rb
148
+ - lib/organo/commands/sequel/sequel_update.rb
134
149
  - lib/organo/commands/statistics.rb
135
150
  - lib/organo/commands/version.rb
136
151
  - 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