aniview 2.1.2 → 3.0.1
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 +4 -4
- data/bin/aniview +4 -4
- data/lib/aniview.rb +1 -1
- data/lib/aniview/interface/animeio/animefile.rb +4 -2
- data/lib/aniview/interface/animeio/animeio.rb +226 -175
- data/lib/aniview/interface/animeio/animeseries.rb +29 -45
- data/lib/aniview/interface/bridge.rb +11 -0
- data/lib/aniview/interface/deluge/delugec.rb +16 -10
- data/lib/aniview/interface/item.rb +3 -0
- data/lib/aniview/interface/mpv/mpvbridge.rb +38 -8
- data/lib/aniview/interface/pref/defaults.json +6 -5
- data/lib/aniview/interface/pref/pref.rb +40 -16
- data/lib/aniview/interface/pref/validate.json +2 -1
- data/lib/aniview/interface/schedule/schedule.rb +17 -18
- data/lib/aniview/interface/subscription/subscription.rb +22 -16
- data/lib/aniview/util/util.rb +1 -1
- data/lib/aniview/view/aiomenu.rb +15 -23
- data/lib/aniview/view/delugemenu.rb +12 -21
- data/lib/aniview/view/menu.rb +123 -91
- data/lib/aniview/view/prefmenu.rb +11 -27
- data/lib/aniview/view/schedulemenu.rb +0 -11
- data/lib/aniview/view/statusline.rb +42 -5
- data/lib/aniview/view/subscriptionmenu.rb +16 -20
- data/lib/application.rb +89 -68
- data/lib/daemon.rb +20 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b35aefbae5c33c60dd90e34e39ba25538fb537d
|
4
|
+
data.tar.gz: f930e37c98cab765b2baaf880e1631e9b8cee308
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cb7100a4503b321ebac1a28582d856fc2b536fbae03ffa7dbc3d9bcacb5d5506e3ba8f75871822f749695afff13c9249bee1fc6bdb309c2d0265e366e49cace
|
7
|
+
data.tar.gz: def2061bba9ae07a58886a26a0f8d468632d98623c1d13be405f895651be834e4d737aebc7df084fcf79b5bd44ac274012c264f35bdad467c245078b4428597c
|
data/bin/aniview
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
begin
|
4
|
-
|
4
|
+
require 'aniview'
|
5
5
|
rescue LoadError
|
6
|
-
|
6
|
+
require_relative '../lib/aniview' if File.exist?(File.join(File.dirname(__FILE__), '../lib/aniview.rb'))
|
7
7
|
end
|
8
8
|
|
9
9
|
unless defined? Aniview
|
10
|
-
|
11
|
-
|
10
|
+
puts "cant find aniview library"
|
11
|
+
exit
|
12
12
|
end
|
13
13
|
|
14
14
|
Aniview::main(ARGV)
|
data/lib/aniview.rb
CHANGED
@@ -32,6 +32,7 @@ module Aniview
|
|
32
32
|
case arg
|
33
33
|
when "-d"
|
34
34
|
argv.delete_at(0)
|
35
|
+
daemonize = true
|
35
36
|
main_class = Aniview::Daemon.new(argv)
|
36
37
|
when "-h"
|
37
38
|
self.show_help
|
@@ -49,7 +50,6 @@ module Aniview
|
|
49
50
|
process = fork do
|
50
51
|
main_class.run
|
51
52
|
end
|
52
|
-
|
53
53
|
Process.detach(process)
|
54
54
|
else
|
55
55
|
main_class.run
|
@@ -11,17 +11,19 @@ module Aniview
|
|
11
11
|
include Aniview::Util
|
12
12
|
|
13
13
|
attr_accessor :last_modified
|
14
|
+
attr_accessor :accessible
|
14
15
|
attr_accessor :path
|
15
16
|
|
16
17
|
def initialize(path_, seen = false)
|
17
|
-
@watched
|
18
|
+
@watched = seen
|
19
|
+
@accessible = true
|
18
20
|
begin
|
19
21
|
@last_modified = File::Stat.new(path_).mtime
|
20
22
|
rescue Errno::ENOENT
|
21
23
|
@last_modified = "0"
|
22
24
|
end
|
23
25
|
@watched_on = 0
|
24
|
-
@path
|
26
|
+
@path = path_
|
25
27
|
|
26
28
|
@attr = {
|
27
29
|
"t" => "empty",
|
@@ -1,212 +1,263 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require 'fileutils'
|
3
|
+
require 'observer'
|
4
|
+
require 'listen'
|
5
|
+
require 'benchmark'
|
6
|
+
|
3
7
|
require_relative 'animefile'
|
4
8
|
require_relative 'animeseries'
|
5
9
|
require_relative '../../util/util'
|
10
|
+
require_relative '../bridge'
|
6
11
|
|
7
12
|
module Aniview
|
8
13
|
module Interface
|
9
|
-
|
10
|
-
class AnimeIO
|
11
|
-
|
14
|
+
|
15
|
+
class AnimeIO < Bridge
|
16
|
+
|
17
|
+
include Aniview::Util
|
18
|
+
|
19
|
+
include Observable
|
20
|
+
|
21
|
+
def initialize(pref, mpvbridge)
|
12
22
|
@pref = pref
|
13
23
|
@mpvbridge = mpvbridge
|
14
24
|
@empty_hash = make_empty_hash
|
15
25
|
@watch_log_tag = "♪"
|
16
26
|
@dir_last_modified = {}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
27
|
+
@made_changes = true
|
28
|
+
|
29
|
+
self.load
|
30
|
+
pref_changed!
|
31
|
+
relisten
|
32
|
+
|
33
|
+
@pref.add_observer(self, :pref_changed!)
|
34
|
+
@mpvbridge.add_observer(self, :animefile_changed!)
|
35
|
+
#@@local_anime.each { |key, obj| obj.add_observer(self, :animefile_changed!)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def relisten
|
39
|
+
@listener.stop unless @listener == nil
|
40
|
+
return if @anime_dirs == nil or @anime_dirs[0] == ""
|
41
|
+
@listener = Listen.to(*@anime_dirs, only: /\.mkv$/) do |modified, added, removed|
|
42
|
+
index_anime
|
43
|
+
end
|
44
|
+
@listener.start
|
45
|
+
end
|
46
|
+
|
47
|
+
def cleanup
|
48
|
+
@listener.stop unless @listener == nil
|
49
|
+
end
|
21
50
|
|
22
51
|
def make_empty_hash
|
23
52
|
af = AnimeFile.new("empty")
|
24
53
|
{AnimeSeries.new("empty", [af]) => [af]}
|
25
54
|
end
|
26
55
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
56
|
+
def save
|
57
|
+
@pref.set "local_anime", Util.encode_object(@@local_anime)
|
58
|
+
end
|
59
|
+
|
60
|
+
def load
|
61
|
+
raw = @pref.get "local_anime"
|
62
|
+
if not raw == nil and raw.class == String
|
63
|
+
@@local_anime = Util.decode_object raw
|
64
|
+
else
|
65
|
+
@@local_anime = {}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def pref_changed!
|
70
|
+
new_dirs = (@pref.get("anime_locations").split(":")).collect { |dir|
|
71
|
+
@pref.parseDir(dir)
|
72
|
+
}
|
73
|
+
if new_dirs != @anime_dirs
|
74
|
+
@anime_dirs = new_dirs
|
75
|
+
index_anime
|
76
|
+
relisten
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def animefile_changed!
|
81
|
+
return unless @mpvbridge.what_changed == "local_anime"
|
82
|
+
changed
|
83
|
+
notify_observers
|
84
|
+
end
|
39
85
|
|
40
|
-
def index_anime(force: false, verbose: false)
|
41
|
-
ret = {}
|
42
|
-
made_changes = false
|
43
86
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
87
|
+
##
|
88
|
+
## @brief Indexes anime files up to 1 level deep in specified anime directories
|
89
|
+
##
|
90
|
+
## @param force The force
|
91
|
+
## @param verbose The verbose
|
92
|
+
##
|
93
|
+
## @return { description_of_the_return_value }
|
94
|
+
##
|
95
|
+
def index_anime(force: false, verbose: false)
|
96
|
+
Thread.new {
|
97
|
+
ret = {}
|
98
|
+
made_changes = false
|
99
|
+
lal = @@local_anime.length
|
48
100
|
|
49
|
-
|
101
|
+
@anime_dirs.each { |dir|
|
50
102
|
|
51
|
-
|
52
|
-
if
|
53
|
-
|
103
|
+
# check if the directory exists
|
104
|
+
if not File.exist? dir
|
105
|
+
if @dir_last_modified[dir] != "check"
|
106
|
+
@dir_last_modified[dir] = "check"
|
107
|
+
made_changes = true
|
108
|
+
end
|
54
109
|
next
|
55
|
-
else
|
56
|
-
@dir_last_modified[dir] = dir_mtime
|
57
110
|
end
|
58
|
-
else
|
59
|
-
@dir_last_modified.merge!(dir => dir_mtime)
|
60
|
-
end
|
61
111
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
AnimeSeries.new(
|
140
|
-
parent(sarr[sarr.length - 1].path),
|
141
|
-
sorted_subarray
|
142
|
-
) => sorted_subarray
|
143
|
-
)
|
144
|
-
return Hash[ret.sort_by{ |a| a[0].title}]
|
145
|
-
end
|
146
|
-
|
147
|
-
#return the difference of getAired and getWatched
|
148
|
-
def getUnwatched
|
149
|
-
index_anime
|
150
|
-
ret = []
|
151
|
-
#puts @@local_anime
|
152
|
-
@@local_anime.each{ |anime|
|
153
|
-
ret << anime[1] if not anime[1].seen?
|
154
|
-
}
|
155
|
-
return ret
|
156
|
-
end
|
157
|
-
|
158
|
-
#return an AnimeFile array of all mkvs in any dir specified in $pref["dirs"]
|
159
|
-
def getAll
|
160
|
-
index_anime
|
161
|
-
return @@local_anime.values
|
162
|
-
end
|
163
|
-
|
164
|
-
def getAllSeries
|
165
|
-
arr = getAll
|
112
|
+
puts "checking #{dir}" if verbose
|
113
|
+
|
114
|
+
# skip indexing a directory if it hasn't been modified since the last
|
115
|
+
# check (disabled because doesn't save to much time)
|
116
|
+
#
|
117
|
+
#dir_mtime = File::Stat.new(dir).mtime
|
118
|
+
#
|
119
|
+
#if @dir_last_modified.key? dir
|
120
|
+
# if @dir_last_modified[dir] == dir_mtime
|
121
|
+
# next
|
122
|
+
# else
|
123
|
+
# @dir_last_modified[dir] = dir_mtime
|
124
|
+
# end
|
125
|
+
#else
|
126
|
+
# @dir_last_modified.merge!(dir => dir_mtime)
|
127
|
+
#end
|
128
|
+
|
129
|
+
# get all files in the directory and in all subfolders of the directory
|
130
|
+
files = Dir.glob("#{dir}*/*.{mkv,avi,mp4}") + Dir.glob("#{dir}/*.{mkv,avi,mp4}")
|
131
|
+
|
132
|
+
files.each { |file|
|
133
|
+
print "indexing #{file} -> " if verbose
|
134
|
+
seen_this = false
|
135
|
+
|
136
|
+
# we have already indexed this file
|
137
|
+
if @@local_anime != nil and @@local_anime.key?(file)
|
138
|
+
|
139
|
+
# get its seen data
|
140
|
+
seen_this = @@local_anime[file].seen?
|
141
|
+
# get its last modifed data
|
142
|
+
last_modified = File::Stat.new(file).mtime
|
143
|
+
# get wether or not it is accessible
|
144
|
+
@@local_anime[file].accessible = true
|
145
|
+
|
146
|
+
# if we arent forcing or the anime hasn't been modified since the
|
147
|
+
# last check, skip it
|
148
|
+
if not force or last_modified == @@local_anime[file].last_modified
|
149
|
+
puts "unchanged" if verbose
|
150
|
+
ret.merge!(file => @@local_anime[file])
|
151
|
+
next
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
#puts "changed!"
|
156
|
+
|
157
|
+
# okay we are making changes to local_anime
|
158
|
+
made_changes = true
|
159
|
+
|
160
|
+
# this is the anime file we are adding
|
161
|
+
ret.merge!(
|
162
|
+
file => AnimeFile.new(
|
163
|
+
file,
|
164
|
+
seen_this
|
165
|
+
)
|
166
|
+
)
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
#if @@local_anime != nil
|
171
|
+
# @@local_anime.merge!(ret)
|
172
|
+
#else
|
173
|
+
@@local_anime = ret
|
174
|
+
#end
|
175
|
+
|
176
|
+
#pruned = {}
|
177
|
+
#@@local_anime.each{ |a|
|
178
|
+
# pruned.merge!(a[0] => a[1]) if File.exist? a[1].path
|
179
|
+
#}
|
180
|
+
#@@local_anime = pruned
|
181
|
+
made_changes = true if @@local_anime.length != lal
|
182
|
+
if @made_changes
|
183
|
+
self.save
|
184
|
+
changed
|
185
|
+
notify_observers
|
186
|
+
end
|
187
|
+
}
|
188
|
+
end
|
166
189
|
|
167
|
-
|
168
|
-
|
190
|
+
#returns the parent directory of a file
|
191
|
+
def parent(file)
|
192
|
+
return File.basename(File.dirname(file))
|
193
|
+
end
|
169
194
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
195
|
+
#convert an AnimeFile array to a hash structured like
|
196
|
+
#(string)parent => (AnimeFile array)[child0, child1, child2] and return it
|
197
|
+
def makeHash arr
|
198
|
+
#return @empty_hash if arr[0] == nil
|
199
|
+
|
200
|
+
keys = {}
|
201
|
+
hash = {}
|
202
|
+
|
203
|
+
arr.sort_by {|i| i.title}.each { |file|
|
204
|
+
if ! keys.key?(parent file.path)
|
205
|
+
key = AnimeSeries.new parent(file.path)
|
206
|
+
keys.merge! parent(file.path) => key
|
207
|
+
hash.merge! key => []
|
208
|
+
else
|
209
|
+
key = keys[parent file.path]
|
210
|
+
end
|
211
|
+
|
212
|
+
hash[key] << file
|
213
|
+
key += file
|
214
|
+
}
|
215
|
+
hash.sort_by{ |j| j[0].title }.to_h
|
216
|
+
end
|
179
217
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
218
|
+
#return the difference of getAired and getWatched
|
219
|
+
def unwatched
|
220
|
+
makeHash @@local_anime.reject { |f, a| a.seen? }.values
|
221
|
+
end
|
185
222
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
223
|
+
#return an AnimeFile array of all mkvs in any dir specified in $pref["dirs"]
|
224
|
+
def items
|
225
|
+
makeHash @@local_anime.values
|
226
|
+
end
|
190
227
|
|
191
|
-
|
228
|
+
def logWatched(file)
|
229
|
+
open(@pref.parseDir(@pref.get("watch_log")), 'a') do |f|
|
230
|
+
f.puts %x(date).chomp + " ./" + File.basename(file) + " " + @watch_log_tag
|
231
|
+
end
|
232
|
+
end
|
192
233
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
234
|
+
def addWatched(file)
|
235
|
+
@@local_anime[file].watch
|
236
|
+
self.save
|
237
|
+
changed
|
238
|
+
notify_observers
|
239
|
+
end
|
197
240
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
self.save
|
204
|
-
end
|
241
|
+
def rmWatched(path = "")
|
242
|
+
if @@local_anime.key? path
|
243
|
+
@@local_anime[path].unwatch
|
244
|
+
return
|
245
|
+
end
|
205
246
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
247
|
+
r = []
|
248
|
+
@@local_anime.values.each_with_index{ |v, i| r << {Integer(v.seenOn) => @@local_anime.keys[i]} if v.seen? }
|
249
|
+
return if r.length == 0
|
250
|
+
last_watched = (r.sort_by{ |h| h.keys.first}.reverse)[0].values[0]
|
251
|
+
@@local_anime[last_watched].unwatch
|
252
|
+
self.save
|
253
|
+
changed
|
254
|
+
notify_observers
|
255
|
+
end
|
256
|
+
|
257
|
+
def watch(file)
|
258
|
+
@mpvbridge.play file
|
259
|
+
end
|
260
|
+
|
210
261
|
end
|
211
262
|
end
|
212
263
|
end
|