rubyhexagon 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/api.rb +31 -75
- data/lib/container.rb +2 -2
- data/lib/pool.rb +1 -1
- data/lib/post.rb +20 -81
- data/lib/rubyhexagon.rb +2 -3
- data/lib/search.rb +36 -28
- data/lib/set.rb +1 -1
- data/lib/standard/error.rb +1 -1
- data/lib/standard/hash.rb +1 -1
- data/lib/standard/http.rb +43 -34
- data/lib/standard/int.rb +1 -1
- data/lib/standard/string.rb +5 -1
- data/lib/standard/time.rb +2 -2
- metadata +46 -26
- data/bin/e621 +0 -27
- data/lib/config.rb +0 -46
- data/lib/examples/add.rb +0 -57
- data/lib/examples/db.rb +0 -143
- data/lib/examples/sync.rb +0 -187
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 34c8430199af7c9d7c8e2efb98cf8da90cbcdf09
|
4
|
+
data.tar.gz: 5675d205567c98595d52b5651eefe4fdd99f5dc6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4907ea016fa1d66489323f71cf10ed2ff9bd07a251f7462c6d7c09d8820115477ae9f5378431b583724ce81d9866fe6626db07cbc2947c94a1e05a94168e7738
|
7
|
+
data.tar.gz: 6aa265a2deb00c532ec2fcc0d7ac60a79fea98cd5b237f5c628ea1846dc91ccab034cb045dc121e3db9bb5543bd878eb4c08d7aad0e0b69f3efed6237c37237a
|
data/lib/api.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -20,104 +20,60 @@
|
|
20
20
|
require "standard/http"
|
21
21
|
|
22
22
|
module E621
|
23
|
-
attr_reader :user
|
24
23
|
class API
|
25
|
-
|
26
|
-
def initialize(mod=nil)
|
24
|
+
def initialize(user=nil,pass=nil)
|
27
25
|
@http = HTTP.new
|
28
|
-
|
29
|
-
|
26
|
+
login(user,pass) if !defined? @@login
|
27
|
+
end
|
28
|
+
# A wrapper function to fit into the general theme better.
|
29
|
+
def post_list(*args)
|
30
|
+
post_index(*args)
|
30
31
|
end
|
31
32
|
# Send commands to API and parse all answers, even errors.
|
32
33
|
# Also make it work with POST and GET requests.
|
33
34
|
def method_missing(method,*args)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# is something wrong
|
46
|
-
retry
|
47
|
-
end
|
48
|
-
#raise APIError,json["reason"] if json.include?("success") && !json["success"]
|
49
|
-
return json
|
50
|
-
else
|
51
|
-
raise NoMethodError, "undefined method #{method} for #{self.class}"
|
52
|
-
end
|
35
|
+
request = request2body(args.first)
|
36
|
+
method = method.to_s.split("_")
|
37
|
+
m = case method[0]
|
38
|
+
when "post" then
|
39
|
+
case method[1]
|
40
|
+
when "show" then :get
|
41
|
+
else :post
|
42
|
+
end
|
43
|
+
else :post
|
44
|
+
end
|
45
|
+
@http.__send__(m,"/#{method.join("/")}.json",request)
|
53
46
|
end
|
54
47
|
private
|
55
48
|
# This helper function provides the functionality of translating Ruby Hashes
|
56
49
|
# into HTTP POST body strings.
|
57
|
-
def request2body(
|
58
|
-
|
59
|
-
|
60
|
-
s += "&" unless s == String.new
|
50
|
+
def request2body(request)
|
51
|
+
query = @@login ? "#@@login&" : String.new
|
52
|
+
request = request.map do |k,v|
|
61
53
|
if v.is_a?(Hash) then
|
62
|
-
t
|
63
|
-
|
64
|
-
|
65
|
-
t += "#{k}[#{e}]=#{a}"
|
66
|
-
end
|
67
|
-
s += t
|
68
|
-
else
|
69
|
-
s += "#{k}=#{v}"
|
54
|
+
raise Argumenterror, "Hashes as request values aren't allowed."
|
55
|
+
elsif v.is_a?(Array) then
|
56
|
+
v = v.join(",")
|
70
57
|
end
|
58
|
+
"#{k}=#{v}"
|
71
59
|
end
|
72
|
-
|
73
|
-
return
|
60
|
+
query += request.join("&")
|
61
|
+
return query
|
74
62
|
end
|
75
63
|
# Perform an API and site login. This function needs to be called once
|
76
64
|
# before any actual API call can be made.
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
# Perform a re-login if the last time is older than x days. Or if there is
|
81
|
-
# no cookie.
|
82
|
-
passwd = File.expand_path(Config.paths["passwd"])
|
83
|
-
if File.exist?(passwd) then
|
84
|
-
File.open(passwd){|f|@passwd=f.read.parse}
|
65
|
+
def login(user,pass)
|
66
|
+
if user == nil && pass == nil then
|
67
|
+
@@login = nil
|
85
68
|
else
|
86
|
-
|
87
|
-
end
|
88
|
-
if (Time.now.to_i-@passwd["last_login"].to_i) < 3.days then
|
89
|
-
@@login = @passwd["login"]
|
90
|
-
else
|
91
|
-
if @passwd["name"] != "" && @passwd["pass"] != "" then
|
92
|
-
name,pass = @passwd["name"],@passwd["pass"]
|
93
|
-
else
|
94
|
-
puts "No user data found. Please provide user data."
|
95
|
-
name,pass = get_credentials
|
96
|
-
@passwd["name"],@passwd["pass"] = name,pass
|
97
|
-
# Store that data for later use.
|
98
|
-
end
|
99
|
-
request = "name=#{name}&password=#{pass}"
|
69
|
+
request = {name:name,password:pass}
|
100
70
|
body = @http.get("/user/login.json",request)
|
101
71
|
if body.has_key?("success") && (!body["success"] || body["success"] == "failed") then
|
102
72
|
raise AuthentificationError, "Username or password wrong!"
|
103
73
|
else
|
104
74
|
@@login = "login=#{body["name"]}&password_hash=#{body["password_hash"]}"
|
105
|
-
@passwd["login"] = @@login # Save login string for later use.
|
106
75
|
end
|
107
|
-
@passwd["last_login"] = Time.now.to_i
|
108
|
-
# Write everything back!
|
109
|
-
File.open(passwd,"w"){|f|f.print @passwd.to_json}
|
110
76
|
end
|
111
|
-
return @passwd["name"]
|
112
|
-
end
|
113
|
-
# If there is no data saved for login, ask the user. They must know!
|
114
|
-
def get_credentials
|
115
|
-
print "Username: "
|
116
|
-
name = $stdin.gets.chomp
|
117
|
-
print "Password: "
|
118
|
-
pass = `stty_o=$(stty -g);stty -echo;read pass;stty $stty_o; echo $pass`.chomp
|
119
|
-
puts
|
120
|
-
return [name,pass]
|
121
77
|
end
|
122
78
|
end
|
123
79
|
end
|
data/lib/container.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -20,7 +20,7 @@
|
|
20
20
|
module E621
|
21
21
|
class Container
|
22
22
|
def method_missing(method)
|
23
|
-
if instance_variables.include?("@#{method}".to_sym) then
|
23
|
+
if instance_variables.include?("@#{method}".to_sym) && method != :api then
|
24
24
|
return instance_variable_get("@#{method}")
|
25
25
|
else
|
26
26
|
raise NoMethodError, "undefined method #{method} for #{self.class}"
|
data/lib/pool.rb
CHANGED
data/lib/post.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -22,90 +22,29 @@ require "digest/md5"
|
|
22
22
|
module E621
|
23
23
|
class Post < Container
|
24
24
|
def initialize(post)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
return body
|
36
|
-
end
|
37
|
-
|
38
|
-
def download(where)
|
39
|
-
if @file_url then
|
40
|
-
host,port = @file_url.sub(%r{^.+?//},"").sub(%r{/.+$},""),@file_url.match(/^https/) ? 443 : 80
|
25
|
+
@api = API.new
|
26
|
+
if post.is_a?(Fixnum) || (post.is_a?(String) && post.match(/^[0-9,a-f]+$/i)) then
|
27
|
+
post = if post.is_a?(String) && post.length == 32 then {md5:post}
|
28
|
+
elsif post.is_a?(Fixnum) || (post.is_a?(String) && post.match(/^\d+$/)) then
|
29
|
+
{id:post.to_i}
|
30
|
+
else
|
31
|
+
raise ArgumentError, "Neither an ID nor a MD5 Hash."
|
32
|
+
end
|
33
|
+
post = @api.post_show(post)
|
34
|
+
elsif post.is_a?(Hash) then # Variable post is ready to use. Do nothing.
|
41
35
|
else
|
42
|
-
|
43
|
-
@file_url = "/data/#{@md5[0,2]}/#{@md5[2,2]}/#@md5.#@file_ext"
|
36
|
+
raise ArgumentError, "Post only accepts an id, a MD5 hashsum or a Ruby hash."
|
44
37
|
end
|
45
|
-
|
46
|
-
if !File.exist?(where) then
|
47
|
-
body = ""
|
48
|
-
while Digest::MD5.hexdigest(body) != @md5 do
|
49
|
-
body = http.get(@file_url.sub(/^.+?\.net/,""),"")["body"]
|
50
|
-
end
|
51
|
-
File.open(where,"w") do |f|
|
52
|
-
f.print body
|
53
|
-
end
|
54
|
-
else
|
55
|
-
md5 = String.new
|
56
|
-
File.open(where,"r") do |f|
|
57
|
-
md5 = Digest::MD5.hexdigest(f.read)
|
58
|
-
end
|
59
|
-
if md5 != @md5 then
|
60
|
-
body = ""
|
61
|
-
while Digest::MD5.hexdigest(body) != @md5 do
|
62
|
-
body = http.get(@file_url.sub(/^.+?\.net/,""),"")["body"]
|
63
|
-
end
|
64
|
-
File.open(where,"w") do |f|
|
65
|
-
f.print body
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def add_to_set(id)
|
72
|
-
api = API.new("set")
|
73
|
-
api.post("add_post",{"post_id"=>@id,"set_id"=>id})
|
74
|
-
end
|
75
|
-
|
76
|
-
def remove_from_set(id)
|
77
|
-
api = API.new("set")
|
78
|
-
api.post("remove_post",{"post_id"=>@id,"set_id"=>id})
|
79
|
-
end
|
80
|
-
|
81
|
-
def favorite
|
82
|
-
api = API.new("favorite")
|
83
|
-
api.post("create",{"id"=>@id})
|
84
|
-
end
|
85
|
-
|
86
|
-
def unfavorite
|
87
|
-
api = API.new("favorite")
|
88
|
-
api.post("destroy",{"id"=>@id})
|
89
|
-
end
|
90
|
-
|
91
|
-
def vote(dir)
|
92
|
-
dir = if dir >= 0 then 1 elsif dir < 0 then -1 end
|
93
|
-
api = API.new("post")
|
94
|
-
api.post("vote",{"id"=>@id,"score"=>dir})
|
95
|
-
end
|
96
|
-
|
97
|
-
def keys
|
98
|
-
return instance_variables.map{|i|i.to_s.sub("@","")}
|
38
|
+
set_variables(post)
|
99
39
|
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
40
|
+
alias show initialize
|
41
|
+
# Cast a vote! Any value above 0 votes up, every value below 0 votes down.
|
42
|
+
# Zero itself causes an error.
|
43
|
+
def vote(direction)
|
44
|
+
if direction > 0 then @api.post_vote(1)
|
45
|
+
elsif direction < 0 then @api.post_vote(-1)
|
46
|
+
else raise ArgumentError, "Zero isn't allowed for voting results."
|
107
47
|
end
|
108
|
-
return json_hash.to_json
|
109
48
|
end
|
110
49
|
end
|
111
50
|
end
|
data/lib/rubyhexagon.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -23,12 +23,11 @@ require "standard/error"
|
|
23
23
|
require "standard/time"
|
24
24
|
|
25
25
|
require "api"
|
26
|
-
require "config"
|
27
26
|
require "container"
|
28
27
|
require "search"
|
29
28
|
require "pool"
|
30
29
|
|
31
30
|
module E621
|
32
31
|
Name = "rubyhexagon"
|
33
|
-
Version = "0.4.
|
32
|
+
Version = "0.4.1"
|
34
33
|
end
|
data/lib/search.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -18,56 +18,64 @@
|
|
18
18
|
=end
|
19
19
|
|
20
20
|
require "post"
|
21
|
+
require "thread"
|
21
22
|
|
22
23
|
module E621
|
23
|
-
attr_reader :posts
|
24
24
|
class Search
|
25
25
|
# commands update/download
|
26
|
-
def initialize(query)
|
27
|
-
@api
|
28
|
-
@
|
29
|
-
@request = {"limit"=>100,"page"=>1,"tags"=>query.join("+")}
|
30
|
-
fetch
|
26
|
+
def initialize(query,page=1)
|
27
|
+
@api, @queue = API.new, SizedQueue.new(4096)
|
28
|
+
@request = {limit:100,page:page,tags:query.url_encode}
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
@request[
|
35
|
-
fetch
|
31
|
+
def next_page
|
32
|
+
@request[:page] += 1
|
36
33
|
end
|
37
34
|
|
35
|
+
def previous_page
|
36
|
+
@request[:page] -= 1
|
37
|
+
end
|
38
|
+
# Return each post via a block and process them individually.
|
39
|
+
# This could cause a race condition in the unlikely manner when the queue is
|
40
|
+
# empty and not being filled again, but the worker is still runnning.
|
38
41
|
def each_post
|
39
|
-
|
40
|
-
|
42
|
+
fetch_all
|
43
|
+
until !@worker.status do
|
44
|
+
until @queue.empty? do
|
45
|
+
post = @queue.pop
|
41
46
|
yield post
|
42
47
|
end
|
43
|
-
next!
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
47
|
-
def
|
48
|
-
return @request["page"]
|
49
|
-
end
|
50
|
-
|
51
|
-
def page=(page)
|
52
|
-
@request["page"]=page
|
51
|
+
def posts
|
53
52
|
fetch
|
54
53
|
end
|
55
54
|
|
56
|
-
def
|
57
|
-
@request[
|
58
|
-
fetch
|
55
|
+
def page
|
56
|
+
return @request[:page]
|
59
57
|
end
|
60
58
|
|
61
|
-
def
|
62
|
-
|
63
|
-
{"name"=>@name,"queries"=>@queries,"posts"=>posts}.to_json
|
59
|
+
def page=(page)
|
60
|
+
@request[:page] = page
|
64
61
|
end
|
62
|
+
|
65
63
|
private
|
66
64
|
def fetch
|
67
|
-
@
|
68
|
-
|
69
|
-
Post.new(post) unless post["tags"].match(@bad_tags)
|
65
|
+
@api.post_list(@request).map do |post|
|
66
|
+
Post.new(post)
|
70
67
|
end.compact
|
71
68
|
end
|
69
|
+
def fetch_all
|
70
|
+
@worker = Thread.new do
|
71
|
+
until (posts = @api.post_list(@request)) == Array.new do
|
72
|
+
posts.each do |post|
|
73
|
+
post = Post.new(post)
|
74
|
+
@queue << post if post
|
75
|
+
end
|
76
|
+
next_page
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
72
80
|
end
|
73
81
|
end
|
data/lib/set.rb
CHANGED
data/lib/standard/error.rb
CHANGED
data/lib/standard/hash.rb
CHANGED
data/lib/standard/http.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -25,28 +25,25 @@ module E621
|
|
25
25
|
@http = Net::HTTP.new(host,port)
|
26
26
|
@http.use_ssl = true if port == 443
|
27
27
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
message += body
|
46
|
-
mlength = (message.length/1024.0).round(1)
|
47
|
-
print "Downloaded #{" "*(clength-mlength.to_s.length)}#{mlength}/#{count}kB\r"
|
28
|
+
def method_missing(method, *args)
|
29
|
+
if [:get,:post].include?(method) then
|
30
|
+
tries,url,request = 0, *args
|
31
|
+
begin
|
32
|
+
response = case method
|
33
|
+
when :get then @http.get("#{url}?#{request}")
|
34
|
+
when :post then @http.post(url,request)
|
35
|
+
end
|
36
|
+
rescue
|
37
|
+
sleep 2**tries
|
38
|
+
tries += 1
|
39
|
+
raise if tries >= 8
|
40
|
+
retry
|
41
|
+
end
|
42
|
+
response = parse_body(response)
|
43
|
+
else
|
44
|
+
raise NoMethodError, "undefined method #{method} for #{self.class}"
|
48
45
|
end
|
49
|
-
return
|
46
|
+
return response
|
50
47
|
end
|
51
48
|
private
|
52
49
|
# As every body gets processed the same, just put it into a seperate method.
|
@@ -64,18 +61,30 @@ module E621
|
|
64
61
|
# Parse all code that returns not in JSON to actual JSON like hashes.
|
65
62
|
def errorcode(code,url)
|
66
63
|
body = {"success"=>false,"reason"=>""}
|
67
|
-
body["reason"] = if code.match(/3\d{2}/) then
|
68
|
-
|
69
|
-
elsif code.match(/
|
70
|
-
|
71
|
-
elsif code.match(/
|
72
|
-
|
73
|
-
elsif code.match(/
|
74
|
-
|
75
|
-
elsif code.match(/
|
76
|
-
|
77
|
-
elsif code.match(/
|
78
|
-
|
64
|
+
body["reason"] = if code.match(/3\d{2}/) then
|
65
|
+
"We got redirected!"
|
66
|
+
elsif code.match(/403/) then
|
67
|
+
"Access denied!"
|
68
|
+
elsif code.match(/404/) then
|
69
|
+
"File not found!"
|
70
|
+
elsif code.match(/420/) then
|
71
|
+
"Record could not be saved!"
|
72
|
+
elsif code.match(/421/) then
|
73
|
+
"User is throttled, try again later!"
|
74
|
+
elsif code.match(/422/) then
|
75
|
+
"The resource is locked!"
|
76
|
+
elsif code.match(/423/) then
|
77
|
+
"Resource already exists!"
|
78
|
+
elsif code.match(/4\d{2}/) then
|
79
|
+
"We made a bad request!"
|
80
|
+
elsif code.match(/500/) then
|
81
|
+
"Internal server error!"
|
82
|
+
elsif code.match(/503/) then
|
83
|
+
"Server has too much load!"
|
84
|
+
elsif code.match(/5\d{2}/) then
|
85
|
+
"Some unkown server side error!"
|
86
|
+
else
|
87
|
+
"HTTP response code out of range!!"
|
79
88
|
end
|
80
89
|
return body
|
81
90
|
end
|
data/lib/standard/int.rb
CHANGED
data/lib/standard/string.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -18,6 +18,7 @@
|
|
18
18
|
=end
|
19
19
|
|
20
20
|
require "json"
|
21
|
+
require "cgi"
|
21
22
|
|
22
23
|
class String
|
23
24
|
# Make json parsing a lot easier and less to write.
|
@@ -27,6 +28,9 @@ class String
|
|
27
28
|
def to_ascii
|
28
29
|
self.gsub("_"," ").encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "")
|
29
30
|
end
|
31
|
+
def url_encode
|
32
|
+
CGI.escape(self)
|
33
|
+
end
|
30
34
|
# Remove all tags inside of a string.
|
31
35
|
def clean
|
32
36
|
self.gsub(/<.+?>/,"")
|
data/lib/standard/time.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright 2014 Maxine Red <
|
2
|
+
Copyright 2014, 2015 Maxine Red <maxine@furfind.net>
|
3
3
|
|
4
4
|
This file is part of rubyhexagon.
|
5
5
|
|
@@ -19,7 +19,7 @@
|
|
19
19
|
class Time
|
20
20
|
# A general to_s function for Time objects.
|
21
21
|
def to_s
|
22
|
-
self.strftime("%b %e,%Y %I:%M %p")
|
22
|
+
self.strftime("%b %e,%Y %I:%M:%S %p")
|
23
23
|
end
|
24
24
|
# This methods takes a block and returns how long it took to execute that block.
|
25
25
|
def self.measure
|
metadata
CHANGED
@@ -1,64 +1,84 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyhexagon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Maxine Red
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
11
|
+
date: 2016-01-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.18'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.18'
|
14
41
|
description: Rubyhexagon provides Ruby bindings for the e621 [dot] net API.
|
15
|
-
email:
|
16
|
-
executables:
|
17
|
-
- e621
|
42
|
+
email: maxine@furfind.net
|
43
|
+
executables: []
|
18
44
|
extensions: []
|
19
45
|
extra_rdoc_files: []
|
20
46
|
files:
|
21
|
-
- lib/
|
22
|
-
- lib/
|
23
|
-
- lib/examples/add.rb
|
24
|
-
- lib/examples/db.rb
|
47
|
+
- lib/api.rb
|
48
|
+
- lib/container.rb
|
25
49
|
- lib/pool.rb
|
26
50
|
- lib/post.rb
|
27
|
-
- lib/
|
28
|
-
- lib/
|
51
|
+
- lib/rubyhexagon.rb
|
52
|
+
- lib/search.rb
|
53
|
+
- lib/set.rb
|
29
54
|
- lib/standard/error.rb
|
30
|
-
- lib/standard/int.rb
|
31
55
|
- lib/standard/hash.rb
|
56
|
+
- lib/standard/http.rb
|
57
|
+
- lib/standard/int.rb
|
32
58
|
- lib/standard/string.rb
|
33
|
-
- lib/
|
34
|
-
- lib/container.rb
|
35
|
-
- lib/rubyhexagon.rb
|
36
|
-
- lib/api.rb
|
37
|
-
- lib/search.rb
|
38
|
-
- bin/e621
|
59
|
+
- lib/standard/time.rb
|
39
60
|
homepage: https://github.com/maxine-red/rubyhexagon
|
40
61
|
licenses:
|
41
62
|
- GPL-3.0
|
63
|
+
metadata: {}
|
42
64
|
post_install_message:
|
43
65
|
rdoc_options: []
|
44
66
|
require_paths:
|
45
67
|
- lib
|
46
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
69
|
requirements:
|
49
|
-
- -
|
70
|
+
- - ">="
|
50
71
|
- !ruby/object:Gem::Version
|
51
72
|
version: 1.9.2
|
52
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
74
|
requirements:
|
55
|
-
- -
|
75
|
+
- - ">="
|
56
76
|
- !ruby/object:Gem::Version
|
57
77
|
version: '0'
|
58
78
|
requirements: []
|
59
79
|
rubyforge_project:
|
60
|
-
rubygems_version:
|
80
|
+
rubygems_version: 2.2.2
|
61
81
|
signing_key:
|
62
|
-
specification_version:
|
82
|
+
specification_version: 4
|
63
83
|
summary: Rubyhexagon, Ruby bindings for e621[dot]net.
|
64
84
|
test_files: []
|
data/bin/e621
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
=begin
|
3
|
-
Copyright 2014 Maxine Red <maxine_red1@yahoo.com>
|
4
|
-
|
5
|
-
This file is part of rubyhexahon.
|
6
|
-
|
7
|
-
rubyhexahon is free software: you can redistribute it and/or modify
|
8
|
-
it under the terms of the GNU General Public License as published by
|
9
|
-
the Free Software Foundation, either version 3 of the License, or
|
10
|
-
(at your option) any later version.
|
11
|
-
|
12
|
-
rubyhexahon is distributed in the hope that it will be useful,
|
13
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
-
GNU General Public License for more details.
|
16
|
-
|
17
|
-
You should have received a copy of the GNU General Public License
|
18
|
-
along with rubyhexahon. If not, see <http://www.gnu.org/licenses/>.
|
19
|
-
=end
|
20
|
-
|
21
|
-
$:.unshift File.dirname(__FILE__)+"/../lib"
|
22
|
-
|
23
|
-
require "rubyhexagon"
|
24
|
-
|
25
|
-
$0 = "E621 #{ARGV[0]} #{ARGV[1]}"
|
26
|
-
|
27
|
-
require "examples/#{ARGV.shift}"
|
data/lib/config.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Copyright 2014 Maxine Red <maxine_red1@yahoo.com>
|
3
|
-
|
4
|
-
This file is part of rubyhexagon.
|
5
|
-
|
6
|
-
rubyhexagon is free software: you can redistribute it and/or modify
|
7
|
-
it under the terms of the GNU General Public License as published by
|
8
|
-
the Free Software Foundation, either version 3 of the License, or
|
9
|
-
(at your option) any later version.
|
10
|
-
|
11
|
-
rubyhexagon is distributed in the hope that it will be useful,
|
12
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU General Public License for more details.
|
15
|
-
|
16
|
-
You should have received a copy of the GNU General Public License
|
17
|
-
along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
=end
|
19
|
-
module E621
|
20
|
-
class Config
|
21
|
-
def self.config
|
22
|
-
return @@config
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.paths
|
26
|
-
return @@paths
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.blacklist
|
30
|
-
return @@blacklist
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.config=(config)
|
34
|
-
if File.exist?(config) then
|
35
|
-
File.open(config) do |f|
|
36
|
-
c = f.read.parse
|
37
|
-
@@paths = c.delete("paths")
|
38
|
-
@@blacklist = c.delete("blacklist")
|
39
|
-
@@config = c
|
40
|
-
end
|
41
|
-
else
|
42
|
-
raise ArgumentError, "No configuration file specified. Broken installation!"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/lib/examples/add.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Copyright 2014 Maxine Red <maxine_red1@yahoo.com>
|
3
|
-
|
4
|
-
This file is part of rubyhexagon.
|
5
|
-
|
6
|
-
rubyhexagon is free software: you can redistribute it and/or modify
|
7
|
-
it under the terms of the GNU General Public License as published by
|
8
|
-
the Free Software Foundation, either version 3 of the License, or
|
9
|
-
(at your option) any later version.
|
10
|
-
|
11
|
-
rubyhexagon is distributed in the hope that it will be useful,
|
12
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU General Public License for more details.
|
15
|
-
|
16
|
-
You should have received a copy of the GNU General Public License
|
17
|
-
along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
=end
|
19
|
-
|
20
|
-
require "json"
|
21
|
-
|
22
|
-
include E621
|
23
|
-
|
24
|
-
mod = ARGV.shift
|
25
|
-
|
26
|
-
$0 = "E621 #{mod}"
|
27
|
-
|
28
|
-
E621::Config.config = File.expand_path("~/.hexagon/conf.json")
|
29
|
-
Dir.chdir(File.expand_path(E621::Config.paths["home"])) do
|
30
|
-
pools, api = Array.new, API.new(mod)
|
31
|
-
File.open(File.expand_path(E621::Config.paths["j#{mod}s"])) do |f|
|
32
|
-
pools = JSON.parser.new(f.read).parse
|
33
|
-
end
|
34
|
-
puts "Old count: #{pools.length}"
|
35
|
-
candidates = ARGV.map{|x|x.to_i}.reject{|x|x==0}
|
36
|
-
puts "Adding candidates: #{candidates.length}"
|
37
|
-
new = ARGV.map{|x|x.to_i}.reject{|x|x==0||pools.include?(x)}
|
38
|
-
new.each do |id|
|
39
|
-
pool = api.post("show",{"id"=>id})
|
40
|
-
if pool["id"] && mod == "pool" then
|
41
|
-
pools << id
|
42
|
-
elsif pool["id"] && mod == "set" then
|
43
|
-
pools << {"id"=>pool["id"],"owner"=>pool["user_id"]}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
puts "Adding: #{new.length}"
|
47
|
-
if mod == "pool" then
|
48
|
-
pools = pools.sort.uniq
|
49
|
-
elsif mod == "set" then
|
50
|
-
pools = pools.sort{|k1,k2|k1["id"]<=>k2["id"]}.uniq
|
51
|
-
end
|
52
|
-
puts "New count: #{pools.length}"
|
53
|
-
pools = pools.to_json
|
54
|
-
File.open(File.expand_path(E621::Config.paths["j#{mod}s"]),"w") do |f|
|
55
|
-
f.print pools
|
56
|
-
end
|
57
|
-
end
|
data/lib/examples/db.rb
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Copyright 2014 Maxine Red <maxine_red1@yahoo.com>
|
3
|
-
|
4
|
-
This file is part of rubyhexagon.
|
5
|
-
|
6
|
-
rubyhexagon is free software: you can redistribute it and/or modify
|
7
|
-
it under the terms of the GNU General Public License as published by
|
8
|
-
the Free Software Foundation, either version 3 of the License, or
|
9
|
-
(at your option) any later version.
|
10
|
-
|
11
|
-
rubyhexagon is distributed in the hope that it will be useful,
|
12
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU General Public License for more details.
|
15
|
-
|
16
|
-
You should have received a copy of the GNU General Public License
|
17
|
-
along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
=end
|
19
|
-
|
20
|
-
require "logger"
|
21
|
-
require "thread"
|
22
|
-
require "pg"
|
23
|
-
|
24
|
-
include E621
|
25
|
-
|
26
|
-
$form = "%b %e, %Y %I:%M:%S %p"
|
27
|
-
|
28
|
-
require "search"
|
29
|
-
require "pool"
|
30
|
-
require "set"
|
31
|
-
|
32
|
-
Thread.abort_on_exception = true
|
33
|
-
|
34
|
-
class DB
|
35
|
-
def initialize(database)
|
36
|
-
@pg = PG.connect(dbname:database)
|
37
|
-
@mt = Mutex.new
|
38
|
-
end
|
39
|
-
def exec(query)
|
40
|
-
@mt.synchronize do
|
41
|
-
result = @pg.exec(query)
|
42
|
-
return result
|
43
|
-
end
|
44
|
-
end
|
45
|
-
def escape_string(str)
|
46
|
-
@pg.escape_string(str)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class Sync
|
51
|
-
def initialize
|
52
|
-
E621::Config.config = File.expand_path("~/.hexagon/conf.json")
|
53
|
-
if $stdout.tty? then
|
54
|
-
@log = Logger.new($stdout)
|
55
|
-
@log.level = Logger::DEBUG
|
56
|
-
else
|
57
|
-
@log = Logger.new(File.expand_path(E621::Config.paths["logging"]))
|
58
|
-
@log.level = Logger::INFO
|
59
|
-
end
|
60
|
-
@log.formatter = proc do |sev,dat,prog,msg|
|
61
|
-
"#{Time.now.strftime($form)} [#{sev.pad(5)}] #{msg}#$/"
|
62
|
-
end
|
63
|
-
api = API.new("user") # Used for login
|
64
|
-
@log.info("Program #$0 started.")
|
65
|
-
@uid = api.get("index",{"name"=>api.user}).first["id"]
|
66
|
-
@max_wait = 1
|
67
|
-
Dir.chdir(File.expand_path(E621::Config.paths["files"]))
|
68
|
-
@db = DB.new("danbooru")
|
69
|
-
@queue = Queue.new
|
70
|
-
@mt = Mutex.new
|
71
|
-
end
|
72
|
-
|
73
|
-
def threads
|
74
|
-
return E621::Config.threads
|
75
|
-
end
|
76
|
-
|
77
|
-
def worker(mod)
|
78
|
-
if mod == "post" then
|
79
|
-
fetch_posts
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def fetch_posts
|
84
|
-
lid = @db.exec("SELECT id FROM e621.posts ORDER BY id DESC LIMIT 1;").first
|
85
|
-
if lid then
|
86
|
-
lid = lid["id"].to_i
|
87
|
-
else
|
88
|
-
lid = 0
|
89
|
-
end
|
90
|
-
posts = Search.new(["order:id", "id:#{lid}.."])
|
91
|
-
@cols = ["id","tags","artist","created_at","score","md5","file_ext","description","rating","width","height","has_children","parent_id","file_size"]
|
92
|
-
posts.each_post do |post|
|
93
|
-
@queue << [post,"#{post.md5[0,2]}/#{post.md5[2,2]}/#{post.md5}.#{post.file_ext}"]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
def download
|
97
|
-
Thread.current.exit if @queue.empty?
|
98
|
-
post,path = @queue.pop
|
99
|
-
m = String.new
|
100
|
-
path.split("/")[0,2].each do |d|
|
101
|
-
m += "#{d}/"
|
102
|
-
Dir.mkdir(m) unless File.exists?(m)
|
103
|
-
end
|
104
|
-
tries = 0
|
105
|
-
begin
|
106
|
-
post.download(path)
|
107
|
-
rescue
|
108
|
-
raise if tries > 8
|
109
|
-
tries += 1
|
110
|
-
sleep 2
|
111
|
-
retry
|
112
|
-
end
|
113
|
-
data = @cols.map do |x|
|
114
|
-
y=post.__send__(x.to_sym)
|
115
|
-
y = y.to_i if x == "created_at"
|
116
|
-
y = y.join(" ") if x == "artist"
|
117
|
-
y != nil ? @db.escape_string(y.to_s) : "NULL"
|
118
|
-
end
|
119
|
-
if !@db.exec("SELECT id FROM e621.posts WHERE id = #{post.id};").first then
|
120
|
-
query = "INSERT INTO e621.posts (#{@cols.join(",")}) VALUES ('#{data.join("','")}');".gsub("'NULL'","NULL")
|
121
|
-
@db.exec(query)
|
122
|
-
@mt.synchronize do
|
123
|
-
@log.info("Added post ##{post.id.pad(6," ")} to library.")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
sync = Sync.new
|
129
|
-
posts = Thread.new do
|
130
|
-
sync.worker("post")
|
131
|
-
end
|
132
|
-
sleep 4
|
133
|
-
downloads = Array.new
|
134
|
-
10.times do
|
135
|
-
downloads << Thread.new do
|
136
|
-
loop do
|
137
|
-
sync.download
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
posts.join
|
143
|
-
downloads.each{|d|d.join}
|
data/lib/examples/sync.rb
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Copyright 2014 Maxine Red <maxine_red1@yahoo.com>
|
3
|
-
|
4
|
-
This file is part of rubyhexagon.
|
5
|
-
|
6
|
-
rubyhexagon is free software: you can redistribute it and/or modify
|
7
|
-
it under the terms of the GNU General Public License as published by
|
8
|
-
the Free Software Foundation, either version 3 of the License, or
|
9
|
-
(at your option) any later version.
|
10
|
-
|
11
|
-
rubyhexagon is distributed in the hope that it will be useful,
|
12
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU General Public License for more details.
|
15
|
-
|
16
|
-
You should have received a copy of the GNU General Public License
|
17
|
-
along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
=end
|
19
|
-
|
20
|
-
require "logger"
|
21
|
-
|
22
|
-
include E621
|
23
|
-
|
24
|
-
mod = ARGV.shift
|
25
|
-
|
26
|
-
$form = "%b %e, %Y %I:%M:%S %p"
|
27
|
-
|
28
|
-
require mod
|
29
|
-
|
30
|
-
class Sync
|
31
|
-
def initialize
|
32
|
-
E621::Config.config = File.expand_path("~/.hexagon/conf.json")
|
33
|
-
if $stdout.tty? then
|
34
|
-
@log = Logger.new($stdout)
|
35
|
-
@log.level = Logger::DEBUG
|
36
|
-
else
|
37
|
-
@log = Logger.new(File.expand_path(E621::Config.paths["logging"]))
|
38
|
-
@log.level = Logger::INFO
|
39
|
-
end
|
40
|
-
@log.formatter = proc do |sev,dat,prog,msg|
|
41
|
-
"#{Time.now.strftime($form)} [#{sev.pad(5)}] #{msg}#$/"
|
42
|
-
end
|
43
|
-
api = API.new("user") # Used for login
|
44
|
-
@log.info("Program #$0 started.")
|
45
|
-
@uid = api.get("index",{"name"=>api.user}).first["id"]
|
46
|
-
@max_wait = 1
|
47
|
-
end
|
48
|
-
|
49
|
-
def worker(mod)
|
50
|
-
@mod = mod
|
51
|
-
Dir.chdir(File.expand_path("~/Pictures/e621/#{mod}s")) do
|
52
|
-
sets = Array.new
|
53
|
-
File.open(File.expand_path(E621::Config.paths["j#{mod}s"])) do |f|
|
54
|
-
sets = f.read.parse
|
55
|
-
end
|
56
|
-
@set_files = File.expand_path(E621::Config.paths["#{mod}s"])
|
57
|
-
api = API.new(mod)
|
58
|
-
sets.each do |oset|
|
59
|
-
id = mod == "set" ? oset["id"] : oset
|
60
|
-
if mod == "set" then
|
61
|
-
set = Set.new(id)
|
62
|
-
elsif mod == "pool" then
|
63
|
-
set = Pool.new(id)
|
64
|
-
end
|
65
|
-
begin
|
66
|
-
set.name = set.name.gsub("_"," ")
|
67
|
-
rescue
|
68
|
-
@log.error("Error on #{mod} #{id}")
|
69
|
-
net = Net::HTTP.new("e621.net",443)
|
70
|
-
net.use_ssl = true
|
71
|
-
body = net.get("/#{mod}/show/#{id}").body
|
72
|
-
File.open("/tmp/e621.html","w"){|f|f.print body}
|
73
|
-
if body.match("ActiveRecord::RecordNotFound")
|
74
|
-
pools_f, pools = File.expand_path("~/.hexagon/#{mod}s.json"), Array.new
|
75
|
-
File.open(pools_f) do |f|
|
76
|
-
pools = f.read.parse
|
77
|
-
end
|
78
|
-
pools.delete(id)
|
79
|
-
File.open(pools_f,"w") do |f|
|
80
|
-
f.print pools.to_json
|
81
|
-
end
|
82
|
-
@log.info("Removed: #{mod} ##{id} doesn't exist anymore.")
|
83
|
-
puts "Removed: #{mod} ##{id} doesn't exist anymore."
|
84
|
-
end
|
85
|
-
next
|
86
|
-
end
|
87
|
-
@log.info("Fetching #{mod} \"#{set.name}\"")
|
88
|
-
set.name = "Love_Can_Be_Different" if set.name == "Love_can_be_different"
|
89
|
-
set.name = set.name.gsub("_"," ").encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "")
|
90
|
-
set.name = set.name.gsub(/[^0-9, ,_,a-z,\-]/i,"").sub(/\s+$/,"")
|
91
|
-
name = mod == "set" ? set.shortname : id.pad(5)
|
92
|
-
if !File.exists?(@set_files+"/#{name}.json") then
|
93
|
-
File.open(@set_files+"/#{name}.json","w"){|f|f.print "{\"downloads\":[],\"updated_at\":0}"}
|
94
|
-
end
|
95
|
-
File.open(@set_files+"/#{name}.json"){|f|@posts = f.read.parse}
|
96
|
-
@posts.store("updated_at",0) if !@posts.has_key?("updated_at")
|
97
|
-
@posts.store("downloads",@posts["posts"]) if @posts["posts"]
|
98
|
-
next if set.updated_at.to_i <= @posts["updated_at"].to_i
|
99
|
-
dname = mod == "pool" ? set.name : name
|
100
|
-
Dir.mkdir(dname) unless File.exist?(dname)
|
101
|
-
i = 0
|
102
|
-
set.each_post do |post|
|
103
|
-
i += 1
|
104
|
-
next if @posts["downloads"].include?(post.id)
|
105
|
-
download(post,dname,set,i)
|
106
|
-
end
|
107
|
-
advanced_set(oset,name,set) if mod == "set"
|
108
|
-
@posts["updated_at"] = set.updated_at.to_i
|
109
|
-
jposts = @posts.to_json
|
110
|
-
File.open(@set_files+"/#{name}.json","w"){|f|f.print jposts}
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def advanced_set(set,name,s)
|
116
|
-
sid, owner, query = set["id"], set["owner"], set["search"]
|
117
|
-
if owner == @uid then
|
118
|
-
Search.new("fav:maxine_red #{query} order:id".split(" ")).each_post do |post|
|
119
|
-
next if @posts["downloads"].include?(post.id)
|
120
|
-
download(post,name,s)
|
121
|
-
end
|
122
|
-
api = API.new("set")
|
123
|
-
set = api.get("show", {"id"=>sid})
|
124
|
-
posts = set["posts"].map{|post|Post.new(post).id}
|
125
|
-
name = set["shortname"]
|
126
|
-
local = Dir["#{name}/*"].reject{|x|x.match(/db$/)}.map{|x|x.split(".")[1].to_i}.sort.uniq
|
127
|
-
(posts-local).each do |id|
|
128
|
-
post = Post.new({"id"=>id})
|
129
|
-
f = post.remove_from_set(sid)
|
130
|
-
if f["success"] then
|
131
|
-
s = "Removed Post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set["name"]}\""
|
132
|
-
puts "#{Time.now.strftime($form)}: \e[1;33m#{s}\e[0m"
|
133
|
-
@log.info(s)
|
134
|
-
else
|
135
|
-
s = "#{f["reason"].to_s.gsub(/<.+?>/,"")}."
|
136
|
-
puts "#{Time.now.strftime($form)}: \e[1;31m#{s}\e[0m"
|
137
|
-
@log.info(s)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
(local-posts).each do |id|
|
141
|
-
next if id == 0
|
142
|
-
post = Post.new({"id"=>id})
|
143
|
-
f = post.add_to_set(sid)
|
144
|
-
if f["success"] then
|
145
|
-
s = "Added Post #{" "*(6-post.id.to_s.length)}#{post.id} to \"#{set["name"]}\"."
|
146
|
-
puts "#{Time.now.strftime($form)}: #{s}"
|
147
|
-
@log.info(s)
|
148
|
-
else
|
149
|
-
s = "#{f["reason"].gsub(/<.+?>/,"")}. Removing local file."
|
150
|
-
puts "#{Time.now.strftime($form)}: #{s}"
|
151
|
-
@log.info(s)
|
152
|
-
File.unlink(Dir["#{set["shortname"]}/*.#{"0"*(8-post.id.to_s.length)}#{post.id}.*"].first)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
def download(post,name,set,id=0)
|
158
|
-
artist = post.artist.first
|
159
|
-
if @mod == "set" then
|
160
|
-
string = [post.created_at.to_i,post.id.pad(8),artist+"_"+name,post.file_ext]
|
161
|
-
elsif @mod == "pool" then
|
162
|
-
string = [set.id.pad(5),id.pad(4),post.id.pad(8),artist,name.downcase.gsub(/\s/,"_"),post.file_ext]
|
163
|
-
end
|
164
|
-
string = string.join(".")
|
165
|
-
tries = 0
|
166
|
-
begin
|
167
|
-
post.download("#{name}/#{string}")
|
168
|
-
rescue
|
169
|
-
raise if tries > 4
|
170
|
-
tries += 1
|
171
|
-
puts "#{Time.now.strftime($form)}: #$!"
|
172
|
-
@log.info("#$!")
|
173
|
-
sleep 1
|
174
|
-
retry
|
175
|
-
end
|
176
|
-
File.utime(post.created_at,post.created_at,"#{name}/#{string}")
|
177
|
-
@posts["downloads"] << post.id
|
178
|
-
jposts = @posts.to_json
|
179
|
-
File.open(@set_files+"/#{name}.json","w"){|f|f.print jposts}
|
180
|
-
s = "Downloaded post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set.name}\"."
|
181
|
-
puts "#{Time.now.strftime($form)}: #{s}"
|
182
|
-
sleep(rand*@max_wait)
|
183
|
-
@log.info(s)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
sync = Sync.new
|
187
|
-
sync.worker(mod)
|