pig-media-server 0.3.2 → 2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/bin/pig-media-server +4 -1
  4. data/gulpfile.js +33 -0
  5. data/javascripts/application.js +117 -0
  6. data/javascripts/chromecast.js +57 -0
  7. data/javascripts/components/head.js +106 -0
  8. data/javascripts/components/list.js +104 -0
  9. data/javascripts/components/new_flag.js +23 -0
  10. data/javascripts/components/player.js +171 -0
  11. data/javascripts/components/query_list.js +68 -0
  12. data/javascripts/components/sort.js +64 -0
  13. data/javascripts/components/watch.js +48 -0
  14. data/javascripts/controller.js +62 -0
  15. data/javascripts/custom_list.js +14 -0
  16. data/javascripts/event_dispatcher.js +21 -0
  17. data/javascripts/recent.js +34 -0
  18. data/javascripts/utils.js +22 -0
  19. data/javascripts/video.js +10 -0
  20. data/lib/pig-media-server/api.rb +96 -0
  21. data/lib/pig-media-server/aspect.rb +10 -5
  22. data/lib/pig-media-server/backup.rb +69 -0
  23. data/lib/pig-media-server/cli.rb +60 -25
  24. data/lib/pig-media-server/crawl.rb +41 -5
  25. data/lib/pig-media-server/kindle_send.rb +31 -24
  26. data/lib/pig-media-server/model/data.rb +106 -0
  27. data/lib/pig-media-server/model/migrate.rb +34 -0
  28. data/lib/pig-media-server/model/pig.rb +11 -2
  29. data/lib/pig-media-server/version.rb +1 -1
  30. data/lib/pig-media-server/views/_custom_links.haml +4 -0
  31. data/lib/pig-media-server/views/_ft_flv.haml +1 -0
  32. data/lib/pig-media-server/views/_ft_pdf.haml +0 -0
  33. data/lib/pig-media-server/views/_ft_video.haml +9 -4
  34. data/lib/pig-media-server/views/_link.haml +4 -1
  35. data/lib/pig-media-server/views/_new_flag.haml +1 -1
  36. data/lib/pig-media-server/views/app.scss +10 -1
  37. data/lib/pig-media-server/views/bundle.js +13 -0
  38. data/lib/pig-media-server/views/chromecast.coffee +54 -0
  39. data/lib/pig-media-server/views/config.coffee +13 -1
  40. data/lib/pig-media-server/views/config.haml +27 -4
  41. data/lib/pig-media-server/views/feed.builder +3 -2
  42. data/lib/pig-media-server/views/flv.coffee +33 -0
  43. data/lib/pig-media-server/views/index.haml +11 -5
  44. data/lib/pig-media-server/views/meta.haml +4 -4
  45. data/lib/pig-media-server/views/movie.coffee +65 -39
  46. data/lib/pig-media-server/views/react.haml +22 -0
  47. data/lib/pig-media-server/views/remote.haml +2 -2
  48. data/lib/pig-media-server/views/session.coffee +5 -0
  49. data/lib/pig-media-server/views/storage.coffee +5 -16
  50. data/lib/pig-media-server/views/sub.haml +5 -6
  51. data/lib/pig-media-server/views/subview.coffee +109 -19
  52. data/lib/pig-media-server/views/tv.coffee +97 -0
  53. data/lib/pig-media-server/views/tv.haml +33 -0
  54. data/lib/pig-media-server/views/unread.coffee +10 -0
  55. data/lib/pig-media-server/web.rb +102 -37
  56. data/package.json +23 -0
  57. data/pig-media-server.gemspec +5 -0
  58. metadata +123 -38
@@ -1,9 +1,45 @@
1
1
  require 'pig-media-server'
2
2
  require 'pig-media-server/model/pig'
3
+ require 'mechanize'
3
4
 
4
5
 
5
6
  module PigMediaServer
6
7
  class Crawl
8
+
9
+ def recommend
10
+ users = Groonga['Datas'].select.to_a.map{|x| x.original_key}.select{|x| x =~ /user_data/}.map{|x| x.split("/")[1]}.uniq
11
+
12
+ users.each do |user|
13
+ keys = []
14
+ animetick = Groonga['Datas'].select{|x| x.original_key == "user_data/#{user}/animetick" }.first
15
+ if animetick
16
+ animetick = animetick.body.gsub('"', '')
17
+ alice = Mechanize.new
18
+ page = alice.get("http://animetick.net/users/#{animetick}")
19
+ titles = page.root.xpath('//*[@id="body"]/div[3]/ul/li/div[2]').map{|x| x.inner_text}.map{|x|
20
+ x.gsub(/\n\ +/, '')
21
+ }
22
+ titles.each{|title|
23
+ title = title.split('').map{|x|
24
+ if x =~ /\p{Han}|\p{Hiragana}|\p{Katakana}|[0-9a-zA-Z]/
25
+ x
26
+ else
27
+ ' '
28
+ end
29
+
30
+ }.join('').sub(/\ +$/, '')
31
+ Groonga['Files'].select(Sewell.generate(title, ['path'])).select{|x| x.path =~ '.mp4'}.to_a.each{|record|
32
+ next if record.mtime < Time.now.to_i-86400*30*5
33
+ keys << record
34
+ }
35
+ }
36
+ keys = keys.sort_by{|x| -x.mtime}.map{|x| x._key}
37
+ FileUtils.mkdir_p "#{$config['user_data_path']}/recommend"
38
+ open("#{$config['user_data_path']}/recommend/#{user}", 'w'){|f| f.puts keys.join("\n")}
39
+ end
40
+ end
41
+ end
42
+
7
43
  def all
8
44
  $config = Pit.get("Pig Media Server")
9
45
  if ARGV[1]
@@ -11,15 +47,15 @@ module PigMediaServer
11
47
  else
12
48
  array = Dir.glob("#{$config['path']}/**/*").sort
13
49
  end
14
- array.each_with_index{|x,i|
50
+
51
+ array.each.with_index(1){|x,i|
15
52
  next unless File.exist?(x)
16
53
  next if File::ftype(x) == 'directory'
17
- flag = false
18
- $config['exclude_path'].each{|e| flag = true if x =~ /#{e.sub(/\//, '\/')}/ } if $config['exclude_path'].class.to_s == 'Array'
19
- next if flag
54
+ next if $config['exclude_path'].class == Array && $config['exclude_path'].find{|e| x =~ /#{e.sub(/\//, '\/')}/ }
20
55
  Pig.find_or_create_by_path x
21
- puts "Crawl #{i+1} / #{array.count}"
56
+ puts "Crawl #{i} / #{array.count}" if i % 100 == 0 or i ==array.count
22
57
  }
58
+ self.recommend
23
59
  end
24
60
  end
25
61
  end
@@ -2,50 +2,57 @@ require 'mail'
2
2
  require 'pony'
3
3
  require 'pig-media-server'
4
4
  require 'pig-media-server/model/pig'
5
+ require 'pig-media-server/model/data'
5
6
 
6
7
  module PigMediaServer
7
8
  class KindleSend
8
9
  def run
9
10
  pit_config = Pit.get 'Pig Media Server'
10
- while true
11
- begin
11
+ 100.times do
12
+ #begin
12
13
  GC.start
13
- from_hash = Hash[*Dir.glob("#{pit_config['user_data_path']}/*.json").map{|t| JSON.parse open(t).read}.select{|t| t['kindle_to'] and t['kindle_from']}.map{|t| [t['kindle_to'], t['kindle_from']]}.select{|t| t.first != '' and t.last != ''}.flatten]
14
+ a = AppData.all.select{|x| x[:value].class == String and x[:key] =~ /kindle/ and x[:value] =~ /@/}.sort{|a2,b| a2[:key] <=> b[:key]}
15
+ froms = a.select{|x| x[:key] =~ /from/}
16
+ tos = a.select{|x| x[:key] =~ /to/}
17
+ from_data = {}
18
+ tos.count.times{|i|
19
+ from_data[tos[i][:value]] = froms[i][:value]
20
+ }
14
21
  Dir.glob("#{pit_config['user_data_path']}/kindle/queue/*").each{|x|
15
22
  begin
16
23
  queue = x.split('/').last
17
24
  key = queue.split('_').first
18
- user_id = queue.split('_').last
19
- config = JSON.parse open("#{pit_config['user_data_path']}/#{user_id}.json").read
20
- p [key, user_id, config['kindle_to'], config['kindle_from']]
21
25
 
22
26
  pig = Pig.find key
23
- puts 'start send'
24
- from_hash.each{|to, from|
25
- p [to, from]
26
- Pony.mail({
27
- :to => to,
28
- from: from,
29
- subject: '',
30
- body: '',
31
- attachments: {"#{key}.mobi" => File.read(pig.record.path)},
32
- :via => :smtp,
33
- :via_options => pit_config['smtp'].dup
34
- })
27
+ puts 'start send: ' + pig.path
28
+ from_data.each{|to, from|
29
+ begin
30
+ p [to, from]
31
+ Pony.mail({
32
+ :to => to,
33
+ from: from,
34
+ subject: '',
35
+ body: '',
36
+ attachments: {"#{key}.mobi" => File.read(pig.record.path)},
37
+ :via => :smtp,
38
+ :via_options => pit_config['smtp'].dup
39
+ })
40
+ rescue
41
+ end
35
42
  }
36
43
  rescue =>e
37
44
  p e
38
45
  p e.backtrace
39
46
  end
40
- FileUtils.cd '/home/ssig33/dev/pig'
47
+ FileUtils.cd '/home/ssig33/server'
41
48
  FileUtils.rm x
42
49
  puts 'end '+x
43
50
  }
44
- rescue => e
45
- p e
46
- p e.backtrace
47
- end
48
- sleep 1
51
+ #rescue => e
52
+ # p e
53
+ # p e.backtrace
54
+ #end
55
+ sleep 10
49
56
  end
50
57
  end
51
58
  end
@@ -0,0 +1,106 @@
1
+ #coding:utf-8
2
+ require 'fileutils'
3
+ require 'digest/md5'
4
+ require 'pig-media-server/model/migrate'
5
+
6
+ $config = $config || Pit.get("Pig Media Server")
7
+
8
+
9
+ class AppData
10
+ def self.find key
11
+ key = Digest::MD5.hexdigest(key)
12
+ parse(Groonga['Datas'][key].body)
13
+ rescue
14
+ nil
15
+ end
16
+
17
+ def self.set key, value
18
+ g_key = Digest::MD5.hexdigest(key)
19
+ Groonga['Datas'].add g_key
20
+ Groonga['Datas'][g_key].body = value.to_json
21
+ Groonga['Datas'][g_key].original_key = key
22
+ end
23
+
24
+ def self.all
25
+ Groonga['Datas'].select.to_a.map{|x|
26
+ {key: x.original_key, value: parse(x.body)}
27
+ }
28
+ end
29
+
30
+ def self.parse val
31
+ case val
32
+ when 'true'
33
+ true
34
+ when 'false'
35
+ false
36
+ else
37
+ JSON.parse val
38
+ end
39
+ rescue
40
+ if val.class == String
41
+ val.gsub(/^"|"$/, '')
42
+ else
43
+ val
44
+ end
45
+ end
46
+ end
47
+
48
+ class Stars
49
+ def self.list user
50
+ Pig.find Groonga['Stars'].select{|x|
51
+ x._key =~ user
52
+ }.to_a.map{|x| x._key.split('/').last}
53
+ end
54
+
55
+ def self.star? user, key
56
+ key =user+'/'+key
57
+ !!Groonga['Stars'][key]
58
+ rescue
59
+ false
60
+ end
61
+
62
+ def self.star user, key
63
+ key =user+'/'+key
64
+ if Groonga['Stars'].add key
65
+ Groonga['Stars'].delete key
66
+ else
67
+ Groonga['Stars'].add key
68
+ end
69
+ end
70
+
71
+ def self.unstar user, key
72
+ key =user+'/'+key
73
+ Groonga['Stars'].delete key
74
+ end
75
+ end
76
+
77
+ class Recents
78
+ def self.list user
79
+ hash = {}
80
+ Groonga['Recents'].select{|x|
81
+ x._key =~ user
82
+ }.to_a.map{|x| x._key.split("/").last}.each{|x|
83
+ hash["movie/#{x}"] = {}
84
+ }
85
+ hash
86
+ end
87
+
88
+ def self.recent? user, key
89
+ key =user+'/'+key
90
+ !!Groonga['Recents'][key]
91
+ rescue
92
+ nil
93
+ end
94
+
95
+ def self.recent user, key
96
+ key =user+'/'+key
97
+ Groonga['Recents'].add key
98
+ end
99
+ end
100
+
101
+ Dir.glob($config['user_data_path']+"/**/*.json").sort.each{|x|
102
+ user = x.split("/").last.split(".json").first
103
+ JSON.parse(open(x).read).map{|t| t}.select{|a| a.last.class != Array and a.last.class != Hash}.each{|ary|
104
+ AppData.set("user_data/#{user}/#{ary.first}", ary.last)
105
+ }
106
+ }
@@ -24,3 +24,37 @@ unless Groonga['Files']
24
24
  }
25
25
  end
26
26
  end
27
+
28
+ unless Groonga['Datas']
29
+ puts "create table 'Datas'"
30
+ Groonga::Schema.define do |schema|
31
+ schema.create_table("Datas", type: :patricia_trie, key_type: 'ShortText'){|table|
32
+ table.long_text "body"
33
+ table.long_text 'original_key'
34
+ }
35
+ end
36
+ end
37
+
38
+ unless Groonga['Stars']
39
+ puts "create table 'Stars'"
40
+ Groonga::Schema.define do |schema|
41
+ schema.create_table("Stars", type: :patricia_trie, key_type: 'ShortText'){|table|
42
+ }
43
+ end
44
+ end
45
+
46
+ unless Groonga['Recents']
47
+ puts "create table 'Recents'"
48
+ Groonga::Schema.define do |schema|
49
+ schema.create_table("Recents", type: :patricia_trie, key_type: 'ShortText'){|table|
50
+ }
51
+ end
52
+ end
53
+
54
+ unless Groonga['QueryList']
55
+ puts "create table 'QueryList'"
56
+ Groonga::Schema.define do |schema|
57
+ schema.create_table("QueryList", type: :patricia_trie, key_type: 'ShortText'){|table| table.short_text "query" }
58
+ end
59
+
60
+ end
@@ -1,6 +1,7 @@
1
1
  #coding:utf-8
2
2
  require 'fileutils'
3
3
  require 'pig-media-server/model/migrate'
4
+ require 'pig-media-server/model/data'
4
5
 
5
6
  CONFIG = Pit.get('Pig Media Server')
6
7
 
@@ -16,20 +17,25 @@ class Pig
16
17
  def key; self.record._key;end
17
18
  def name; self.record.path.split('/').last; end
18
19
  def mtime; Time.at(self.record.mtime);end
20
+ def mtime_to_i; self.record.mtime; end
19
21
  def size; self.record.size;end
20
22
  def metadata; self.record.metadata;end
21
23
  def srt; self.record.srt;end
22
24
  def url; 'http://'+self.config['hostname']+ '/volume' + URI.encode(self.record.path.sub(/#{config['path'].sub(/\//, '\/')}/, ''));end
23
25
  def type
24
26
  case self.name.split('.').last
25
- when 'mp4', 'MP4', 'webm'
27
+ when 'mp4', 'MP4', 'webm', 'm4v'
26
28
  'video'
27
29
  when 'zip', 'ZIP'
28
30
  'read'
31
+ when 'pdf'
32
+ 'pdf'
29
33
  when 'txt', 'TXT'
30
34
  'txt'
31
35
  when 'mobi'
32
36
  'mobi'
37
+ when 'flv'
38
+ 'flv'
33
39
  else
34
40
  'other'
35
41
  end
@@ -57,7 +63,10 @@ str.chomp.chomp
57
63
  open("#{self.config['user_data_path']}/rate/queue.txt", "a"){|x| x.puts "#{self.key} #{rate}"}
58
64
  end
59
65
 
60
-
66
+ def to_hash(opts = {})
67
+ hash = {key: self.key, name: self.name, mtime: self.mtime, size: self.size, url: self.url, type: self.type, mtime_to_i: self.mtime_to_i}
68
+ hash
69
+ end
61
70
 
62
71
  def self.find key
63
72
  case key.class.to_s
@@ -1,3 +1,3 @@
1
1
  module PigMediaServer
2
- VERSION = "0.3.2"
2
+ VERSION = "2"
3
3
  end
@@ -0,0 +1,4 @@
1
+ - if CONFIG['custom_links']
2
+ - CONFIG['custom_links'].each do |c|
3
+ -if c['type'].index(record.type)
4
+ %a{href: eval('"'+c['path']+'"')}=c['title']
@@ -0,0 +1 @@
1
+ %a.flv{href: 'javascript:void(0)', url: record.url, key: record.key, title: record.name}watch
File without changes
@@ -1,6 +1,11 @@
1
1
  -if record.srt
2
- %a.watch{href: 'javascript:void(0)', srt: 'true', url: record.url, key: record.key, title: record.name}watch
2
+ %a.watch{href: 'javascript:void(0)', srt: 'true', url: record.url, key: record.key, title: record.name} Watch
3
3
  -else
4
- %a.watch{href: 'javascript:void(0)', url: record.url, key: record.key, title: record.name}watch
5
- -if hash()['remote']
6
- %a.remote{href: 'javascript:void(0)', key: record.key} remote
4
+ %a.watch{href: 'javascript:void(0)', url: record.url, key: record.key, title: record.name} Watch
5
+ -if remote?
6
+ %a.remote{href: 'javascript:void(0)', key: record.key} Remote
7
+ -if request.env['HTTP_X_REAL_IP'].to_s =~ /192.168/
8
+ - url = record.url.sub(/pig.ssig33.com/, '192.168.1.53')
9
+ %a.remote.chromecast{href: 'javascript:void(0)', onclick: "chrome_cast('#{url}', '#{record.key}')", style: 'display:none'} Chromecast
10
+ -else
11
+ %a.remote.chromecast{href: 'javascript:void(0)', onclick: "chrome_cast('#{record.url}', '#{record.key}')", style: 'display:none'} Chromecast
@@ -2,13 +2,16 @@
2
2
  !=partial :"_new_flag", locals: {record: l}
3
3
  %a.main_link{key: l.key, href: l.url}=h(l.name)
4
4
  !=partial :"_ft_#{l.type}", locals: {record: l}
5
+ -if session[:user_id]
6
+ %a.star{href: "/star?href=#{CGI.escape request.url}&key=#{l.key}", key: l.key} #{star?(l.key) ? 'Unstar' : 'Star'}
5
7
  %span.mtime=l.mtime.to_s.sub(/\ \+0900$/, '')
6
- %span.size=number_to_human_size(l.size).encode('UTF-8', 'UTF-8')
8
+ %span.size=number_to_human_size(l.size).to_s.encode('UTF-8', 'UTF-8')
7
9
  %a.meta{href: "/meta/#{l.key}"} Meta
8
10
  -if l.srt
9
11
  %a.sub.meta{href: "/sub/#{l.key}"} Sub
10
12
  -if l.type == 'txt' or l.type == 'read'
11
13
  %a.ao.meta{href: "/ao/#{l.key}"} Aozora
14
+ !=partial :"_custom_links", locals: {record: l}
12
15
  %a.delete{href: 'javascript:void(0)', onclick: "var ok=confirm('Really?'); if (ok) location.href='/delete/#{l.key}?href=#{CGI.escape request.url}'; return false;"} Delete
13
16
  %br
14
17
 
@@ -1,4 +1,4 @@
1
- -if record.type == 'video'
1
+ -if record.type == 'video' or record.type == 'flv'
2
2
  %span.new_flag{key: "movie/#{record.record._key}", style: 'color:lime; font-size:large'}
3
3
  -elsif record.type == 'read'
4
4
  =''
@@ -1,3 +1,7 @@
1
+ button, a, input{
2
+ margin-right: 3px;
3
+ }
4
+
1
5
  body {
2
6
  text-align:center;
3
7
  background:black;
@@ -10,6 +14,10 @@ body {
10
14
  text-align:left;
11
15
  }
12
16
 
17
+ :fullscreen{
18
+ overflow:scroll;
19
+ }
20
+
13
21
  #notice{ color:green; }
14
22
  #error{ color:red; }
15
23
  .small{ font-size:small;}
@@ -30,7 +38,7 @@ nick{color:lightpink}
30
38
  .x-small{font-size:x-small}
31
39
  span.link{font-size:x-large}
32
40
 
33
- a.watch, a.read, a.txt, a.recent, a.kindle{
41
+ a.remote, a.flv, a.watch, a.read, a.txt, a.recent, a.kindle{
34
42
  color:mistyrose;
35
43
  }
36
44
 
@@ -78,6 +86,7 @@ a.delete{
78
86
  width:3em !important;
79
87
  text-align:center !important;
80
88
  font-size:100% !important;
89
+ cursor: pointer;
81
90
  }
82
91
  .main_link {
83
92
  margin-left:3em;