aniview 0.3.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aniview.rb +59 -10
- data/lib/aniview/client/aniclient.rb +50 -0
- data/lib/aniview/interface/animeio/animeio.rb +2 -7
- data/lib/aniview/interface/deluge/delugec.rb +146 -49
- data/lib/aniview/interface/deluge/torrentitem.rb +4 -1
- data/lib/aniview/interface/pref/defaults.json +95 -66
- data/lib/aniview/interface/pref/pref.rb +18 -10
- data/lib/aniview/interface/pref/validate.json +32 -2
- data/lib/aniview/interface/schedule/schedule.rb +74 -0
- data/lib/aniview/interface/schedule/scheduleitem.rb +46 -0
- data/lib/aniview/interface/subscription/subscription.rb +102 -0
- data/lib/aniview/interface/subscription/subscriptiondaemon.rb +42 -0
- data/lib/aniview/util/alogger.rb +12 -3
- data/lib/aniview/util/command.rb +1 -0
- data/lib/aniview/util/format.rb +106 -105
- data/lib/aniview/util/stringhelp.rb +50 -0
- data/lib/aniview/view/delugemenu.rb +14 -3
- data/lib/aniview/view/menu.rb +2 -2
- data/lib/aniview/view/schedulemenu.rb +36 -0
- data/lib/aniview/view/subscriptionmenu.rb +35 -0
- data/lib/aniviewd.rb +167 -0
- metadata +11 -3
- data/lib/aniview/interface/rssfeed/rssfeed.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3997c84f2c7fe4c76932df56e2974b8e7fcdfdd
|
4
|
+
data.tar.gz: de56d18cced70e4feb91ad1f54bbf6975eaaa761
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59457afc95892f3a5002bc9fa01d3433a39a831ea32c5382628939245c3f23e1125c829634f1760b830fc1f2edec1645c58ed9d2d43a30113ceb79060ff7a49
|
7
|
+
data.tar.gz: c51ed7a61437b2ed9bc3c7a8ea02e4b7b52a04c788bcfedcaa5e8baa54af72025e4ed9d0e29459a2b54b47029650ae825ce07db620cbf0737473383f2ec71a3c
|
data/lib/aniview.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'highline'
|
2
2
|
require 'highline/import'
|
3
|
-
require 'json'
|
4
3
|
require 'thread'
|
5
4
|
require 'io/console'
|
6
5
|
require 'warning'
|
@@ -10,30 +9,54 @@ Warning.ignore([:fixnum, :bignum])
|
|
10
9
|
require_relative 'aniview/view/aiomenu'
|
11
10
|
require_relative 'aniview/view/delugemenu'
|
12
11
|
require_relative 'aniview/view/prefmenu'
|
12
|
+
require_relative 'aniview/view/schedulemenu'
|
13
|
+
require_relative 'aniview/view/subscriptionmenu'
|
13
14
|
|
14
15
|
require_relative 'aniview/interface/animeio/animeio'
|
15
16
|
require_relative 'aniview/interface/deluge/delugec'
|
16
17
|
require_relative 'aniview/interface/pref/pref'
|
17
|
-
require_relative 'aniview/interface/
|
18
|
+
require_relative 'aniview/interface/subscription/subscription'
|
19
|
+
require_relative 'aniview/interface/subscription/subscriptiondaemon'
|
20
|
+
require_relative 'aniview/interface/schedule/schedule'
|
18
21
|
|
19
22
|
require_relative 'aniview/util/alogger'
|
20
23
|
require_relative 'aniview/util/command'
|
21
24
|
require_relative 'aniview/util/term'
|
22
25
|
|
26
|
+
require_relative 'aniview/client/aniclient'
|
27
|
+
|
23
28
|
$stdout.sync = true
|
24
29
|
|
25
30
|
class AniView
|
26
31
|
def initialize
|
27
32
|
|
28
|
-
@term
|
33
|
+
@term = Term.new
|
29
34
|
|
30
35
|
@pref = Pref.new
|
31
36
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
+
$l = ALogger.new(@pref.parseDir(@pref.get "log_file"), false)
|
38
|
+
|
39
|
+
@aio = AnimeIO.new @pref
|
40
|
+
|
41
|
+
@schedule = Schedule.new @pref
|
42
|
+
|
43
|
+
@delugec = DelugeC.new(@pref)
|
44
|
+
|
45
|
+
@c = AniClient.new @pref
|
46
|
+
|
47
|
+
@subscription = Subscription.new(@pref, @schedule, @delugec, @c)
|
48
|
+
|
49
|
+
if not @c.server?
|
50
|
+
#puts "starting server"
|
51
|
+
process = fork do
|
52
|
+
require_relative 'aniviewd'
|
53
|
+
avd = AniViewd.new([])
|
54
|
+
avd.run
|
55
|
+
end
|
56
|
+
Process.detach(process)
|
57
|
+
end
|
58
|
+
|
59
|
+
@aiomenu = AioMenu.new(
|
37
60
|
refresh_function: :getAll,
|
38
61
|
interface: @aio,
|
39
62
|
name: @pref.get("menu_titles")["library"],
|
@@ -59,6 +82,26 @@ class AniView
|
|
59
82
|
term: @term,
|
60
83
|
children: false
|
61
84
|
)
|
85
|
+
|
86
|
+
@schedulemenu = ScheduleMenu.new(
|
87
|
+
refresh_function: :getAll,
|
88
|
+
interface: @schedule,
|
89
|
+
name: @pref.get("menu_titles")["schedlue"],
|
90
|
+
pref: @pref,
|
91
|
+
format: "format_schedule",
|
92
|
+
term: @term,
|
93
|
+
children: false
|
94
|
+
)
|
95
|
+
|
96
|
+
@subscriptionmenu = SubscriptionMenu.new(
|
97
|
+
refresh_function: :getAll,
|
98
|
+
interface: @subscription,
|
99
|
+
name: @pref.get("menu_titles")["subscriptions"],
|
100
|
+
pref: @pref,
|
101
|
+
format: "format_subscriptions",
|
102
|
+
term: @term,
|
103
|
+
children: false
|
104
|
+
)
|
62
105
|
|
63
106
|
@term.save.hide_cursor.echo_off
|
64
107
|
|
@@ -130,12 +173,18 @@ class AniView
|
|
130
173
|
elsif key == @pref.get("keybindings")["goto_torrents"]
|
131
174
|
@view = @delugemenu
|
132
175
|
@view.setName(@pref.get("menu_titles")["torrents"])
|
133
|
-
@view.setRfunc(:getTorrents)
|
134
176
|
|
135
177
|
elsif key == @pref.get("keybindings")["goto_preferences"]
|
136
178
|
@view = @prefmenu
|
137
179
|
@view.setName(@pref.get("menu_titles")["preferences"])
|
138
|
-
|
180
|
+
|
181
|
+
elsif key == @pref.get("keybindings")["goto_schedule"]
|
182
|
+
@view = @schedulemenu
|
183
|
+
@view.setName(@pref.get("menu_titles")["schedule"])
|
184
|
+
|
185
|
+
elsif key == @pref.get("keybindings")["goto_subscriptions"]
|
186
|
+
@view = @subscriptionmenu
|
187
|
+
@view.setName(@pref.get("menu_titles")["subscriptions"])
|
139
188
|
|
140
189
|
elsif key == ":"
|
141
190
|
cmd = Command.read(@term, ":")
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
#require_relative '../interface/pref/pref'
|
4
|
+
|
5
|
+
class AniClient
|
6
|
+
|
7
|
+
def initialize(pref)
|
8
|
+
@pref = pref
|
9
|
+
# @pref = Pref.new if @pref == "no"
|
10
|
+
end
|
11
|
+
|
12
|
+
def connect
|
13
|
+
begin
|
14
|
+
TCPSocket.new 'localhost', @pref.get("daemon")["port"]
|
15
|
+
rescue Errno::ECONNREFUSED
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def sendMsg msg
|
21
|
+
begin
|
22
|
+
s = connect
|
23
|
+
return "" if s == false
|
24
|
+
s.puts msg
|
25
|
+
r = s.gets.chomp
|
26
|
+
s.close
|
27
|
+
return r
|
28
|
+
rescue Errno::ECONNRESET
|
29
|
+
return ""
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def stopDaemon
|
34
|
+
sendMsg "quit"
|
35
|
+
end
|
36
|
+
|
37
|
+
def info
|
38
|
+
sendMsg "info"
|
39
|
+
end
|
40
|
+
|
41
|
+
def lastchecked
|
42
|
+
sendMsg "lastchecked"
|
43
|
+
end
|
44
|
+
|
45
|
+
def server?
|
46
|
+
return false unless sendMsg("up?") == "true"
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -41,7 +41,7 @@ class AnimeIO
|
|
41
41
|
ret = {}
|
42
42
|
(@pref.get("anime_locations").split(":")).each { |dir|
|
43
43
|
|
44
|
-
dir = @pref.
|
44
|
+
dir = @pref.parseDir dir
|
45
45
|
|
46
46
|
Dir.glob("#{dir}*/*.{mkv,avi,mp4}").each { |file|
|
47
47
|
puts "indexing #{file}" if verbose
|
@@ -117,11 +117,6 @@ class AnimeIO
|
|
117
117
|
subarray
|
118
118
|
) => subarray
|
119
119
|
)
|
120
|
-
|
121
|
-
|
122
|
-
#puts ret.inspect
|
123
|
-
#exit
|
124
|
-
|
125
120
|
return Hash[ret.sort_by{ |a| a[0].title}]
|
126
121
|
end
|
127
122
|
|
@@ -157,7 +152,7 @@ class AnimeIO
|
|
157
152
|
end
|
158
153
|
|
159
154
|
def logWatched(file)
|
160
|
-
open(@pref.
|
155
|
+
open(@pref.parseDir(@pref.get("watch_log")), 'a') do |f|
|
161
156
|
f.puts %x(date).chomp + " ./" + File.basename(file) + " " + @watch_log_tag
|
162
157
|
end
|
163
158
|
end
|
@@ -3,54 +3,151 @@ require_relative 'torrentitem'
|
|
3
3
|
|
4
4
|
class DelugeC
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
6
|
+
def initialize pref
|
7
|
+
@pref = pref
|
8
|
+
|
9
|
+
host = @pref.get("deluge_config")["host"]
|
10
|
+
login = @pref.get("deluge_config")["login"]
|
11
|
+
password = @pref.get("deluge_config")["password"]
|
12
|
+
|
13
|
+
if (login == "" and password == "") and (host == "127.0.0.1" or host == "localhost")
|
14
|
+
la = localAuth
|
15
|
+
login = la[0]
|
16
|
+
password = la[1]
|
17
|
+
@pref.set(["deluge_config", "login"], login)
|
18
|
+
@pref.set(["deluge_config", "password"], password)
|
19
|
+
end
|
20
|
+
|
21
|
+
@client = Deluge::Rpc::Client.new(
|
22
|
+
host: host,
|
23
|
+
port: Integer(@pref.get("deluge_config")["port"]),
|
24
|
+
login: @pref.get("deluge_config")["login"],
|
25
|
+
password: @pref.get("deluge_config")["password"]
|
26
|
+
)
|
27
|
+
|
28
|
+
@status = "not connected"
|
29
|
+
@connected = false
|
30
|
+
connect
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def getStatus
|
35
|
+
@status
|
36
|
+
end
|
37
|
+
|
38
|
+
def connect
|
39
|
+
begin
|
40
|
+
@status = "connected"
|
41
|
+
@client.connect
|
42
|
+
@connected = true
|
43
|
+
rescue Deluge::Rpc::Connection::RPCError
|
44
|
+
@status = "error connecting"
|
45
|
+
@connected = false
|
46
|
+
rescue RuntimeError
|
47
|
+
@status = "error connecting"
|
48
|
+
@client.close
|
49
|
+
@connected = false
|
50
|
+
end
|
51
|
+
|
52
|
+
@client.close unless @connected
|
53
|
+
end
|
54
|
+
|
55
|
+
def localAuth
|
56
|
+
authfile = Dir.home + "/.config/deluge/auth"
|
57
|
+
["", ""] if not File.exist? authfile
|
58
|
+
File.open(Dir.home + "/.config/deluge/auth") { |f| f.read }.split(":")
|
59
|
+
end
|
60
|
+
|
61
|
+
def getTorrents
|
62
|
+
connect unless @connected
|
63
|
+
return {} unless @connected
|
64
|
+
|
65
|
+
tkeys = [
|
66
|
+
"name",
|
67
|
+
"progress",
|
68
|
+
"eta",
|
69
|
+
"paused",
|
70
|
+
"state",
|
71
|
+
"hash",
|
72
|
+
#"active_time",
|
73
|
+
#"is_finished",
|
74
|
+
#"max_connections",
|
75
|
+
#"max_download_speed",
|
76
|
+
#"max_upload_slots",
|
77
|
+
#"max_upload_speed",
|
78
|
+
#"message",
|
79
|
+
#"next_announce",
|
80
|
+
#"num_peers",
|
81
|
+
#"num_seeds",
|
82
|
+
#"remove_at_ratio",
|
83
|
+
#"save_path",
|
84
|
+
#"seeding_time",
|
85
|
+
#"seeds_peers_ratio",
|
86
|
+
#"seed_rank",
|
87
|
+
#"stop_at_ratio",
|
88
|
+
#"stop_ratio",
|
89
|
+
#"time_added",
|
90
|
+
#"upload_payload_rate",
|
91
|
+
#"comment",
|
92
|
+
#"file_priorities",
|
93
|
+
#"file_progress",
|
94
|
+
#"files",
|
95
|
+
#"is_seed",
|
96
|
+
#"num_files",
|
97
|
+
#"num_pieces",
|
98
|
+
#"peers",
|
99
|
+
#"piece_length",
|
100
|
+
#"private",
|
101
|
+
#"queue",
|
102
|
+
#"ratio",
|
103
|
+
#"total_size",
|
104
|
+
#"tracker_host"
|
105
|
+
]
|
106
|
+
|
107
|
+
return @client.core.get_torrents_status({}, tkeys)
|
108
|
+
end
|
109
|
+
|
110
|
+
def toggleTorrent torrentItem
|
111
|
+
id = torrentItem.attributes["h"]
|
112
|
+
if torrentItem.attributes["u"]
|
113
|
+
@client.core.resume_torrent([id])
|
114
|
+
else
|
115
|
+
@client.core.pause_torrent([id])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def removeTorrent torrentItem, withData
|
120
|
+
id = torrentItem.attributes["h"]
|
121
|
+
@client.core.remove_torrent(id, withData)
|
122
|
+
end
|
123
|
+
|
124
|
+
def addTorrent mag, loc
|
125
|
+
connect unless @connected
|
126
|
+
return false unless @connected
|
127
|
+
begin
|
128
|
+
tid = @client.core.add_torrent_magnet(mag, {"download_location": loc})
|
129
|
+
rescue Deluge::Rpc::Connection::InvokeTimeoutError
|
130
|
+
tid = nil
|
131
|
+
end
|
132
|
+
return true if tid.class == String and tid.length > 1
|
133
|
+
return false
|
134
|
+
end
|
135
|
+
|
136
|
+
def makeHash(arr)
|
137
|
+
ret = {}
|
138
|
+
arr.each{ |t|
|
139
|
+
tinfo = t[1]
|
140
|
+
torrent = TorrentItem.new(
|
141
|
+
name: tinfo["name"],
|
142
|
+
progress: tinfo["progress"],
|
143
|
+
eta: tinfo["eta"],
|
144
|
+
paused: tinfo["paused"],
|
145
|
+
state: tinfo["state"],
|
146
|
+
id: tinfo["hash"]
|
147
|
+
)
|
148
|
+
ret.merge!(torrent => torrent)
|
149
|
+
}
|
150
|
+
return ret
|
151
|
+
end
|
55
152
|
|
56
153
|
end
|
@@ -2,11 +2,14 @@ require_relative '../../util/format'
|
|
2
2
|
require_relative '../item'
|
3
3
|
|
4
4
|
class TorrentItem < Item
|
5
|
-
def initialize(name:, progress:, eta:)
|
5
|
+
def initialize(name:, progress:, eta:, paused:, state:, id:)
|
6
6
|
@attr = {
|
7
7
|
"n" => name,
|
8
8
|
"p" => Format.format_progress(progress),
|
9
9
|
"e" => Format.format_duration(eta),
|
10
|
+
"u" => paused,
|
11
|
+
"s" => state,
|
12
|
+
"h" => id
|
10
13
|
}
|
11
14
|
end
|
12
15
|
|
@@ -1,68 +1,97 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
2
|
+
"keybindings" :
|
3
|
+
{
|
4
|
+
"goto_preferences" : "0",
|
5
|
+
"goto_unwatched" : "1",
|
6
|
+
"goto_library" : "2",
|
7
|
+
"goto_torrents" : "3",
|
8
|
+
"goto_schedule" : "4",
|
9
|
+
"goto_subscriptions" : "5",
|
10
|
+
"anime_set_watched" : "Z",
|
11
|
+
"anime_set_unwatched" : "u",
|
12
|
+
"anime_undo_set_watched" : "z",
|
13
|
+
"torrents_pause" : "space",
|
14
|
+
"torrents_remove" : "-",
|
15
|
+
"torrents_remove_data" : "_",
|
16
|
+
"schedule_add_item" : "+",
|
17
|
+
"schedule_delete_item" : "-",
|
18
|
+
"schedule_edit_item" : "enter",
|
19
|
+
"subscriptions_edit" : "enter",
|
20
|
+
"menu_nav_up" : "up",
|
21
|
+
"menu_nav_down" : "down",
|
22
|
+
"menu_nav_expand" : "space"
|
23
|
+
},
|
24
|
+
"anime_locations" : "~/anime/:$airing_dir",
|
25
|
+
"airing_dir" : "~/anime/airing/",
|
26
|
+
"clr" :
|
27
|
+
{
|
28
|
+
"main" : "blue",
|
29
|
+
"primary" : "white",
|
30
|
+
"secondary" : "cyan",
|
31
|
+
"selected" : "red"
|
32
|
+
},
|
33
|
+
"menu_titles" :
|
34
|
+
{
|
35
|
+
"unwatched" : "unwatched",
|
36
|
+
"library" : "anime library",
|
37
|
+
"torrents" : "torrents",
|
38
|
+
"preferences" : "preferences",
|
39
|
+
"schedule" : "schedule",
|
40
|
+
"subscriptions" : "subscriptions"
|
41
|
+
},
|
42
|
+
"format_library" :
|
43
|
+
{
|
44
|
+
"title" : " %t @ %D %S ",
|
45
|
+
"parent" : " %t - %c@ %D %S ",
|
46
|
+
"child" : " %t@ %D %S "
|
47
|
+
},
|
48
|
+
"format_library_unwatched" :
|
49
|
+
{
|
50
|
+
"title" : " %t @ $q@ %D %S ",
|
51
|
+
"parent" : " %t - %c@ %D %S ",
|
52
|
+
"child" : " %t@ %D %S %r "
|
53
|
+
},
|
54
|
+
"format_torrents" :
|
55
|
+
{
|
56
|
+
"title" : " %t - %s",
|
57
|
+
"parent" : " %n@ %p "
|
58
|
+
},
|
59
|
+
"format_schedule" :
|
60
|
+
{
|
61
|
+
"title" : " %t",
|
62
|
+
"parent" : " %t@ %p "
|
63
|
+
},
|
64
|
+
"format_subscriptions" :
|
65
|
+
{
|
66
|
+
"title" : " %t - %d@ last checked: %l ",
|
67
|
+
"parent" : " %f - /%r/@ %m "
|
68
|
+
},
|
69
|
+
"format_preferences" :
|
70
|
+
{
|
71
|
+
"title" : " %t",
|
72
|
+
"parent" : " %t@ %v "
|
73
|
+
},
|
74
|
+
"deluge_config" :
|
75
|
+
{
|
76
|
+
"host" : "localhost",
|
77
|
+
"port" : "58846",
|
78
|
+
"login" : "",
|
79
|
+
"password" : ""
|
80
|
+
},
|
81
|
+
"rss_feed" :
|
82
|
+
{
|
83
|
+
"url" : "https://nyaa.pantsu.cat/feed?c=3_5&s=1&max=100&userID=0&q=",
|
84
|
+
"refresh_interval" : "150"
|
85
|
+
},
|
86
|
+
"daemon" :
|
87
|
+
{
|
88
|
+
"port" : "21312"
|
89
|
+
},
|
90
|
+
"log_file" : "$conf_dir/aw.log",
|
91
|
+
"daemon_log_file" : "$conf_dir/server.log",
|
92
|
+
"watch_log" : "$conf_dir/watchlog",
|
93
|
+
"conf_dir" : "~/.config/aniview",
|
94
|
+
"watch_command" : "mpv -alang jpn -slang eng -msg-level=all=fatal -ass",
|
95
|
+
"local_anime" : null,
|
96
|
+
"schedule" : []
|
68
97
|
}
|