aniview 3.2.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -9
- data/bin/aniview +17 -9
- data/config/view.yml +3 -0
- data/lib/aniview.rb +1 -60
- data/modules/animeio/README.md +2 -0
- data/modules/animeio/config/daemon.yml +4 -0
- data/modules/animeio/config/view.yml +22 -0
- data/modules/animeio/lib/animeio.rb +24 -0
- data/modules/animeio/lib/animeio/anime_indexer.rb +99 -0
- data/modules/animeio/lib/animeio/animefile.rb +91 -0
- data/modules/animeio/lib/animeio/animeio.rb +175 -0
- data/modules/animeio/lib/animeio/animeio_view.rb +41 -0
- data/modules/animeio/lib/animeio/animeseries.rb +61 -0
- data/modules/mpv/README.md +2 -0
- data/modules/mpv/config/daemon.yml +2 -0
- data/modules/mpv/lib/mpv.rb +27 -0
- data/modules/mpv/lib/mpv/filename_widget.rb +16 -0
- data/modules/mpv/lib/mpv/mpv_controller.rb +85 -0
- data/modules/mpv/lib/mpv/time_widget.rb +29 -0
- metadata +33 -107
- data/lib/aniview/client/aniclient.rb +0 -118
- data/lib/aniview/interface/animeio/animefile.rb +0 -93
- data/lib/aniview/interface/animeio/animeio.rb +0 -321
- data/lib/aniview/interface/animeio/animeseries.rb +0 -60
- data/lib/aniview/interface/bridge.rb +0 -11
- data/lib/aniview/interface/deluge/delugec.rb +0 -172
- data/lib/aniview/interface/deluge/torrentitem.rb +0 -24
- data/lib/aniview/interface/item.rb +0 -24
- data/lib/aniview/interface/mpv/mpvbridge.rb +0 -149
- data/lib/aniview/interface/pref/defaults.json +0 -105
- data/lib/aniview/interface/pref/pref.rb +0 -209
- data/lib/aniview/interface/pref/prefitem.rb +0 -19
- data/lib/aniview/interface/pref/validate.json +0 -105
- data/lib/aniview/interface/schedule/schedule.rb +0 -99
- data/lib/aniview/interface/schedule/scheduleitem.rb +0 -59
- data/lib/aniview/interface/subscription/subscription.rb +0 -123
- data/lib/aniview/util/error.rb +0 -9
- data/lib/aniview/util/folder_listen.rb +0 -53
- data/lib/aniview/util/term.rb +0 -44
- data/lib/aniview/util/util.rb +0 -167
- data/lib/aniview/view/aiomenu.rb +0 -69
- data/lib/aniview/view/color.rb +0 -69
- data/lib/aniview/view/delugemenu.rb +0 -38
- data/lib/aniview/view/menu.rb +0 -325
- data/lib/aniview/view/prefmenu.rb +0 -26
- data/lib/aniview/view/schedulemenu.rb +0 -28
- data/lib/aniview/view/statusline.rb +0 -60
- data/lib/aniview/view/subscriptionmenu.rb +0 -37
- data/lib/application.rb +0 -306
- data/lib/daemon.rb +0 -188
@@ -1,209 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'json'
|
3
|
-
require 'observer'
|
4
|
-
|
5
|
-
require_relative 'prefitem'
|
6
|
-
require_relative '../../view/color'
|
7
|
-
require_relative '../bridge'
|
8
|
-
|
9
|
-
module Aniview
|
10
|
-
|
11
|
-
module Interface
|
12
|
-
|
13
|
-
##
|
14
|
-
## @brief Class for preferences.
|
15
|
-
##
|
16
|
-
class Pref < Bridge
|
17
|
-
|
18
|
-
include Observable
|
19
|
-
|
20
|
-
attr_accessor :logger
|
21
|
-
|
22
|
-
##
|
23
|
-
## @brief Initializes pref object, with optional logger
|
24
|
-
##
|
25
|
-
## @param logger The logger
|
26
|
-
##
|
27
|
-
## @return A new pref object
|
28
|
-
##
|
29
|
-
def initialize(logger: nil)
|
30
|
-
@logger = logger
|
31
|
-
conf = Dir.home + "/.config/aniview"
|
32
|
-
@default_file = File.join(File.dirname(__FILE__), "/defaults.json")
|
33
|
-
@pref_file = conf + "/aniview.json"
|
34
|
-
validation_file = File.join(File.dirname(__FILE__), "/validate.json")
|
35
|
-
@validations = read(validation_file)
|
36
|
-
|
37
|
-
FileUtils.mkdir_p(conf) unless File.directory?(conf)
|
38
|
-
load
|
39
|
-
save unless File.exist?(@pref_file)
|
40
|
-
end
|
41
|
-
|
42
|
-
##
|
43
|
-
## @brief converts a directory like "~/movies" to
|
44
|
-
## "/users/shinji/movies/"
|
45
|
-
##
|
46
|
-
## @param path The path to parse
|
47
|
-
##
|
48
|
-
## @return the parsed directory string
|
49
|
-
##
|
50
|
-
def parseDir(path)
|
51
|
-
{
|
52
|
-
"$airing_dir" => @pref["airing_dir"],
|
53
|
-
"$conf_dir" => @pref["conf_dir"],
|
54
|
-
"~" => Dir.home
|
55
|
-
}.inject(path) { |path, r| path.gsub(r[0], r[1]) }
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
## @brief gets a preference
|
60
|
-
##
|
61
|
-
## @param key The key
|
62
|
-
##
|
63
|
-
## @return the preference at key or nil if there is no such preference
|
64
|
-
##
|
65
|
-
def get(key)
|
66
|
-
@pref[key] if @pref.key?(key)
|
67
|
-
end
|
68
|
-
|
69
|
-
##
|
70
|
-
## @brief Validates and sets a preference
|
71
|
-
##
|
72
|
-
## @param trail The key or array of keys that specify where
|
73
|
-
## the preference is stored
|
74
|
-
## @param destination The new value for the preference
|
75
|
-
##
|
76
|
-
## @return nil
|
77
|
-
##
|
78
|
-
def set(trail, destination)
|
79
|
-
trail = [trail] if trail.class == String
|
80
|
-
|
81
|
-
destination = case destination
|
82
|
-
when "true"
|
83
|
-
true
|
84
|
-
when "false"
|
85
|
-
false
|
86
|
-
else
|
87
|
-
destination
|
88
|
-
end
|
89
|
-
|
90
|
-
return unless valid_preference?(trail, destination)
|
91
|
-
|
92
|
-
trail[0...-1].inject(@pref, :fetch)[trail.last] = destination
|
93
|
-
save
|
94
|
-
changed
|
95
|
-
notify_observers
|
96
|
-
end
|
97
|
-
|
98
|
-
def pref_type(trail)
|
99
|
-
trail.inject(@validations, :fetch)
|
100
|
-
end
|
101
|
-
|
102
|
-
def get_pref(trail)
|
103
|
-
trail.inject(@pref, :fetch)
|
104
|
-
end
|
105
|
-
|
106
|
-
##
|
107
|
-
## @brief validates a preference
|
108
|
-
##
|
109
|
-
## @param trail The array of keys that specify where the
|
110
|
-
## preference is stored
|
111
|
-
## @param destination The new value for the preference
|
112
|
-
##
|
113
|
-
## @return true if preference is valid, false otherwise
|
114
|
-
##
|
115
|
-
def valid_preference?(trail, destination)
|
116
|
-
skeys = [ "space", "up", "down", "left", "right", "enter" ]
|
117
|
-
|
118
|
-
case pref_type(trail)
|
119
|
-
when "key"
|
120
|
-
destination.length == 1 or skeys.include?(destination)
|
121
|
-
when "path"
|
122
|
-
destination.split(":").map { |d| Dir.exist?(parseDir d) }.reduce { |m, n| m and n }
|
123
|
-
when "color"
|
124
|
-
Aniview::View::Color.respond_to?(destination)
|
125
|
-
when "int"
|
126
|
-
destination.scan(/\D/).empty? and destination.length > 1
|
127
|
-
when "boolean"
|
128
|
-
destination.class == TrueClass or destination.class == FalseClass
|
129
|
-
when "locked"
|
130
|
-
false
|
131
|
-
else
|
132
|
-
true
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
##
|
137
|
-
## @brief gets an array of PrefItems to be displayed in the menu
|
138
|
-
##
|
139
|
-
## @return an array of PrefItems
|
140
|
-
##
|
141
|
-
def items
|
142
|
-
ignore = {
|
143
|
-
"local_anime" => true,
|
144
|
-
"schedule" => true,
|
145
|
-
}
|
146
|
-
@pref.map{ |title, preference|
|
147
|
-
next if ignore.key? title
|
148
|
-
if preference.class == Hash
|
149
|
-
preference.map { |subtitle, subpreference|
|
150
|
-
PrefItem.new(title + "_" + subtitle, subpreference, [title, subtitle])
|
151
|
-
}
|
152
|
-
else
|
153
|
-
preference = preference.join(":") if preference.class == Array
|
154
|
-
PrefItem.new(title, preference, [title])
|
155
|
-
end
|
156
|
-
}.flatten.compact
|
157
|
-
end
|
158
|
-
|
159
|
-
##
|
160
|
-
## @brief saves the prefs to disk
|
161
|
-
##
|
162
|
-
## @return nil
|
163
|
-
##
|
164
|
-
def save
|
165
|
-
File.open(@pref_file, "w") { |f| f.write(JSON.pretty_generate(@pref)) }
|
166
|
-
end
|
167
|
-
|
168
|
-
##
|
169
|
-
## @brief loads the prefs from file
|
170
|
-
##
|
171
|
-
## @param file The file
|
172
|
-
##
|
173
|
-
## @return nil
|
174
|
-
##
|
175
|
-
def load
|
176
|
-
@pref = read(@pref_file) || read(@default_file)
|
177
|
-
changed
|
178
|
-
notify_observers
|
179
|
-
end
|
180
|
-
|
181
|
-
##
|
182
|
-
## @brief reads json from a file
|
183
|
-
##
|
184
|
-
## @param file The file
|
185
|
-
##
|
186
|
-
## @return parsed json
|
187
|
-
##
|
188
|
-
def read(file)
|
189
|
-
begin
|
190
|
-
File.open(file, "r") { |f|
|
191
|
-
json = f.read
|
192
|
-
if json.empty?
|
193
|
-
return nil
|
194
|
-
else
|
195
|
-
begin
|
196
|
-
JSON.parse json
|
197
|
-
rescue JSON::ParserError
|
198
|
-
raise Aniview::Error::InvalidPref.new
|
199
|
-
end
|
200
|
-
end
|
201
|
-
}
|
202
|
-
rescue Errno::ENOENT
|
203
|
-
return nil
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require_relative '../item'
|
2
|
-
|
3
|
-
module Aniview
|
4
|
-
module Interface
|
5
|
-
class PrefItem < Item
|
6
|
-
def initialize(title, value, path_ = [])
|
7
|
-
@path = path_
|
8
|
-
@attr = {
|
9
|
-
"t" => title,
|
10
|
-
"v" => value,
|
11
|
-
}
|
12
|
-
end
|
13
|
-
|
14
|
-
def path
|
15
|
-
return @path
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"keybindings" :
|
3
|
-
{
|
4
|
-
"goto_preferences" : "key",
|
5
|
-
"goto_unwatched" : "key",
|
6
|
-
"goto_library" : "key",
|
7
|
-
"goto_torrents" : "key",
|
8
|
-
"goto_schedule" : "key",
|
9
|
-
"goto_subscriptions" : "key",
|
10
|
-
"anime_set_watched" : "key",
|
11
|
-
"anime_set_unwatched" : "key",
|
12
|
-
"anime_undo_set_watched" : "key",
|
13
|
-
"torrents_pause" : "key",
|
14
|
-
"torrents_remove" : "key",
|
15
|
-
"torrents_remove_data" : "key",
|
16
|
-
"schedule_add_item" : "key",
|
17
|
-
"schedule_delete_item" : "key",
|
18
|
-
"schedule_edit_item" : "key",
|
19
|
-
"subscriptions_edit" : "key",
|
20
|
-
"menu_nav_up" : "key",
|
21
|
-
"menu_nav_down" : "key",
|
22
|
-
"menu_nav_expand" : "key"
|
23
|
-
},
|
24
|
-
"anime_locations" : "path",
|
25
|
-
"airing_dir" : "path",
|
26
|
-
"clr" :
|
27
|
-
{
|
28
|
-
"main" : "color",
|
29
|
-
"primary" : "color",
|
30
|
-
"secondary" : "color",
|
31
|
-
"selected" : "color"
|
32
|
-
},
|
33
|
-
"menu_titles" :
|
34
|
-
{
|
35
|
-
"unwatched" : "any",
|
36
|
-
"library" : "any",
|
37
|
-
"torrents" : "any",
|
38
|
-
"preferences" : "any",
|
39
|
-
"schedule" : "any",
|
40
|
-
"subscriptions" : "any"
|
41
|
-
|
42
|
-
},
|
43
|
-
"format_library" :
|
44
|
-
{
|
45
|
-
"title" : "any",
|
46
|
-
"parent" : "any",
|
47
|
-
"child" : "any"
|
48
|
-
},
|
49
|
-
"format_library_unwatched" :
|
50
|
-
{
|
51
|
-
"title" : "any",
|
52
|
-
"parent" : "any",
|
53
|
-
"child" : "any"
|
54
|
-
},
|
55
|
-
"format_torrents" :
|
56
|
-
{
|
57
|
-
"title" : "any",
|
58
|
-
"parent" : "any"
|
59
|
-
},
|
60
|
-
"format_schedule" :
|
61
|
-
{
|
62
|
-
"title" : "any",
|
63
|
-
"parent" : "any"
|
64
|
-
},
|
65
|
-
"format_preferences" :
|
66
|
-
{
|
67
|
-
"title" : "any",
|
68
|
-
"parent" : "any"
|
69
|
-
},
|
70
|
-
"format_subscriptions" :
|
71
|
-
{
|
72
|
-
"title" : "any",
|
73
|
-
"parent" : "any"
|
74
|
-
},
|
75
|
-
"format_status" : "any",
|
76
|
-
"deluge_config" :
|
77
|
-
{
|
78
|
-
"host" : "any",
|
79
|
-
"port" : "int",
|
80
|
-
"login" : "any",
|
81
|
-
"password" : "any",
|
82
|
-
"cli_executable" : "any"
|
83
|
-
},
|
84
|
-
"rss_feed" :
|
85
|
-
{
|
86
|
-
"url" : "any",
|
87
|
-
"refresh_interval" : "int"
|
88
|
-
},
|
89
|
-
"daemon" :
|
90
|
-
{
|
91
|
-
"port" : "int"
|
92
|
-
},
|
93
|
-
"avs_files": {
|
94
|
-
"create?": "boolean",
|
95
|
-
"only_on_mounted_fs?": "boolean"
|
96
|
-
},
|
97
|
-
"set_watched_percentage" : "int",
|
98
|
-
"log_file" : "path",
|
99
|
-
"daemon_log_file" : "path",
|
100
|
-
"watch_log" : "path",
|
101
|
-
"conf_dir" : "locked",
|
102
|
-
"mpv_args" : "any",
|
103
|
-
"local_anime" : "any",
|
104
|
-
"schedule" : "any"
|
105
|
-
}
|
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
require_relative 'scheduleitem'
|
4
|
-
require_relative '../../util/util'
|
5
|
-
require_relative '../bridge'
|
6
|
-
|
7
|
-
module Aniview
|
8
|
-
module Interface
|
9
|
-
class Schedule < Bridge
|
10
|
-
|
11
|
-
include Aniview::Util
|
12
|
-
|
13
|
-
include Observable
|
14
|
-
|
15
|
-
attr_accessor :schedule
|
16
|
-
|
17
|
-
def initialize pref
|
18
|
-
@pref = pref
|
19
|
-
load
|
20
|
-
end
|
21
|
-
|
22
|
-
def empty?
|
23
|
-
if @schedule == nil or @schedule.length == 0
|
24
|
-
@schedule = [ScheduleItem.new("no schedule", "")]
|
25
|
-
save
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def items
|
30
|
-
empty?
|
31
|
-
@schedule.map{ |t| [t,t] }.to_h
|
32
|
-
end
|
33
|
-
|
34
|
-
def getAllCereal
|
35
|
-
r=""
|
36
|
-
getAll.each { |si| r+=si.cereal }
|
37
|
-
r
|
38
|
-
end
|
39
|
-
|
40
|
-
def mergeItems _items
|
41
|
-
_items.each { |item|
|
42
|
-
@schedule.each { |schedule_item|
|
43
|
-
if item.id == schedule_item.id
|
44
|
-
m = [schedule_item.attributes["m"], item.attributes["m"]]
|
45
|
-
if m[0] != m[1]
|
46
|
-
schedule_item.setmatched m[1]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
}
|
50
|
-
}
|
51
|
-
save
|
52
|
-
end
|
53
|
-
|
54
|
-
def addItem item
|
55
|
-
@schedule.delete_at 0 if @schedule[0].attributes["t"] == "no schedule"
|
56
|
-
|
57
|
-
new_item = ScheduleItem.new(item, @pref.get("airing_dir"))
|
58
|
-
|
59
|
-
FileUtils.mkdir_p @pref.parseDir new_item.attributes["p"]
|
60
|
-
|
61
|
-
@schedule << new_item
|
62
|
-
|
63
|
-
save
|
64
|
-
end
|
65
|
-
|
66
|
-
def editItem loc, val
|
67
|
-
old_dir = @pref.parseDir @schedule[loc].attributes["p"]
|
68
|
-
@schedule[loc].setTitle val
|
69
|
-
new_dir = @pref.parseDir @schedule[loc].attributes["p"]
|
70
|
-
|
71
|
-
FileUtils.mv old_dir, new_dir unless old_dir.downcase == new_dir.downcase
|
72
|
-
|
73
|
-
save
|
74
|
-
end
|
75
|
-
|
76
|
-
def removeItem loc
|
77
|
-
@schedule.delete_at loc
|
78
|
-
save
|
79
|
-
end
|
80
|
-
|
81
|
-
def save
|
82
|
-
@pref.set "schedule", (Util.encode_object @schedule)
|
83
|
-
changed
|
84
|
-
notify_observers
|
85
|
-
end
|
86
|
-
|
87
|
-
def load
|
88
|
-
#@pref.load
|
89
|
-
raw = @pref.get "schedule"
|
90
|
-
if not raw == nil and raw.class == String
|
91
|
-
@schedule = Util.decode_object raw
|
92
|
-
else
|
93
|
-
empty?
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require_relative '../item'
|
2
|
-
require 'securerandom'
|
3
|
-
|
4
|
-
module Aniview
|
5
|
-
module Interface
|
6
|
-
class ScheduleItem < Item
|
7
|
-
def initialize(title, dir)
|
8
|
-
@dirpath = dir
|
9
|
-
@basepath = escapePath title
|
10
|
-
|
11
|
-
@attr = {
|
12
|
-
"t" => title,
|
13
|
-
"f" => title[0..4] + "…",
|
14
|
-
"r" => title,
|
15
|
-
"p" => @dirpath + @basepath,
|
16
|
-
"m" => "never"
|
17
|
-
}
|
18
|
-
|
19
|
-
@lastseen = 0
|
20
|
-
@id = SecureRandom.uuid
|
21
|
-
end
|
22
|
-
|
23
|
-
def updataDir nd
|
24
|
-
@dirpath = nd
|
25
|
-
@attr["p"] = nd + @basepath
|
26
|
-
end
|
27
|
-
|
28
|
-
def escapePath path
|
29
|
-
path_ = path.gsub(":", "_")
|
30
|
-
path_.gsub("/", ":")
|
31
|
-
end
|
32
|
-
|
33
|
-
def setTitle newtitle
|
34
|
-
@attr["t"] = newtitle
|
35
|
-
@attr["f"] = newtitle[0..4] + "…"
|
36
|
-
@attr["p"] = @dirpath + escapePath(newtitle)
|
37
|
-
end
|
38
|
-
|
39
|
-
def setRegexp regexp
|
40
|
-
@attr["r"] = regexp
|
41
|
-
end
|
42
|
-
|
43
|
-
def setSeen
|
44
|
-
@lastseen = Time.now.to_s
|
45
|
-
@attr["m"] = @lastseen
|
46
|
-
end
|
47
|
-
|
48
|
-
def setmatched date
|
49
|
-
@attr["m"] = date
|
50
|
-
end
|
51
|
-
|
52
|
-
def id
|
53
|
-
id = SecureRandom.uuid if @id == nil
|
54
|
-
@id
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|