aniview 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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