pig-media-server 0.3.2 → 2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/bin/pig-media-server +4 -1
- data/gulpfile.js +33 -0
- data/javascripts/application.js +117 -0
- data/javascripts/chromecast.js +57 -0
- data/javascripts/components/head.js +106 -0
- data/javascripts/components/list.js +104 -0
- data/javascripts/components/new_flag.js +23 -0
- data/javascripts/components/player.js +171 -0
- data/javascripts/components/query_list.js +68 -0
- data/javascripts/components/sort.js +64 -0
- data/javascripts/components/watch.js +48 -0
- data/javascripts/controller.js +62 -0
- data/javascripts/custom_list.js +14 -0
- data/javascripts/event_dispatcher.js +21 -0
- data/javascripts/recent.js +34 -0
- data/javascripts/utils.js +22 -0
- data/javascripts/video.js +10 -0
- data/lib/pig-media-server/api.rb +96 -0
- data/lib/pig-media-server/aspect.rb +10 -5
- data/lib/pig-media-server/backup.rb +69 -0
- data/lib/pig-media-server/cli.rb +60 -25
- data/lib/pig-media-server/crawl.rb +41 -5
- data/lib/pig-media-server/kindle_send.rb +31 -24
- data/lib/pig-media-server/model/data.rb +106 -0
- data/lib/pig-media-server/model/migrate.rb +34 -0
- data/lib/pig-media-server/model/pig.rb +11 -2
- data/lib/pig-media-server/version.rb +1 -1
- data/lib/pig-media-server/views/_custom_links.haml +4 -0
- data/lib/pig-media-server/views/_ft_flv.haml +1 -0
- data/lib/pig-media-server/views/_ft_pdf.haml +0 -0
- data/lib/pig-media-server/views/_ft_video.haml +9 -4
- data/lib/pig-media-server/views/_link.haml +4 -1
- data/lib/pig-media-server/views/_new_flag.haml +1 -1
- data/lib/pig-media-server/views/app.scss +10 -1
- data/lib/pig-media-server/views/bundle.js +13 -0
- data/lib/pig-media-server/views/chromecast.coffee +54 -0
- data/lib/pig-media-server/views/config.coffee +13 -1
- data/lib/pig-media-server/views/config.haml +27 -4
- data/lib/pig-media-server/views/feed.builder +3 -2
- data/lib/pig-media-server/views/flv.coffee +33 -0
- data/lib/pig-media-server/views/index.haml +11 -5
- data/lib/pig-media-server/views/meta.haml +4 -4
- data/lib/pig-media-server/views/movie.coffee +65 -39
- data/lib/pig-media-server/views/react.haml +22 -0
- data/lib/pig-media-server/views/remote.haml +2 -2
- data/lib/pig-media-server/views/session.coffee +5 -0
- data/lib/pig-media-server/views/storage.coffee +5 -16
- data/lib/pig-media-server/views/sub.haml +5 -6
- data/lib/pig-media-server/views/subview.coffee +109 -19
- data/lib/pig-media-server/views/tv.coffee +97 -0
- data/lib/pig-media-server/views/tv.haml +33 -0
- data/lib/pig-media-server/views/unread.coffee +10 -0
- data/lib/pig-media-server/web.rb +102 -37
- data/package.json +23 -0
- data/pig-media-server.gemspec +5 -0
- metadata +123 -38
@@ -0,0 +1,68 @@
|
|
1
|
+
class Item extends React.Component {
|
2
|
+
url(){ return `/?query=${encodeURIComponent(this.props.query)}` }
|
3
|
+
|
4
|
+
click(){
|
5
|
+
this.props.state.open(this.url());
|
6
|
+
}
|
7
|
+
|
8
|
+
delete_query(){
|
9
|
+
if(confirm('Really?')){
|
10
|
+
$.post("/api/r/delete_query_list", {query: this.props.query}).done((data)=>{
|
11
|
+
this.props.update_list();
|
12
|
+
});
|
13
|
+
}
|
14
|
+
}
|
15
|
+
render(){
|
16
|
+
return <span className='main_span'>
|
17
|
+
<a href='javascript:void(0)' onClick={()=> this.click()}>
|
18
|
+
{this.props.query}
|
19
|
+
</a>
|
20
|
+
<a href='javascript:void(0)' className='delete' onClick={()=> this.delete_query()}>
|
21
|
+
Delete
|
22
|
+
</a>
|
23
|
+
</span>
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
class QueryList extends React.Component {
|
28
|
+
constructor(props){
|
29
|
+
super(props);
|
30
|
+
this.state = {};
|
31
|
+
this.state.list = [];
|
32
|
+
this.controller = new Controller()
|
33
|
+
}
|
34
|
+
|
35
|
+
update_list(){
|
36
|
+
$.get("/api/r/query_list").done((data)=>{
|
37
|
+
this.state.list = data;
|
38
|
+
this.setState(this.state);
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
componentDidMount(){
|
43
|
+
this.update_list();
|
44
|
+
}
|
45
|
+
|
46
|
+
show(){
|
47
|
+
if(location.pathname == '/'){
|
48
|
+
if(!this.controller.query()){
|
49
|
+
return true;
|
50
|
+
} else {
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
} else {
|
54
|
+
return false
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
render(){
|
59
|
+
var items = $.map(this.state.list, (query)=>{
|
60
|
+
return <Item key={query} query={query} state={this.props.state} update_list={()=> this.update_list()}/>
|
61
|
+
});
|
62
|
+
return <div>
|
63
|
+
{this.show() ? items : null}
|
64
|
+
</div>
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
window.QueryList = QueryList;
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class QuerySave extends React.Component{
|
2
|
+
constructor(props){
|
3
|
+
super(props);
|
4
|
+
this.controller = new Controller();
|
5
|
+
}
|
6
|
+
|
7
|
+
click(){
|
8
|
+
var query = decodeURIComponent(this.controller.query());
|
9
|
+
$.post("/api/r/query_list", {query: query})
|
10
|
+
}
|
11
|
+
render(){
|
12
|
+
return <span>
|
13
|
+
<a href='javascript:void(0)' onClick={()=> this.click()}>Save Query</a>
|
14
|
+
</span>
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
class Sort extends React.Component{
|
19
|
+
constructor(props){
|
20
|
+
super(props);
|
21
|
+
this.controller = new Controller();
|
22
|
+
}
|
23
|
+
|
24
|
+
sort_by_date(){
|
25
|
+
var query = this.controller.query();
|
26
|
+
var new_url = `/?query=${query}&sort=date&order=descending`
|
27
|
+
history.pushState("", "", new_url);
|
28
|
+
this.props.state.initialize();
|
29
|
+
}
|
30
|
+
|
31
|
+
sort_by_name(){
|
32
|
+
var query = this.controller.query();
|
33
|
+
var new_url = `/?query=${query}&sort=name&order=ascending`
|
34
|
+
history.pushState("", "", new_url);
|
35
|
+
this.props.state.initialize();
|
36
|
+
}
|
37
|
+
|
38
|
+
change_order(order){
|
39
|
+
var query = this.controller.query();
|
40
|
+
var sort = this.controller.params().sort;
|
41
|
+
var new_url = `/?query=${query}&sort=${sort}&order=${order}`
|
42
|
+
history.pushState("", "", new_url);
|
43
|
+
this.props.state.initialize();
|
44
|
+
|
45
|
+
}
|
46
|
+
|
47
|
+
can_change_order(){ return !!this.controller.params().sort; }
|
48
|
+
render(){
|
49
|
+
return <p>
|
50
|
+
<a href="javascript:void(0)" onClick={()=> this.sort_by_date()}>Sort By Date</a>
|
51
|
+
<a href="javascript:void(0)" onClick={()=> this.sort_by_name()}>Sort By Name</a>
|
52
|
+
{this.can_change_order() ?
|
53
|
+
<span>
|
54
|
+
<a href="javascript:void(0)" onClick={()=> this.change_order('ascending')}>Ascending</a>
|
55
|
+
<a href="javascript:void(0)" onClick={()=> this.change_order('descending')}>Descending</a>
|
56
|
+
</span>
|
57
|
+
: null
|
58
|
+
}
|
59
|
+
<QuerySave />
|
60
|
+
</p>
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
window.Sort = Sort;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class ChromeCast extends React.Component {
|
2
|
+
is_video(){ var e = ext(this.props.item.name); return e == 'mp4' || e == 'flv'; }
|
3
|
+
|
4
|
+
click(){ window.chrome_cast(this.props.item.url, this.props.item.key) }
|
5
|
+
render(){
|
6
|
+
return <span>
|
7
|
+
{this.is_video() ?
|
8
|
+
<span>
|
9
|
+
<a
|
10
|
+
className="watch"
|
11
|
+
href="javascript:void(0)"
|
12
|
+
title={this.props.item.name}
|
13
|
+
onClick={()=> this.click()}
|
14
|
+
>ChromeCast</a>
|
15
|
+
|
16
|
+
</span>
|
17
|
+
: null}
|
18
|
+
</span>
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
class Watch extends React.Component {
|
24
|
+
is_video(){
|
25
|
+
var e = ext(this.props.item.name);
|
26
|
+
return e == 'mp4' || e == 'flv';
|
27
|
+
}
|
28
|
+
|
29
|
+
set_video(){ this.props.state.models.video.set(this.props.item); }
|
30
|
+
render(){
|
31
|
+
return <span>
|
32
|
+
{this.is_video() ?
|
33
|
+
<span>
|
34
|
+
<a
|
35
|
+
className="watch"
|
36
|
+
href="javascript:void(0)"
|
37
|
+
title={this.props.item.name}
|
38
|
+
onClick={()=> this.set_video()}
|
39
|
+
>Watch</a>
|
40
|
+
|
41
|
+
</span>
|
42
|
+
: null}
|
43
|
+
</span>
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
window.Watch = Watch;
|
48
|
+
window.ChromeCast = ChromeCast;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Controller {
|
2
|
+
route(){
|
3
|
+
var query =this.params().query;
|
4
|
+
var result = {}
|
5
|
+
switch(location.pathname){
|
6
|
+
case "/":
|
7
|
+
result.page = "list";
|
8
|
+
if(!!query){
|
9
|
+
result.api_url = `/api/r/search?query=${query}`
|
10
|
+
if(!!this.params().sort){ result.api_url += `&sort=${this.params().sort}` }
|
11
|
+
if(!!this.params().order){ result.api_url += `&order=${this.params().order}` }
|
12
|
+
if(!!this.params().page){ result.api_url += `&page=${this.params().page}` }
|
13
|
+
$('title').text(decodeURIComponent(this.query()));
|
14
|
+
} else {
|
15
|
+
result.api_url = null;
|
16
|
+
}
|
17
|
+
break;
|
18
|
+
|
19
|
+
case "/latest":
|
20
|
+
result.page = "list";
|
21
|
+
result.api_url = '/api/r/latest';
|
22
|
+
$('title').text("Latest - Pig Media Server");
|
23
|
+
break;
|
24
|
+
case "/custom":
|
25
|
+
result.page = "list";
|
26
|
+
result.api_url = `/api/r/custom?name=${this.params().name}`;
|
27
|
+
$('title').text(decodeURIComponent(this.params().name));
|
28
|
+
break;
|
29
|
+
|
30
|
+
case "/recommend":
|
31
|
+
result.page = "list";
|
32
|
+
result.api_url = `/api/r/recommend?name=${this.params().name}`;
|
33
|
+
$('title').text('Recommend');
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
return result;
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
params(){
|
42
|
+
var arg = new Object;
|
43
|
+
var pair = location.search.substring(1).split('&');
|
44
|
+
for(var i=0; pair[i]; i++) {
|
45
|
+
var kv = pair[i].split('=');
|
46
|
+
arg[kv[0]] = kv[1];
|
47
|
+
}
|
48
|
+
return arg;
|
49
|
+
}
|
50
|
+
|
51
|
+
query(){ return this.params().query; }
|
52
|
+
|
53
|
+
can_sort_and_paging(){
|
54
|
+
if(location.pathname == '/'){
|
55
|
+
return !!this.query();
|
56
|
+
} else {
|
57
|
+
return false;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
window.Controller = Controller;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class EventDispatcher {
|
2
|
+
constructor(){
|
3
|
+
this.listeners = {};
|
4
|
+
}
|
5
|
+
|
6
|
+
addEventListener(type, callback){
|
7
|
+
if (!this.listeners[type]) { this.listeners[type] = []; }
|
8
|
+
this.listeners[type].push(callback);
|
9
|
+
}
|
10
|
+
clearEventListener(){ this.listeners = {}; }
|
11
|
+
|
12
|
+
dispatchEvent(event) {
|
13
|
+
if (this.listeners[event.type]) {
|
14
|
+
for (var listener in this.listeners[event.type]) {
|
15
|
+
this.listeners[event.type][listener].apply(this.listeners, arguments);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
window.EventDispatcher = EventDispatcher;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Recent {
|
2
|
+
constructor(app){
|
3
|
+
this.app = app;
|
4
|
+
}
|
5
|
+
|
6
|
+
login(){ return !!this.app.state.session.user_id }
|
7
|
+
|
8
|
+
load(){
|
9
|
+
if(this.login()){
|
10
|
+
var dd = new Date();
|
11
|
+
$.get('/recents', {stamp: dd.getTime()}).done((data)=>{
|
12
|
+
this.app.state.recents = data;
|
13
|
+
this.app.update_state();
|
14
|
+
});
|
15
|
+
} else {
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
use(key){
|
20
|
+
if(this.login()){
|
21
|
+
var dd = new Date();
|
22
|
+
$.get('/recents', {stamp: dd.getTime()}).done((recents)=>{
|
23
|
+
recents[key] = {time: parseInt((new Date)/1000), type: 'movie'}
|
24
|
+
$.post("/recents", {data: JSON.stringify(recents)});
|
25
|
+
this.app.state.recents = recents;
|
26
|
+
this.app.update_state();
|
27
|
+
});
|
28
|
+
} else {
|
29
|
+
console.log("kotti");
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
window.Recent = Recent;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
window.round = (i)=>{
|
2
|
+
i = i*10;
|
3
|
+
return Math.round(i)/10
|
4
|
+
}
|
5
|
+
|
6
|
+
window.size_pretty = (size)=>{
|
7
|
+
var size = parseFloat(String(size));
|
8
|
+
var result = size;
|
9
|
+
if(size < 1024){
|
10
|
+
result = `${size} Bytes`
|
11
|
+
} else if(size < 1024*1024){
|
12
|
+
result = `${round(size / 1024)} KB`
|
13
|
+
} else if(size < 1024*1024*1024){
|
14
|
+
result = `${round(size / (1024*1024))} MB`
|
15
|
+
} else if(size < 1024*1024*1024*1024){
|
16
|
+
result = `${round(size / (1024*1024*1024))} GB`
|
17
|
+
}
|
18
|
+
return result
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
window.ext = (str)=>{ return String(str).split('.').pop().toLowerCase(); }
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
module PigMediaServer
|
3
|
+
module API
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
def page
|
6
|
+
params[:page].to_i < 1 ? 1 : params[:page].to_i
|
7
|
+
end
|
8
|
+
|
9
|
+
def size
|
10
|
+
params[:size] ? params[:size].to_i : 50
|
11
|
+
end
|
12
|
+
|
13
|
+
def list_to_json list
|
14
|
+
list.map{|x|
|
15
|
+
hash = x.to_hash
|
16
|
+
hash['custom_links'] = partial :_custom_links, locals: {record: x}
|
17
|
+
hash['metadata'] = !!x.metadata and x.metadata != ''
|
18
|
+
hash['srt'] = !!x.metadata and x.metadata != ''
|
19
|
+
hash
|
20
|
+
}.to_json
|
21
|
+
end
|
22
|
+
|
23
|
+
included do
|
24
|
+
get '/api/r/latest' do
|
25
|
+
content_type :json
|
26
|
+
list_to_json(Groonga['Files'].select.paginate([key: 'mtime', order: 'descending'], size: size, page: page).map{|x| Pig.new(x)})
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/api/r/custom' do
|
30
|
+
content_type :json
|
31
|
+
c = config['custom_list'][params[:name]]
|
32
|
+
list_to_json(Pig.find JSON.parse(open(c).read))
|
33
|
+
end
|
34
|
+
|
35
|
+
get '/api/r/recommend' do
|
36
|
+
content_type :json
|
37
|
+
list = []
|
38
|
+
begin
|
39
|
+
keys = open("#{config['user_data_path']}/recommend/#{params[:name]}").read.split("\n")
|
40
|
+
list = Pig.find(keys)
|
41
|
+
rescue
|
42
|
+
end
|
43
|
+
list_to_json(list)
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/api/r/search' do
|
47
|
+
content_type :json
|
48
|
+
list_to_json(Pig.search params.merge(page: page))
|
49
|
+
end
|
50
|
+
|
51
|
+
get '/api/r/config' do
|
52
|
+
content_type :json
|
53
|
+
config.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
get '/api/r/session' do
|
57
|
+
content_type :json
|
58
|
+
session.to_hash.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
get '/api/r/custom_list' do
|
62
|
+
content_type :json
|
63
|
+
if config['custom_list']
|
64
|
+
config['custom_list'].to_json
|
65
|
+
else
|
66
|
+
{}.to_json
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
get '/api/r/query_list' do
|
71
|
+
content_type :json
|
72
|
+
Groonga['QueryList'].select.map{|x| x.query }.sort.to_json
|
73
|
+
end
|
74
|
+
|
75
|
+
post '/api/r/query_list' do
|
76
|
+
content_type :json
|
77
|
+
key = Digest::MD5.hexdigest(params[:query])
|
78
|
+
unless Groonga['QueryList'][key]
|
79
|
+
Groonga['QueryList'].add(key)
|
80
|
+
Groonga['QueryList'][key].query = params[:query]
|
81
|
+
end
|
82
|
+
{result: true}.to_json
|
83
|
+
end
|
84
|
+
|
85
|
+
post '/api/r/delete_query_list' do
|
86
|
+
content_type :json
|
87
|
+
key = Digest::MD5.hexdigest(params[:query])
|
88
|
+
if Groonga['QueryList'][key]
|
89
|
+
Groonga['QueryList'].delete key
|
90
|
+
end
|
91
|
+
{result: true}.to_json
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -7,22 +7,27 @@ module PigMediaServer
|
|
7
7
|
pit_config = Pit.get 'Pig Media Server'
|
8
8
|
while true
|
9
9
|
GC.start
|
10
|
-
begin
|
10
|
+
#begin
|
11
11
|
q = open("#{pit_config['user_data_path']}/rate/queue.txt").read.split("\n")
|
12
12
|
q.each do |x|
|
13
|
-
|
13
|
+
#begin
|
14
|
+
#next if x == ''
|
14
15
|
key = x.split(' ').first
|
15
16
|
rate = x.split(' ').last
|
16
17
|
pig = Pig.find key
|
18
|
+
next unless pig
|
19
|
+
puts pig.path
|
17
20
|
if rate == '16:9'
|
18
21
|
system 'MP4Box', '-add', "#{pig.record.path}:par=1:1", '-new', "#{pig.record.path}.MP4"
|
19
22
|
FileUtils.mv "#{pig.record.path}.MP4", pig.record.path
|
20
23
|
end
|
24
|
+
#rescue
|
25
|
+
#end
|
21
26
|
end
|
22
27
|
open("#{pit_config['user_data_path']}/rate/queue.txt", 'w'){|x| x.puts ''}
|
23
|
-
rescue => e
|
24
|
-
|
25
|
-
end
|
28
|
+
#rescue => e
|
29
|
+
# p e
|
30
|
+
#end
|
26
31
|
sleep 5
|
27
32
|
end
|
28
33
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'pig-media-server/script'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module PigMediaServer
|
5
|
+
class Backup
|
6
|
+
def backup
|
7
|
+
pit_config = Pit.get 'Pig Media Server'
|
8
|
+
backup_path = pit_config['backup_path']
|
9
|
+
Dir.mktmpdir do |tmpdir|
|
10
|
+
FileUtils.cd tmpdir
|
11
|
+
date = Date.today
|
12
|
+
|
13
|
+
a = $f.select.to_a
|
14
|
+
open("backup.json", "w"){|f|
|
15
|
+
a.each_with_index{|x,i|
|
16
|
+
f.puts [x._key, x.path, x.metadata, x.srt].to_json
|
17
|
+
puts "#{i+1} / #{a.count}" if i%100 ==0
|
18
|
+
}
|
19
|
+
}
|
20
|
+
open('groonga.schema', 'w'){|x| x.puts Groonga::Schema.dump}
|
21
|
+
system "tar zcvf #{date}.tar.gz backup.json groonga.schema"
|
22
|
+
FileUtils.mv "#{date}.tar.gz", backup_path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def restore_from path
|
27
|
+
raise unless File.exist? path
|
28
|
+
pit_config = Pit.get 'Pig Media Server'
|
29
|
+
Dir.glob("#{pit_config['groonga']}/**/*").each{|x| FileUtils.rm x}
|
30
|
+
Groonga::Database.create path: pit_config['groonga']+"/search"
|
31
|
+
Dir.mktmpdir do |tmpdir|
|
32
|
+
FileUtils.cd tmpdir
|
33
|
+
FileUtils.cp path, "."
|
34
|
+
system 'tar', 'xvf', Dir.glob("*.gz").first
|
35
|
+
system 'ls'
|
36
|
+
FileUtils.rm Dir.glob("*.gz").first
|
37
|
+
Groonga::Schema.restore(open('groonga.schema').read){|schema| schema.define }
|
38
|
+
$f = Groonga['Files']
|
39
|
+
json =open("backup.json").read.split("\n")
|
40
|
+
json.each_with_index{|x,i|
|
41
|
+
x = JSON.parse x
|
42
|
+
$f.add(x[0])
|
43
|
+
$f[x[0]].path = x[1]
|
44
|
+
$f[x[0]].metadata = x[2]
|
45
|
+
$f[x[0]].srt = x[3]
|
46
|
+
puts "#{i+1} / #{json.count}" if i%100 == 0 or i+1 == json.count
|
47
|
+
}
|
48
|
+
end
|
49
|
+
ary = $f.select.to_a
|
50
|
+
|
51
|
+
lost = []
|
52
|
+
|
53
|
+
ary.each_with_index{|x,i|
|
54
|
+
if x.path.nil?
|
55
|
+
$f.delete x._key
|
56
|
+
next
|
57
|
+
end
|
58
|
+
unless File.exist? x.path
|
59
|
+
puts x.path
|
60
|
+
$f.delete x._key
|
61
|
+
next
|
62
|
+
end
|
63
|
+
x.mtime = File::Stat.new(x.path).mtime.to_i
|
64
|
+
puts "#{i+1} / #{ary.count}" if (i+1)%1000 == 0 or i+1 == ary.count
|
65
|
+
}
|
66
|
+
lost.sort.each{|x| puts x}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/pig-media-server/cli.rb
CHANGED
@@ -1,27 +1,62 @@
|
|
1
|
-
|
2
|
-
when 'setup'
|
3
|
-
require 'fileutils'
|
4
|
-
config = Pit.get("Pig Media Server", require:{
|
5
|
-
'path' => 'Path of your storage',
|
6
|
-
'groonga' => "Path of groonga's files",
|
7
|
-
'exclude_path' => 'Exclude Path(Array)',
|
8
|
-
'user_data_path' => 'Path of User Data'
|
9
|
-
})
|
1
|
+
require 'thor'
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
3
|
+
module PigMediaServer
|
4
|
+
class CLI < Thor
|
5
|
+
desc 'setup', 'setup configurations'
|
6
|
+
def setup
|
7
|
+
require 'fileutils'
|
8
|
+
config = Pit.get("Pig Media Server", require:{
|
9
|
+
'hostname' => 'Your host name',
|
10
|
+
'path' => 'Path of your storage',
|
11
|
+
'groonga' => "Path of groonga's files",
|
12
|
+
'exclude_path' => 'Exclude Path(Array)',
|
13
|
+
'user_data_path' => 'Path of User Data'
|
14
|
+
})
|
15
|
+
|
16
|
+
puts "Path: #{config['path']}"
|
17
|
+
puts "Groonga: #{config['groonga']}"
|
18
|
+
FileUtils.mkdir_p config['user_data_path']
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'crawl', 'run crawler'
|
22
|
+
def crawl
|
23
|
+
require 'pig-media-server/crawl'
|
24
|
+
PigMediaServer::Crawl.new.all
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'server [PORT]', 'run server'
|
28
|
+
option :bind, :type => :string, :default => '0.0.0.0'
|
29
|
+
option :port, :type => :numeric, :default => 8080
|
30
|
+
def server(port = nil)
|
31
|
+
require 'pig-media-server/web'
|
32
|
+
port ||= options[:port]
|
33
|
+
Sinatra::Base.server.delete 'HTTP' # conflict with HTTP.gem
|
34
|
+
PigMediaServer::Web.run! :bind => options[:bind], :port => port.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'aspect', 'fix aspect'
|
38
|
+
def aspect
|
39
|
+
require 'pig-media-server/aspect'
|
40
|
+
PigMediaServer::Aspect.new.run
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'kindle-send', 'send to kindle'
|
44
|
+
def kindle_send
|
45
|
+
require 'pig-media-server/kindle_send'
|
46
|
+
PigMediaServer::KindleSend.new.run
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'backup', 'backup groonga\'s data'
|
50
|
+
def backup
|
51
|
+
require 'pig-media-server/backup'
|
52
|
+
PigMediaServer::Backup.new.backup
|
53
|
+
end
|
54
|
+
|
55
|
+
option :path, required: true
|
56
|
+
desc 'restore', 'restore groonga\'s data'
|
57
|
+
def restore
|
58
|
+
require 'pig-media-server/backup'
|
59
|
+
PigMediaServer::Backup.new.restore_from options[:path]
|
60
|
+
end
|
61
|
+
end
|
27
62
|
end
|