aniview 1.3.0 → 2.0.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/bin/aniview +2 -3
  3. data/lib/aniview.rb +50 -243
  4. data/lib/aniview/client/aniclient.rb +111 -53
  5. data/lib/aniview/interface/animeio/animefile.rb +73 -64
  6. data/lib/aniview/interface/animeio/animeio.rb +184 -181
  7. data/lib/aniview/interface/animeio/animeseries.rb +53 -48
  8. data/lib/aniview/interface/deluge/delugec.rb +158 -153
  9. data/lib/aniview/interface/deluge/torrentitem.rb +21 -16
  10. data/lib/aniview/interface/item.rb +21 -17
  11. data/lib/aniview/interface/mpv/mpvbridge.rb +78 -73
  12. data/lib/aniview/interface/pref/pref.rb +135 -132
  13. data/lib/aniview/interface/pref/prefitem.rb +16 -15
  14. data/lib/aniview/interface/schedule/schedule.rb +89 -83
  15. data/lib/aniview/interface/schedule/scheduleitem.rb +54 -51
  16. data/lib/aniview/interface/subscription/subscription.rb +111 -108
  17. data/lib/aniview/util/term.rb +39 -36
  18. data/lib/aniview/util/util.rb +149 -0
  19. data/lib/aniview/view/aiomenu.rb +68 -63
  20. data/lib/aniview/view/color.rb +69 -67
  21. data/lib/aniview/view/delugemenu.rb +44 -40
  22. data/lib/aniview/view/menu.rb +281 -286
  23. data/lib/aniview/view/prefmenu.rb +36 -34
  24. data/lib/aniview/view/schedulemenu.rb +32 -29
  25. data/lib/aniview/view/statusline.rb +19 -14
  26. data/lib/aniview/view/subscriptionmenu.rb +35 -32
  27. data/lib/application.rb +260 -0
  28. data/lib/daemon.rb +174 -0
  29. metadata +5 -12
  30. data/bin/aniviewd +0 -20
  31. data/lib/aniview/util/alogger.rb +0 -18
  32. data/lib/aniview/util/command.rb +0 -25
  33. data/lib/aniview/util/format.rb +0 -123
  34. data/lib/aniview/util/online.rb +0 -12
  35. data/lib/aniview/util/serializer.rb +0 -19
  36. data/lib/aniview/util/stringhelp.rb +0 -50
  37. data/lib/aniview/view/emote.rb +0 -345
  38. data/lib/aniviewd.rb +0 -179
@@ -1,75 +1,84 @@
1
1
  require 'streamio-ffmpeg'
2
2
  require 'date'
3
3
 
4
- require_relative '../../util/format'
4
+ require_relative '../../util/util'
5
5
  require_relative '../item'
6
6
 
7
- class AnimeFile < Item
8
- def initialize(path_, seen = false)
9
- @watched = seen
10
- @watched_on = 0
11
- @path = path_
7
+ module Aniview
8
+ module Interface
9
+ class AnimeFile < Item
12
10
 
13
- if (@path == "empty")
14
- @attr = {
15
- "t" => "empty",
16
- "d" => 0,
17
- "D" => "0",
18
- "s" => 0,
19
- "S" => "0",
20
- "r" => 0x0,
21
- "a" => "n.a.",
22
- "v" => "",
23
- "l" => "",
24
- "f" => "",
25
- "b" => "",
26
- }
27
- else
28
- mov = FFMPEG::Movie.new(@path)
29
-
30
- @attr = {
31
- "t" => self.string,
32
- "d" => mov.duration,
33
- "D" => Format.format_duration(mov.duration),
34
- "s" => mov.size,
35
- "S" => Format.format_size(mov.size),
36
- "r" => mov.resolution,
37
- "a" => mov.audio_codec,
38
- "v" => mov.video_codec,
39
- "l" => mov.colorspace,
40
- "f" => mov.frame_rate,
41
- "b" => String(mov.bitrate) + "kb/s",
42
- }
43
- end
11
+ include Aniview::Util
44
12
 
45
- end
13
+ attr_accessor :last_modified
14
+ attr_accessor :path
46
15
 
47
- def seen?
48
- return @watched
49
- end
16
+ def initialize(path_, seen = false)
17
+ @watched = seen
18
+ begin
19
+ @last_modified = File::Stat.new(path_).mtime
20
+ rescue Errno::ENOENT
21
+ @last_modified = "0"
22
+ end
23
+ @watched_on = 0
24
+ @path = path_
50
25
 
51
- def seenOn
52
- return @watched_on
53
- end
26
+ @attr = {
27
+ "t" => "empty",
28
+ "d" => 0,
29
+ "D" => "0",
30
+ "s" => 0,
31
+ "S" => "0",
32
+ "r" => 0x0,
33
+ "a" => "n.a.",
34
+ "v" => "",
35
+ "l" => "",
36
+ "f" => "",
37
+ "b" => "",
38
+ }
39
+
40
+ if (@path == "empty")
41
+ else
42
+ mov = FFMPEG::Movie.new(@path)
43
+
44
+ @attr = {
45
+ "t" => self.string,
46
+ "d" => mov.duration,
47
+ "D" => Util.format_duration(mov.duration),
48
+ "s" => mov.size,
49
+ "S" => Util.format_size(mov.size),
50
+ "r" => mov.resolution,
51
+ "a" => mov.audio_codec,
52
+ "v" => mov.video_codec,
53
+ "l" => mov.colorspace,
54
+ "f" => mov.frame_rate,
55
+ "b" => String(mov.bitrate) + "kb/s",
56
+ }
57
+ end
58
+
59
+ end
60
+
61
+ def seen?
62
+ return @watched
63
+ end
64
+
65
+ def seenOn
66
+ return @watched_on
67
+ end
68
+
69
+ def watch
70
+ @watched = true
71
+ @watched_on = DateTime.now.strftime('%Q')
72
+ end
73
+
74
+ def unwatch
75
+ @watched = false
76
+ end
77
+
78
+ def string
79
+ return (File.basename("#{@path}").gsub(/\s*\[.+?\]\s*/) {}).gsub(/(\.mkv)|(\.avi)|(\.mp4)/, "").gsub("_", " ").gsub(/\s*\(.+?\)\s*/) {}
80
+ end
54
81
 
55
- def watch
56
- @watched = true
57
- @watched_on = DateTime.now.strftime('%Q')
58
- end
59
-
60
- def unwatch
61
- @watched = false
62
- end
63
-
64
- def path
65
- return @path
66
- end
67
-
68
- def string
69
- return (File.basename("#{@path}").gsub(/\s*\[.+?\]\s*/) {}).gsub(/(\.mkv)|(\.avi)|(\.mp4)/, "").gsub("_", " ").gsub(/\s*\(.+?\)\s*/) {}
70
- end
71
-
72
- def attributes
73
- return @attr
74
- end
82
+ end
83
+ end
75
84
  end
@@ -1,185 +1,188 @@
1
1
  require 'mkmf'
2
- require 'base64'
2
+ require 'fileutils'
3
3
  require_relative 'animefile'
4
4
  require_relative 'animeseries'
5
-
6
- class AnimeIO
7
-
8
- def initialize(pref, mpvbridge)
9
- @pref = pref
10
- @mpvbridge = mpvbridge
11
- @empty_hash = {
12
- "empty" => AnimeFile.new(
13
- "empty",
14
- {
15
- "d" => 0,
16
- "s" => 0,
17
- "r" => "0x0",
18
- "a" => "n/a"
19
- }
20
- )
21
- }
22
- @watch_log_tag = "♪"
23
-
24
- self.load
25
- index_anime
26
- end
27
-
28
- def save
29
- @pref.set "local_anime", Base64.encode64(Marshal.dump @@local_anime)
30
- end
31
-
32
- def load
33
- raw = @pref.get "local_anime"
34
- if not raw == nil and raw.class == String
35
- @@local_anime = Marshal.load(Base64.decode64(raw))
36
- else
37
- @@local_anime = {}
38
- end
39
- end
40
-
41
- def index_anime(force: false, verbose: false)
42
- ret = {}
43
- (@pref.get("anime_locations").split(":")).each { |dir|
44
-
45
- dir = @pref.parseDir dir
46
-
47
- Dir.glob("#{dir}*/*.{mkv,avi,mp4}").each { |file|
48
- puts "indexing #{file}" if verbose
49
- seen_this = false
50
- if @@local_anime != nil and @@local_anime.key?(file)
51
- seen_this = @@local_anime[file].seen?
52
- if not force
53
- ret.merge!(file => @@local_anime[file])
54
- next
55
- end
56
- end
57
- ret.merge!(
58
- file => AnimeFile.new(
59
- file,
60
- seen_this
61
- )
62
- )
63
-
64
- }
65
- }
66
- if @@local_anime != nil
67
- @@local_anime.merge!(ret)
68
- else
69
- @@local_anime = ret
70
- end
71
-
72
- pruned = {}
73
- @@local_anime.each{ |a|
74
- pruned.merge!(a[0] => a[1]) if File.exist? a[1].path
75
- }
76
- @@local_anime = pruned
77
-
78
- self.save
79
- end
80
-
81
- #returns the parent directory of a file
82
- def parent(file)
83
- return File.basename(File.dirname(file))
84
- end
85
-
86
- #convert an AnimeFile array to a hash structured like
87
- #(string)parent => (AnimeFile array)[child0, child1, child2] and return it
88
- def makeHash(arr)
89
- return @empty_hash if arr[0] == nil
90
- ret = {}
91
- subarray = []
92
-
93
-
94
- sarr = arr.sort_by {|s| s.path}
95
- last_parent = parent sarr[0].path
96
-
97
- (sarr).each { |animefile|
98
-
99
- this_parent = parent animefile.path
100
-
101
- if this_parent != last_parent
102
- ret.merge!(
103
- AnimeSeries.new(
104
- last_parent,
105
- subarray
106
- ) => subarray)
107
- subarray = [animefile]
108
- else
109
- subarray << animefile
110
- end
111
-
112
- last_parent = this_parent
113
-
114
- }
115
- ret.merge!(
116
- AnimeSeries.new(
117
- parent(sarr[sarr.length - 1].path),
118
- subarray
119
- ) => subarray
120
- )
121
- return Hash[ret.sort_by{ |a| a[0].title}]
122
- end
123
-
124
- #return the difference of getAired and getWatched
125
- def getUnwatched
126
- ret = []
127
- #puts @@local_anime
128
- @@local_anime.each{ |anime|
129
- ret << anime[1] if not anime[1].seen?
130
- }
131
- return ret
132
- end
133
-
134
- #return an AnimeFile array of all mkvs in any dir specified in $pref["dirs"]
135
- def getAll
136
- return @@local_anime.values
137
- end
138
-
139
- def getAllSeries
140
- arr = getAll
141
-
142
- last_parent = parent arr[0].path
143
- ret = [ last_parent ]
144
-
145
- arr.each { |animefile|
146
- this_parent = parent animefile.path
147
- if this_parent != last_parent
148
- ret << this_parent
149
- end
150
- last_parent = this_parent
151
- }
152
- return ret
153
- end
154
-
155
- def logWatched(file)
156
- open(@pref.parseDir(@pref.get("watch_log")), 'a') do |f|
157
- f.puts %x(date).chomp + " ./" + File.basename(file) + " " + @watch_log_tag
158
- end
159
- end
160
-
161
- def addWatched(file)
162
- @@local_anime[file].watch
163
- self.save
164
- end
165
-
166
- def rmWatched(path = "zoz")
167
-
168
- if @@local_anime.key? path
169
- @@local_anime[path].unwatch
170
- return
171
- end
172
-
173
- r = []
174
- @@local_anime.values.each_with_index{ |v, i| r << {Integer(v.seenOn) => @@local_anime.keys[i]} if v.seen? }
175
- return if r.length == 0
176
- last_watched = (r.sort_by{ |h| h.keys.first}.reverse)[0].values[0]
177
- @@local_anime[last_watched].unwatch
178
- self.save
179
- end
180
-
181
- #run mpv
182
- def watch(file)
183
- @mpvbridge.play file
184
- end
5
+ require_relative '../../util/util'
6
+
7
+ module Aniview
8
+ module Interface
9
+ include Aniview::Util
10
+ class AnimeIO
11
+ def initialize(pref, mpvbridge)
12
+ @pref = pref
13
+ @mpvbridge = mpvbridge
14
+ @empty_hash = {
15
+ "empty" => AnimeFile.new(
16
+ "empty"
17
+ )
18
+ }
19
+ @watch_log_tag = "♪"
20
+
21
+ self.load
22
+ index_anime
23
+ end
24
+
25
+ def save
26
+ @pref.set "local_anime", Util.encode_object(@@local_anime)
27
+ end
28
+
29
+ def load
30
+ raw = @pref.get "local_anime"
31
+ if not raw == nil and raw.class == String
32
+ @@local_anime = Util.decode_object raw
33
+ else
34
+ @@local_anime = {}
35
+ end
36
+ end
37
+
38
+ def index_anime(force: false, verbose: false)
39
+ ret = {}
40
+ (@pref.get("anime_locations").split(":")).each { |dir|
41
+
42
+ dir = @pref.parseDir dir
43
+
44
+ files = Dir.glob("#{dir}*/*.{mkv,avi,mp4}") + Dir.glob("#{dir}/*.{mkv,avi,mp4}")
45
+
46
+ files.each { |file|
47
+ puts "indexing #{file}" if verbose
48
+ seen_this = false
49
+ if @@local_anime != nil and @@local_anime.key?(file)
50
+ seen_this = @@local_anime[file].seen?
51
+
52
+ last_modified = File::Stat.new(file).mtime
53
+
54
+ if not force or last_modified == @@local_anime[file].last_modified
55
+ ret.merge!(file => @@local_anime[file])
56
+ next
57
+ end
58
+ end
59
+ ret.merge!(
60
+ file => AnimeFile.new(
61
+ file,
62
+ seen_this
63
+ )
64
+ )
65
+ }
66
+ }
67
+ if @@local_anime != nil
68
+ @@local_anime.merge!(ret)
69
+ else
70
+ @@local_anime = ret
71
+ end
72
+
73
+ pruned = {}
74
+ @@local_anime.each{ |a|
75
+ pruned.merge!(a[0] => a[1]) if File.exist? a[1].path
76
+ }
77
+ @@local_anime = pruned
78
+
79
+ self.save
80
+ end
81
+
82
+ #returns the parent directory of a file
83
+ def parent(file)
84
+ return File.basename(File.dirname(file))
85
+ end
86
+
87
+ #convert an AnimeFile array to a hash structured like
88
+ #(string)parent => (AnimeFile array)[child0, child1, child2] and return it
89
+ def makeHash(arr)
90
+ return @empty_hash if arr[0] == nil
91
+ ret = {}
92
+ subarray = []
93
+
94
+
95
+ sarr = arr.sort_by {|s| s.path}
96
+ last_parent = parent sarr[0].path
97
+
98
+ (sarr).each { |animefile|
99
+
100
+ this_parent = parent animefile.path
101
+
102
+ if this_parent != last_parent
103
+ ret.merge!(
104
+ AnimeSeries.new(
105
+ last_parent,
106
+ subarray
107
+ ) => subarray)
108
+ subarray = [animefile]
109
+ else
110
+ subarray << animefile
111
+ end
112
+
113
+ last_parent = this_parent
114
+
115
+ }
116
+ ret.merge!(
117
+ AnimeSeries.new(
118
+ parent(sarr[sarr.length - 1].path),
119
+ subarray
120
+ ) => subarray
121
+ )
122
+ return Hash[ret.sort_by{ |a| a[0].title}]
123
+ end
124
+
125
+ #return the difference of getAired and getWatched
126
+ def getUnwatched
127
+ ret = []
128
+ #puts @@local_anime
129
+ @@local_anime.each{ |anime|
130
+ ret << anime[1] if not anime[1].seen?
131
+ }
132
+ return ret
133
+ end
134
+
135
+ #return an AnimeFile array of all mkvs in any dir specified in $pref["dirs"]
136
+ def getAll
137
+ return @@local_anime.values
138
+ end
139
+
140
+ def getAllSeries
141
+ arr = getAll
142
+
143
+ last_parent = parent arr[0].path
144
+ ret = [ last_parent ]
145
+
146
+ arr.each { |animefile|
147
+ this_parent = parent animefile.path
148
+ if this_parent != last_parent
149
+ ret << this_parent
150
+ end
151
+ last_parent = this_parent
152
+ }
153
+ return ret
154
+ end
155
+
156
+ def logWatched(file)
157
+ open(@pref.parseDir(@pref.get("watch_log")), 'a') do |f|
158
+ f.puts %x(date).chomp + " ./" + File.basename(file) + " " + @watch_log_tag
159
+ end
160
+ end
161
+
162
+ def addWatched(file)
163
+ @@local_anime[file].watch
164
+ self.save
165
+ end
166
+
167
+ def rmWatched(path = "zoz")
168
+
169
+ if @@local_anime.key? path
170
+ @@local_anime[path].unwatch
171
+ return
172
+ end
173
+
174
+ r = []
175
+ @@local_anime.values.each_with_index{ |v, i| r << {Integer(v.seenOn) => @@local_anime.keys[i]} if v.seen? }
176
+ return if r.length == 0
177
+ last_watched = (r.sort_by{ |h| h.keys.first}.reverse)[0].values[0]
178
+ @@local_anime[last_watched].unwatch
179
+ self.save
180
+ end
181
+
182
+ #run mpv
183
+ def watch(file)
184
+ @mpvbridge.play file
185
+ end
186
+ end
187
+ end
185
188
  end