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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -9
  3. data/bin/aniview +17 -9
  4. data/config/view.yml +3 -0
  5. data/lib/aniview.rb +1 -60
  6. data/modules/animeio/README.md +2 -0
  7. data/modules/animeio/config/daemon.yml +4 -0
  8. data/modules/animeio/config/view.yml +22 -0
  9. data/modules/animeio/lib/animeio.rb +24 -0
  10. data/modules/animeio/lib/animeio/anime_indexer.rb +99 -0
  11. data/modules/animeio/lib/animeio/animefile.rb +91 -0
  12. data/modules/animeio/lib/animeio/animeio.rb +175 -0
  13. data/modules/animeio/lib/animeio/animeio_view.rb +41 -0
  14. data/modules/animeio/lib/animeio/animeseries.rb +61 -0
  15. data/modules/mpv/README.md +2 -0
  16. data/modules/mpv/config/daemon.yml +2 -0
  17. data/modules/mpv/lib/mpv.rb +27 -0
  18. data/modules/mpv/lib/mpv/filename_widget.rb +16 -0
  19. data/modules/mpv/lib/mpv/mpv_controller.rb +85 -0
  20. data/modules/mpv/lib/mpv/time_widget.rb +29 -0
  21. metadata +33 -107
  22. data/lib/aniview/client/aniclient.rb +0 -118
  23. data/lib/aniview/interface/animeio/animefile.rb +0 -93
  24. data/lib/aniview/interface/animeio/animeio.rb +0 -321
  25. data/lib/aniview/interface/animeio/animeseries.rb +0 -60
  26. data/lib/aniview/interface/bridge.rb +0 -11
  27. data/lib/aniview/interface/deluge/delugec.rb +0 -172
  28. data/lib/aniview/interface/deluge/torrentitem.rb +0 -24
  29. data/lib/aniview/interface/item.rb +0 -24
  30. data/lib/aniview/interface/mpv/mpvbridge.rb +0 -149
  31. data/lib/aniview/interface/pref/defaults.json +0 -105
  32. data/lib/aniview/interface/pref/pref.rb +0 -209
  33. data/lib/aniview/interface/pref/prefitem.rb +0 -19
  34. data/lib/aniview/interface/pref/validate.json +0 -105
  35. data/lib/aniview/interface/schedule/schedule.rb +0 -99
  36. data/lib/aniview/interface/schedule/scheduleitem.rb +0 -59
  37. data/lib/aniview/interface/subscription/subscription.rb +0 -123
  38. data/lib/aniview/util/error.rb +0 -9
  39. data/lib/aniview/util/folder_listen.rb +0 -53
  40. data/lib/aniview/util/term.rb +0 -44
  41. data/lib/aniview/util/util.rb +0 -167
  42. data/lib/aniview/view/aiomenu.rb +0 -69
  43. data/lib/aniview/view/color.rb +0 -69
  44. data/lib/aniview/view/delugemenu.rb +0 -38
  45. data/lib/aniview/view/menu.rb +0 -325
  46. data/lib/aniview/view/prefmenu.rb +0 -26
  47. data/lib/aniview/view/schedulemenu.rb +0 -28
  48. data/lib/aniview/view/statusline.rb +0 -60
  49. data/lib/aniview/view/subscriptionmenu.rb +0 -37
  50. data/lib/application.rb +0 -306
  51. data/lib/daemon.rb +0 -188
@@ -1,123 +0,0 @@
1
- require 'simple-rss'
2
- require 'open-uri'
3
-
4
- require_relative "../schedule/scheduleitem"
5
- require_relative '../bridge'
6
-
7
- module Aniview
8
- module Interface
9
- class Subscription < Bridge
10
-
11
- include Observable
12
-
13
- def initialize pref, schedule, delugec, client
14
- @c = client
15
- @pref = pref
16
- @schedule = schedule
17
- @delugec = delugec
18
- #SimpleRSS.feed_tags << :"torrent:magnetURI"
19
- #&lt;![CDATA[
20
- end
21
-
22
- def log s
23
- puts "#{Time.now.to_s} [subscription] " + s
24
- end
25
-
26
- def checkDaemon
27
- if @c.server?
28
- "daemon up"
29
- else
30
- "daemon down"
31
- end
32
- end
33
-
34
- def getLastChecked
35
- @c.lastchecked
36
- end
37
-
38
- def getNextCheck
39
- @c.sendMsg "nextcheck"
40
- end
41
-
42
- def syncMatches
43
- @schedule.mergeItems @c.getItems
44
- end
45
-
46
- def updateFeed
47
- begin
48
- SimpleRSS.item_tags << :"torrent:magnetURI"
49
- @rss = SimpleRSS.parse open(@pref.get("rss_feed")["url"])
50
-
51
- rescue SocketError
52
- @rss = nil
53
- end
54
- end
55
-
56
- def feed
57
- @rss
58
- end
59
-
60
- def match regexp, verbose=false
61
- re = Regexp.new regexp
62
- matches = []
63
- @rss.items.each{ |item|
64
- #log "-> checking against #{item[:title]}" if verbose
65
- re.match item[:title] { matches << item }
66
- }
67
- return matches
68
- end
69
-
70
- def matchAll (verbose: false)
71
- updateFeed if @rss == nil
72
- return [] if @rss == nil
73
-
74
- log "matching all" if verbose
75
-
76
- total_matches = 0
77
- @schedule.schedule.each { |subs|
78
- log "matching #{subs.attributes["r"]}" if verbose
79
- matches = match subs.attributes["r"], verbose
80
- log "found #{matches.length} matches" if verbose
81
- #log "#{matches}" if verbose
82
-
83
- if matches.length >= 1
84
-
85
- downloaddir = @pref.parseDir(subs.attributes["p"]) + "/"
86
- newfile = downloaddir + matches[0][:title]
87
-
88
- next if File.exist? newfile
89
- log "attempting to downloading file" if verbose
90
- log "set download dir to #{newfile}" if verbose
91
- log "#{matches[0].link}" if verbose
92
- s = @delugec.addTorrent matches[0].link, @pref.parseDir(subs.attributes["p"]), verbose: true
93
- log "adding torrent, status #{s}" if verbose
94
- subs.setSeen if s
95
- @schedule.save
96
- total_matches+=1
97
- end
98
- }
99
- log "match complete, #{total_matches} found" if verbose
100
- return total_matches
101
- end
102
-
103
- def forceMatch
104
- @mthread = Thread.new do
105
- updateFeed
106
- matchAll
107
- end
108
- end
109
-
110
- def items
111
- @schedule.items
112
- end
113
-
114
- def editItem loc, newval
115
- @schedule.schedule[loc].setRegexp newval
116
- @schedule.save
117
- changed
118
- notify_observers
119
- end
120
- end
121
- end
122
- end
123
-
@@ -1,9 +0,0 @@
1
- module Aniview
2
- module Error
3
- class InvalidPref < StandardError
4
- def initialize(msg="Your preferences file is invalid")
5
- super
6
- end
7
- end
8
- end
9
- end
@@ -1,53 +0,0 @@
1
- # watch for changes in a folder's existance
2
-
3
- module Aniview
4
- module Util
5
- module FolderListen
6
-
7
- def self.to(dirs, &block)
8
- Listener.new(dirs, &block)
9
- end
10
-
11
- ##
12
- ## @brief Similar to Listen gem but uses polling and is only intended
13
- ## to be used on a small number of files. the Listen gem
14
- ## wouldn't support watching an individual FOLDER to see if
15
- ## the folder went away so this is that!
16
- ##
17
- class Listener
18
- def initialize(dirs, &block)
19
- @dirs = dirs
20
- @block = block
21
- @sleep_duration = 1
22
- @dir_hash = dir_hash
23
- end
24
-
25
- def dir_hash
26
- @dirs.map { |dir| [dir, File.exist?(dir)]}.to_h
27
- end
28
-
29
- def changed?
30
- @dir_hash != dir_hash
31
- end
32
-
33
- def stop
34
- @listen_thread.exit if @listen_thread
35
- end
36
-
37
- def start
38
- Thread.abort_on_exception = true
39
- @listen_thread = Thread.new do
40
- while true
41
- if changed?
42
- @block.call
43
- @dir_hash = dir_hash
44
- end
45
- sleep 1
46
- end
47
- end
48
- end
49
-
50
- end
51
- end
52
- end
53
- end
@@ -1,44 +0,0 @@
1
- module Aniview
2
- module Util
3
- class Term
4
-
5
- def initialize
6
- @tput=Hash[
7
- "smcup" => %x(tput smcup),
8
- "rmcup" => %x(tput rmcup),
9
- "civis" => %x(tput civis),
10
- "cnorm" => %x(tput cnorm),
11
- "el1" => "\e[2K",
12
- "bold" => %x(tput bold),
13
- "nobold" => %x(tput sgr0),
14
- ]
15
- end
16
-
17
- def save; print @tput["smcup"]; return self; end
18
- def restore; print @tput["rmcup"]; return self; end
19
- def hide_cursor; print @tput["civis"]; return self; end
20
- def show_cursor; print @tput["cnorm"]; return self; end
21
- def clear_line; print @tput["el1"]; return self; end
22
- def echo_off; %x(stty -echo); return self; end
23
- def echo_on; %x(stty echo); return self; end
24
- def clear; print "\033[2J"; return self; end
25
- def bold; print @tput["bold"]; return self; end
26
- def nobold; print @tput["nobold"]; return self; end
27
-
28
- def cols; return HighLine::SystemExtensions.terminal_size[0]; end
29
- def rows; return HighLine::SystemExtensions.terminal_size[1]; end
30
-
31
- def self.cols; return HighLine::SystemExtensions.terminal_size[0]; end
32
- def self.rows; return HighLine::SystemExtensions.terminal_size[1]; end
33
-
34
- def getKey
35
- return STDIN.getch.gsub("\r", "enter").gsub(" ", "space").gsub("A", "up").gsub("B", "down").gsub("C", "right").gsub("D", "left").gsub("\e", "skip").gsub("[", "skip")
36
- end
37
-
38
- def reset
39
- self.restore.show_cursor.echo_on
40
- end
41
-
42
- end
43
- end
44
- end
@@ -1,167 +0,0 @@
1
- require 'base64'
2
- require 'readline'
3
-
4
- module Aniview
5
- module Util
6
- def self.readline(term, prompt = "", default = "")
7
- term.bold.echo_on
8
- print "\033[" + String(term.rows) + ";1H" + Aniview::View::Color.white
9
- term.show_cursor
10
- Readline.completion_append_character = ""
11
- Readline.pre_input_hook = -> do
12
- Readline.insert_text "#{default}"
13
- Readline.redisplay
14
- Readline.pre_input_hook = nil
15
- end
16
- input = Readline.readline(prompt, false)
17
- term.hide_cursor.nobold.echo_off.clear
18
- return input
19
- end
20
-
21
- def self.error_message(message)
22
- #use statusline to show error messages
23
- print "\e[#{Term.rows - 1};1H\e[31m #{message}\e[K"
24
- end
25
-
26
- def self.format_duration v
27
- hours = Integer((v-(v%3600))/3600)
28
- minutes = Integer( ((v-(v%60))/60) - (hours * 60))
29
- seconds = Integer(v%60)
30
- seconds = "0" + String(seconds) if seconds < 10
31
- if hours < 1 and minutes < 1
32
- "0:#{seconds}"
33
- else
34
- if hours < 1
35
- return "#{String(minutes)}:#{String(seconds)}"
36
- else
37
- minutes = "0" + String(minutes) if minutes < 10
38
- return "#{String(hours)}:#{String(minutes)}:#{String(seconds)}"
39
- end
40
- end
41
- end
42
-
43
- def self.format_size s
44
- fs = Float(s)
45
-
46
- bytecount = {
47
- "TB" => 1000000000000.0,
48
- "GB" => 1000000000.0,
49
- "MB" => 1000000.0,
50
- "KB" => 1000.0,
51
- "B" => 1.0,
52
- }
53
- r = "TB"
54
- r = "GB" if s < bytecount["TB"]
55
- r = "MB" if s < bytecount["GB"]
56
- r = "KB" if s < bytecount["KB"]
57
-
58
- return String( Float(fs/bytecount[r] * 10.0 ).round / 10.0 ) + r
59
- end
60
-
61
- def self.format_progress p
62
- return "#{Integer(p)}.#{Integer(p * 10.0) % 10}"
63
- end
64
-
65
- def self.parse_format string, d, cols
66
- le = "\e[K\n"
67
-
68
- pstr = []
69
- add_to = ""
70
- buffer_char = []
71
-
72
- mode = "char"
73
-
74
- padding_collected = 0
75
-
76
- string.split('').each { |c|
77
-
78
- if mode == "e"
79
- add_to += String(c)
80
- mode = "char"
81
-
82
- elsif c == '%'
83
- mode = "%"
84
-
85
- elsif c == '$'
86
- mode = "$"
87
-
88
- elsif c == '@'
89
- pstr << add_to
90
- add_to = ""
91
- mode = "@"
92
-
93
- elsif c == "#"
94
- padding_collected += 1
95
-
96
- elsif c == "\\"
97
- mode = "e"
98
-
99
- elsif mode == "@"
100
- buffer_char << c
101
- mode = "char"
102
-
103
- elsif mode == "%"
104
- addstr = d.key?(c) ? String(d[c]) : ""
105
- padding = padding_collected > addstr.length ? " " * (padding_collected - addstr.length) : ""
106
- addstr = padding + addstr
107
- add_to += addstr
108
- mode = "char"
109
- padding_collected = 0
110
-
111
- else
112
- add_to += c
113
-
114
- end
115
- }
116
- pstr << add_to
117
-
118
- buffer_char << " " if buffer_char.length == 0
119
-
120
- midstr = ""
121
- tl = 0
122
- pstr.each{ |s| tl += s.length }
123
- buffer_space = 0
124
- buffer_space = (cols - tl) / (pstr.length - 1) if pstr.length > 1
125
-
126
- addl_space = (cols - tl) % pstr.length
127
-
128
- pstr.each_with_index{ |str, i|
129
- break if i == pstr.length - 1
130
- buffer_ = ""
131
- buffer_ = buffer_char[i] * buffer_space if buffer_space >= 0
132
-
133
- midstr += str + buffer_
134
- }
135
- midstr += pstr[pstr.length - 1]
136
-
137
- return midstr[0..cols-1]
138
- end
139
-
140
- def self.encode_object d
141
- Base64.strict_encode64(Marshal.dump d)
142
- end
143
-
144
- def self.decode_object e
145
- begin
146
- Marshal.load(Base64.decode64(e))
147
- rescue ArgumentError
148
- {}
149
- rescue TypeError
150
- {}
151
- end
152
- end
153
-
154
- def self.mounted_filesystem? dir
155
- %x(mount).split("\n").map { |l|
156
- mounted = /on (.*?) /.match(l)[1]
157
- if mounted == "/"
158
- false
159
- else
160
- dir.split("/").zip(mounted.split("/")).reduce(true) { |m,v|
161
- m and (v[0] == v[1] or v[1] == nil)
162
- }
163
- end
164
- }.reduce { |a,b| a or b}
165
- end
166
- end
167
- end
@@ -1,69 +0,0 @@
1
- require_relative 'menu'
2
- require_relative '../util/util'
3
-
4
- module Aniview
5
- module View
6
- class AioMenu < Menu
7
- include Aniview::Util
8
-
9
- def refresh_attributes
10
- if @items.length > 0
11
- unformatted_P = sum_attribute("p") / @items.length
12
- else
13
- unformatted_P = 0
14
- end
15
-
16
- if sum_attribute("d") > 0
17
- unformatted_Q = sum_attribute("W") * 100.0 / sum_attribute("d")
18
- else
19
- unformatted_Q = 0
20
- end
21
- @attributes = {
22
- "t" => @attributes["t"],
23
- "D" => Util.format_duration(sum_attribute("d")),
24
- "S" => Util.format_size(sum_attribute("s")),
25
- "P" => Util.format_progress(unformatted_P),
26
- "Q" => Util.format_progress(unformatted_Q),
27
- "c" => sum_attribute("c"),
28
- "w" => sum_attribute("w")
29
- }
30
- end
31
-
32
- def sum_attribute k
33
- @items.inject(0) { |mem, c| mem += c[0].attr[k] }
34
- end
35
-
36
- def customControl(key, sel)
37
- return if @items == {}
38
- path = @items.values[sel["out"]][sel["in"]].path
39
-
40
- empty = path == "empty"
41
-
42
- if key == @pref.get("keybindings")["menu_nav_expand"]
43
- expand(sel["out"])
44
- elsif key == "r"
45
- refresh
46
- elsif key == "enter" and not empty
47
-
48
- if sel["in_expanded"]
49
- @interface.watch(@items.values[sel["out"]][sel["in"]])
50
- @interface.logWatched(path)
51
- else
52
- @interface.watch_list(@items.values[sel["out"]])
53
- end
54
- elsif key == @pref.get("keybindings")["anime_set_watched"] and not empty
55
- @interface.addWatched(path)
56
- elsif key == @pref.get("keybindings")["anime_undo_set_watched"]
57
- @interface.rmWatched
58
- elsif key == @pref.get("keybindings")["anime_set_unwatched"] and not empty
59
- @interface.rmWatched(path)
60
- moveCursor("down")
61
- end
62
-
63
- changed
64
- notify_observers
65
- end
66
- end
67
- end
68
- end
69
-