aniview 0.3.0 → 1.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/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
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
|
2
4
|
require_relative 'prefitem'
|
3
5
|
require_relative '../../view/emote.rb'
|
4
6
|
require_relative '../../util/alogger'
|
@@ -7,25 +9,25 @@ class Pref
|
|
7
9
|
def initialize
|
8
10
|
|
9
11
|
@home = Dir.home
|
10
|
-
@conf = @home + "/.
|
12
|
+
@conf = @home + "/.config/aniview"
|
11
13
|
|
12
14
|
File.open(File.join(File.dirname(__FILE__), "/validate.json"), "r") {
|
13
15
|
|f| @validate = JSON.parse(f.read)
|
14
16
|
}
|
15
17
|
|
16
|
-
|
17
|
-
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
18
|
-
|
19
|
-
@pref_file = @conf + "/r_anime.json"
|
18
|
+
FileUtils.mkdir_p(@conf) unless File.directory?(@conf)
|
20
19
|
|
21
|
-
@
|
20
|
+
@pref_file = @conf + "/aniview.json"
|
22
21
|
|
23
22
|
self.defaults if not File.exist?(@pref_file)
|
24
23
|
self.load
|
25
24
|
end
|
26
25
|
|
27
|
-
def
|
28
|
-
|
26
|
+
def parseDir path
|
27
|
+
path = path.gsub("$airing_dir", @pref["airing_dir"])
|
28
|
+
path = path.gsub("$conf_dir", @pref["conf_dir"])
|
29
|
+
path = path.gsub("~", Dir.home)
|
30
|
+
return path
|
29
31
|
end
|
30
32
|
|
31
33
|
def defaults
|
@@ -74,13 +76,18 @@ class Pref
|
|
74
76
|
|
75
77
|
when "path"
|
76
78
|
destination.split(":").each { |d|
|
77
|
-
|
79
|
+
return false if not Dir.exist?(parseDir d)
|
80
|
+
}
|
78
81
|
|
79
82
|
when "color"
|
80
83
|
return false if not $clr.key? destination
|
81
84
|
|
82
85
|
when "int"
|
83
86
|
return false if not destination.scan(/\D/).empty? and destination.length > 1
|
87
|
+
|
88
|
+
when "locked"
|
89
|
+
return false
|
90
|
+
|
84
91
|
end
|
85
92
|
|
86
93
|
return true
|
@@ -98,6 +105,7 @@ class Pref
|
|
98
105
|
def getAll
|
99
106
|
ignore = {
|
100
107
|
"local_anime" => true,
|
108
|
+
"schedule" => true,
|
101
109
|
}
|
102
110
|
|
103
111
|
r = {}
|
@@ -122,7 +130,7 @@ class Pref
|
|
122
130
|
end
|
123
131
|
|
124
132
|
def save
|
125
|
-
File.open(@pref_file, "w") { |f| f.write(@pref
|
133
|
+
File.open(@pref_file, "w") { |f| f.write(JSON.pretty_generate(@pref)) }
|
126
134
|
end
|
127
135
|
|
128
136
|
def load
|
@@ -5,14 +5,24 @@
|
|
5
5
|
"goto_unwatched" : "key",
|
6
6
|
"goto_library" : "key",
|
7
7
|
"goto_torrents" : "key",
|
8
|
+
"goto_schedule" : "key",
|
9
|
+
"goto_subscriptions" : "key",
|
8
10
|
"anime_set_watched" : "key",
|
9
11
|
"anime_set_unwatched" : "key",
|
10
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",
|
11
20
|
"menu_nav_up" : "key",
|
12
21
|
"menu_nav_down" : "key",
|
13
22
|
"menu_nav_expand" : "key"
|
14
23
|
},
|
15
24
|
"anime_locations" : "path",
|
25
|
+
"airing_dir" : "path",
|
16
26
|
"clr" :
|
17
27
|
{
|
18
28
|
"main" : "color",
|
@@ -25,7 +35,10 @@
|
|
25
35
|
"unwatched" : "any",
|
26
36
|
"library" : "any",
|
27
37
|
"torrents" : "any",
|
28
|
-
"preferences" : "any"
|
38
|
+
"preferences" : "any",
|
39
|
+
"schedule" : "any",
|
40
|
+
"subscriptions" : "any"
|
41
|
+
|
29
42
|
},
|
30
43
|
"format_library" :
|
31
44
|
{
|
@@ -44,11 +57,21 @@
|
|
44
57
|
"title" : "any",
|
45
58
|
"parent" : "any"
|
46
59
|
},
|
60
|
+
"format_schedule" :
|
61
|
+
{
|
62
|
+
"title" : "any",
|
63
|
+
"parent" : "any"
|
64
|
+
},
|
47
65
|
"format_preferences" :
|
48
66
|
{
|
49
67
|
"title" : "any",
|
50
68
|
"parent" : "any"
|
51
69
|
},
|
70
|
+
"format_subscriptions" :
|
71
|
+
{
|
72
|
+
"title" : "any",
|
73
|
+
"parent" : "any"
|
74
|
+
},
|
52
75
|
"deluge_config" :
|
53
76
|
{
|
54
77
|
"host" : "any",
|
@@ -61,8 +84,15 @@
|
|
61
84
|
"url" : "any",
|
62
85
|
"refresh_interval" : "int"
|
63
86
|
},
|
87
|
+
"daemon" :
|
88
|
+
{
|
89
|
+
"port" : "int"
|
90
|
+
},
|
64
91
|
"log_file" : "path",
|
92
|
+
"daemon_log_file" : "path",
|
65
93
|
"watch_log" : "path",
|
94
|
+
"conf_dir" : "locked",
|
66
95
|
"watch_command" : "any",
|
67
|
-
"local_anime" : "any"
|
96
|
+
"local_anime" : "any",
|
97
|
+
"schedule" : "any"
|
68
98
|
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
require_relative 'scheduleitem'
|
5
|
+
|
6
|
+
class Schedule
|
7
|
+
|
8
|
+
def initialize pref
|
9
|
+
@pref = pref
|
10
|
+
load
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty?
|
14
|
+
if @schedule == nil or @schedule.length == 0
|
15
|
+
@schedule = [ScheduleItem.new("no schedule", "")]
|
16
|
+
save
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def getAll
|
21
|
+
empty?
|
22
|
+
return @schedule
|
23
|
+
end
|
24
|
+
|
25
|
+
def addItem item
|
26
|
+
@schedule.delete_at 0 if @schedule[0].attributes["t"] == "no schedule"
|
27
|
+
|
28
|
+
new_item = ScheduleItem.new(item, @pref.get("airing_dir"))
|
29
|
+
|
30
|
+
FileUtils.mkdir_p @pref.parseDir new_item.attributes["p"]
|
31
|
+
|
32
|
+
@schedule << new_item
|
33
|
+
|
34
|
+
save
|
35
|
+
end
|
36
|
+
|
37
|
+
def editItem loc, val
|
38
|
+
old_dir = @pref.parseDir @schedule[loc].attributes["p"]
|
39
|
+
@schedule[loc].setTitle val
|
40
|
+
new_dir = @pref.parseDir @schedule[loc].attributes["p"]
|
41
|
+
|
42
|
+
FileUtils.mv old_dir, new_dir unless old_dir == new_dir
|
43
|
+
|
44
|
+
save
|
45
|
+
end
|
46
|
+
|
47
|
+
def removeItem loc
|
48
|
+
@schedule.delete_at loc
|
49
|
+
save
|
50
|
+
end
|
51
|
+
|
52
|
+
def save
|
53
|
+
@pref.set "schedule", Base64.encode64(Marshal.dump @schedule)
|
54
|
+
end
|
55
|
+
|
56
|
+
def load
|
57
|
+
@pref.load
|
58
|
+
raw = @pref.get "schedule"
|
59
|
+
if not raw == nil and raw.class == String
|
60
|
+
@schedule = Marshal.load(Base64.decode64(raw))
|
61
|
+
else
|
62
|
+
empty?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def makeHash(arr)
|
67
|
+
ret = {}
|
68
|
+
arr.each{ |t|
|
69
|
+
ret.merge!(t => t)
|
70
|
+
}
|
71
|
+
return ret
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative '../item'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
class ScheduleItem < Item
|
5
|
+
|
6
|
+
def initialize(title, dir)
|
7
|
+
@dirpath = dir
|
8
|
+
@basepath = escapePath title
|
9
|
+
|
10
|
+
@attr = {
|
11
|
+
"t" => title,
|
12
|
+
"f" => title[0..4] + "…",
|
13
|
+
"r" => title,
|
14
|
+
"p" => @dirpath + @basepath,
|
15
|
+
"m" => "never"
|
16
|
+
}
|
17
|
+
|
18
|
+
@lastseen = 0
|
19
|
+
#@id = SecureRandom.uuid
|
20
|
+
end
|
21
|
+
|
22
|
+
def updataDir nd
|
23
|
+
@dirpath = nd
|
24
|
+
@attr["p"] = nd + @basepath
|
25
|
+
end
|
26
|
+
|
27
|
+
def escapePath path
|
28
|
+
path_ = path.gsub(":", "_")
|
29
|
+
path_.gsub("/", ":")
|
30
|
+
end
|
31
|
+
|
32
|
+
def setTitle newtitle
|
33
|
+
@attr["t"] = newtitle
|
34
|
+
@attr["f"] = newtitle[0..4] + "…"
|
35
|
+
@attr["p"] = @dirpath + escapePath(newtitle)
|
36
|
+
end
|
37
|
+
|
38
|
+
def setRegexp regexp
|
39
|
+
@attr["r"] = regexp
|
40
|
+
end
|
41
|
+
|
42
|
+
def setSeen
|
43
|
+
@lastseen = Time.now.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'simple-rss'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
require_relative "../../util/stringhelp"
|
5
|
+
require_relative "../schedule/scheduleitem"
|
6
|
+
|
7
|
+
|
8
|
+
class Subscription
|
9
|
+
def initialize pref, schedule, delugec, client
|
10
|
+
@c = client
|
11
|
+
@pref = pref
|
12
|
+
@schedule = schedule
|
13
|
+
@delugec = delugec
|
14
|
+
end
|
15
|
+
|
16
|
+
def checkDaemon
|
17
|
+
if @c.server?
|
18
|
+
"daemon up"
|
19
|
+
else
|
20
|
+
"daemon down"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def updateFeed
|
25
|
+
begin
|
26
|
+
@rss = SimpleRSS.parse open(@pref.get("rss_feed")["url"])
|
27
|
+
|
28
|
+
rescue SocketError
|
29
|
+
@rss = nil
|
30
|
+
|
31
|
+
rescue
|
32
|
+
@rss = nil
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def feed
|
38
|
+
@rss
|
39
|
+
end
|
40
|
+
|
41
|
+
def getLastChecked
|
42
|
+
@c.lastchecked
|
43
|
+
end
|
44
|
+
|
45
|
+
def match regexp
|
46
|
+
updateFeed if @rss == nil
|
47
|
+
return [] if @rss == nil
|
48
|
+
re = Regexp.new regexp
|
49
|
+
matches = []
|
50
|
+
@rss.items.each{ |item|
|
51
|
+
re.match item[:title] { matches << item }
|
52
|
+
}
|
53
|
+
return matches
|
54
|
+
end
|
55
|
+
|
56
|
+
def matchAll
|
57
|
+
total_matches = 0
|
58
|
+
getAll.each { |subs|
|
59
|
+
matches = match subs.attributes["r"]
|
60
|
+
if matches.length >= 1
|
61
|
+
|
62
|
+
downloaddir = @pref.parseDir(subs.attributes["p"]) + "/"
|
63
|
+
newfile = downloaddir + matches[0][:title]
|
64
|
+
|
65
|
+
next if File.exist? newfile
|
66
|
+
|
67
|
+
s = @delugec.addTorrent matches[0][:link], @pref.parseDir(subs.attributes["p"])
|
68
|
+
subs.setSeen if s
|
69
|
+
@schedule.save
|
70
|
+
total_matches+=1
|
71
|
+
|
72
|
+
end
|
73
|
+
}
|
74
|
+
return total_matches
|
75
|
+
end
|
76
|
+
|
77
|
+
def forceMatch
|
78
|
+
@mthread = Thread.new do
|
79
|
+
updateFeed
|
80
|
+
matchAll
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def getAll
|
85
|
+
@schedule.load
|
86
|
+
@schedule.getAll
|
87
|
+
end
|
88
|
+
|
89
|
+
def editItem loc, newval
|
90
|
+
@schedule.getAll[loc].setRegexp newval
|
91
|
+
@schedule.save
|
92
|
+
end
|
93
|
+
|
94
|
+
def makeHash(arr)
|
95
|
+
ret = {}
|
96
|
+
arr.each{ |subs|
|
97
|
+
ret.merge!(subs => subs)
|
98
|
+
}
|
99
|
+
return ret
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
class SubscriptionDaemon
|
4
|
+
|
5
|
+
def initialize pref, subscription
|
6
|
+
@subscription = subscription
|
7
|
+
@pref = pref
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def match
|
12
|
+
@subscription.updateFeed
|
13
|
+
@subscription.matchAll
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
|
18
|
+
while true
|
19
|
+
|
20
|
+
match
|
21
|
+
|
22
|
+
sleep Integer(@pref.get("rss_feed")["refresh_interval"])
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def start(mode="s")
|
29
|
+
|
30
|
+
puts "started daemon" if mode == "v"
|
31
|
+
|
32
|
+
@thread = Thread.new do
|
33
|
+
run
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def exit
|
39
|
+
@thread.exit if @thread != nil
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/aniview/util/alogger.rb
CHANGED
@@ -1,9 +1,18 @@
|
|
1
1
|
class ALogger
|
2
|
-
|
2
|
+
|
3
|
+
def initialize(file, overwrite = true)
|
4
|
+
|
3
5
|
@logfile = file
|
4
|
-
|
6
|
+
mode = "a"
|
7
|
+
mode = "w" if overwrite
|
8
|
+
open(@logfile, mode) { |f| f.puts "initialized..." }
|
9
|
+
|
5
10
|
end
|
11
|
+
|
6
12
|
def log(string)
|
7
|
-
|
13
|
+
|
14
|
+
open(@logfile, 'a') { |f| f.puts "#{Time.now.to_s} string" }
|
15
|
+
|
8
16
|
end
|
17
|
+
|
9
18
|
end
|