rubyhexagon 0.0.5 → 0.0.6

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 (4) hide show
  1. data/bin/set-sync +184 -148
  2. data/lib/examples/add.rb +57 -0
  3. data/lib/rubyhexagon.rb +1 -1
  4. metadata +3 -2
data/bin/set-sync CHANGED
@@ -26,6 +26,8 @@ require "logger"
26
26
 
27
27
  include E621
28
28
 
29
+ $0 = "E621 Set-sync"
30
+ $form = "%b %e, %Y %I:%M:%S %p"
29
31
 
30
32
  def download(post,name,set)
31
33
  artist = post.tags.split(/\s+/).map do |t|
@@ -38,12 +40,16 @@ def download(post,name,set)
38
40
  end
39
41
  string = [post.created_at.to_i,post.id.pad(8),artist+"_"+name,post.file_ext]
40
42
  string = string.join(".")
43
+ tries = 0
41
44
  begin
42
45
  api = API.new("post")
43
46
  post = Post.new(api.post("show",{"id"=>post.id}))
44
47
  post.download("#{name}/#{string}")
45
48
  rescue
46
- puts $!
49
+ raise if tries > 4
50
+ tries += 1
51
+ puts "#{Time.now.strftime($form)}: #$!"
52
+ @log.info("#$!")
47
53
  sleep 1
48
54
  retry
49
55
  end
@@ -53,173 +59,203 @@ def download(post,name,set)
53
59
  set_files = File.expand_path("~/.hexagon/sets")
54
60
  File.open(set_files+"/#{name}.json","w"){|f|f.print jposts}
55
61
  s = "Downloaded post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set["name"]}\"."
56
- puts s
62
+ puts "#{Time.now.strftime($form)}: #{s}"
57
63
  @log.info(s)
58
64
  end
59
- max_wait = 2.5
60
- E621::Config.config = File.expand_path("~/.hexagon/conf.json")
61
- api = API.new("user")
62
- @log = Logger.new(File.expand_path(E621::Config.paths["logging"]))
63
- @log.formatter = proc do |sev,dat,prog,msg|
64
- "#{Time.now.strftime("%b %e, %Y %I:%M:%S %p")} [#{sev.pad(5)}] #{msg}#$/"
65
- end
66
- @log.level = Logger::INFO
67
- @log.info("Program #$0 started.")
68
- uid = api.get("index",{"name"=>api.user}).first["id"]
69
- tags = File.expand_path("~/.hexagon/tags.json")
70
- if !File.exist?(tags) then
71
- @tags = Array.new
72
- else
73
- File.open(tags) do |f|
74
- @tags = f.read.parse
65
+ begin
66
+ run,running = (File.expand_path("~/.hexagon/sets.run")),false
67
+ if File.exist?(run) then
68
+ running = true
69
+ else
70
+ File.open(run,"w"){|f|f.print $$}
75
71
  end
76
- end
77
- @tags = @tags.sort{|k1,k2|k1["id"]<=>k2["id"]}
78
- net = Net::HTTP.new("e621.net",443)
79
- net.use_ssl = true
80
- body,page = [2],1
81
- until body == Array.new do
82
- body = net.get("/tag/index.json?limit=0&order=count&after_id=#{@tags.last["id"]}&page=#{page}").body.parse
83
- body = body.map{|x|x["name"] = x["name"].encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "");x}
84
- @tags += body
85
- page += 1
86
- end
87
- jtags = @tags.to_json
88
- File.open(tags,"w"){|f|f.print jtags}
89
- @tags = @tags.reject{|x|x["type"]!=1}.map{|x|x["name"]}
90
- Dir.chdir(File.expand_path("~/Dropbox/Furry/e621/sets")) do
91
- sets = Array.new
92
- File.open(File.expand_path("~/.hexagon/sets.json")) do |f|
93
- sets = f.read.parse
72
+ max_wait = 2.5
73
+ E621::Config.config = File.expand_path("~/.hexagon/conf.json")
74
+ api = API.new("user")
75
+ if $stdout.tty? then
76
+ @log = Logger.new($stdout)
77
+ @log.level = Logger::DEBUG
78
+ else
79
+ @log = Logger.new(File.expand_path(E621::Config.paths["logging"]))
80
+ @log.level = Logger::INFO
94
81
  end
95
- sets = sets.sort{|s1,s2|s1["id"]<=>s2["id"]}
96
- set_files = File.expand_path("~/.hexagon/sets")
97
- api = API.new("set")
98
- sets.each do |set|
99
- sid, owner, query = set["id"], set["owner"], set["search"]
100
- set = api.get("show", {"id"=>sid})
101
- posts = set["posts"].map{|post|Post.new(post)}
102
- name = set["shortname"]
103
- @log.info("Fetching set #{set["name"]}")
104
- if !File.exists?(set_files+"/#{name}.json") then
105
- File.open(set_files+"/#{name}.json","w"){|f|f.print "{\"downloads\":[]}"}
106
- end
107
- File.open(set_files+"/#{name}.json"){|f|@posts = f.read.parse}
108
- Dir.mkdir(name) unless File.exist?(name)
109
- posts.each do |post|
110
- next if @posts["downloads"].include?(post.id)
111
- download(post,name,set)
112
- end
113
- next if owner != uid
114
- Search.new("fav:maxine_red #{query} order:id".split(" ")).each_post do |post|
115
- next if @posts["downloads"].include?(post.id)
116
- download(post,name,set)
117
- sleep(rand*max_wait)
82
+ @log.formatter = proc do |sev,dat,prog,msg|
83
+ "#{Time.now.strftime("%b %e, %Y %I:%M:%S %p")} [#{sev.pad(5)}] #{msg}#$/"
84
+ end
85
+ @log.info("Program #$0 started.")
86
+ uid = api.get("index",{"name"=>api.user}).first["id"]
87
+ tags = File.expand_path("~/.hexagon/tags.json")
88
+ if !File.exist?(tags) then
89
+ @tags = Array.new
90
+ else
91
+ File.open(tags) do |f|
92
+ @tags = f.read.parse
118
93
  end
119
94
  end
120
- sets.each do |set|
121
- sid, owner, query = set["id"], set["owner"], set["search"]
122
- next if owner != uid
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 "\e[1;33m#{s}\e[0m"
133
- @log.info(s)
134
- else
135
- s = "#{f["reason"].to_s.gsub(/<.+?>/,"")}."
136
- puts "\e[1;31m#{s}\e[0m"
137
- @log.info(s)
95
+ @tags = @tags.sort{|k1,k2|k1["id"]<=>k2["id"]}
96
+ net = Net::HTTP.new("e621.net",443)
97
+ net.use_ssl = true
98
+ body,page = [2],1
99
+ until body == Array.new do
100
+ body = net.get("/tag/index.json?limit=0&order=count&after_id=#{@tags.last["id"]}&page=#{page}").body.parse
101
+ body = body.map{|x|x["name"] = x["name"].encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "");x}
102
+ @tags += body
103
+ page += 1
104
+ end
105
+ jtags = @tags.to_json
106
+ File.open(tags,"w"){|f|f.print jtags}
107
+ @tags = @tags.reject{|x|x["type"]!=1}.map{|x|x["name"]}
108
+ Dir.chdir(File.expand_path("~/Dropbox/Furry/e621/sets")) do
109
+ sets = Array.new
110
+ File.open(File.expand_path("~/.hexagon/sets.json")) do |f|
111
+ sets = f.read.parse
112
+ end
113
+ sets = sets.sort{|s1,s2|s1["id"]<=>s2["id"]}
114
+ set_files = File.expand_path("~/.hexagon/sets")
115
+ api = API.new("set")
116
+ sets.each do |set|
117
+ sid, owner, query = set["id"], set["owner"], set["search"]
118
+ set = api.get("show", {"id"=>sid})
119
+ @log.info("Fetching set #{set["name"]}")
120
+ posts = set["posts"].map{|post|Post.new(post)}
121
+ name = set["shortname"]
122
+ if !File.exists?(set_files+"/#{name}.json") then
123
+ File.open(set_files+"/#{name}.json","w"){|f|f.print "{\"downloads\":[]}"}
124
+ end
125
+ File.open(set_files+"/#{name}.json"){|f|@posts = f.read.parse}
126
+ Dir.mkdir(name) unless File.exist?(name)
127
+ posts.each do |post|
128
+ next if @posts["downloads"].include?(post.id)
129
+ download(post,name,set)
130
+ end
131
+ next if owner != uid
132
+ Search.new("fav:maxine_red #{query} order:id".split(" ")).each_post do |post|
133
+ next if @posts["downloads"].include?(post.id)
134
+ download(post,name,set)
135
+ sleep(rand*max_wait)
138
136
  end
139
- sleep(rand*max_wait)
140
137
  end
141
- (local-posts).each do |id|
142
- next if id == 0
143
- post = Post.new({"id"=>id})
144
- f = post.add_to_set(sid)
145
- if f["success"] then
146
- s = "Added Post #{" "*(6-post.id.to_s.length)}#{post.id} to \"#{set["name"]}\"."
147
- puts s
148
- @log.info(s)
149
- else
150
- s = "#{f["reason"].gsub(/<.+?>/,"")}. Removing local file."
151
- puts s
152
- @log.info(s)
153
- File.unlink(Dir["#{set["shortname"]}/*.#{"0"*(8-post.id.to_s.length)}#{post.id}.*"].first)
138
+ sets.each do |set|
139
+ sid, owner, query = set["id"], set["owner"], set["search"]
140
+ next if owner != uid
141
+ set = api.get("show", {"id"=>sid})
142
+ posts = set["posts"].map{|post|Post.new(post).id}
143
+ name = set["shortname"]
144
+ local = Dir["#{name}/*"].reject{|x|x.match(/db$/)}.map{|x|x.split(".")[1].to_i}.sort.uniq
145
+ (posts-local).each do |id|
146
+ post = Post.new({"id"=>id})
147
+ f = post.remove_from_set(sid)
148
+ if f["success"] then
149
+ s = "Removed Post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set["name"]}\""
150
+ puts "#{Time.now.strftime($form)}: \e[1;33m#{s}\e[0m"
151
+ @log.info(s)
152
+ else
153
+ s = "#{f["reason"].to_s.gsub(/<.+?>/,"")}."
154
+ puts "#{Time.now.strftime($form)}: \e[1;31m#{s}\e[0m"
155
+ @log.info(s)
156
+ end
157
+ sleep(rand*max_wait)
158
+ end
159
+ (local-posts).each do |id|
160
+ next if id == 0
161
+ post = Post.new({"id"=>id})
162
+ f = post.add_to_set(sid)
163
+ if f["success"] then
164
+ s = "Added Post #{" "*(6-post.id.to_s.length)}#{post.id} to \"#{set["name"]}\"."
165
+ puts "#{Time.now.strftime($form)}: #{s}"
166
+ @log.info(s)
167
+ else
168
+ s = "#{f["reason"].gsub(/<.+?>/,"")}. Removing local file."
169
+ puts "#{Time.now.strftime($form)}: #{s}"
170
+ @log.info(s)
171
+ File.unlink(Dir["#{set["shortname"]}/*.#{"0"*(8-post.id.to_s.length)}#{post.id}.*"].first)
172
+ end
173
+ sleep(rand*max_wait)
154
174
  end
155
- sleep(rand*max_wait)
156
175
  end
157
176
  end
158
- end
159
- Dir.chdir(File.expand_path("~/Dropbox/Furry/e621/pools")) do
160
- pools = Array.new
161
- File.open(File.expand_path("~/.hexagon/pools.json")) do |f|
162
- pools = f.read.parse.sort.uniq
163
- end
164
- pool_files = File.expand_path("~/.hexagon/pools")
165
- api = API.new("pool")
166
- pools.each do |pool|
167
- spool = {"updated_at"=>0, "posts"=>[]}
168
- npool = api.get("show",{"id"=>pool})
169
- pool = Pool.new(npool)
170
- begin
171
- pfile = pool_files+"/#{pool.id.pad(5)}.json"
172
- rescue
173
- @log.error("Error occured: #{npool.inspect}")
174
- raise
175
- end
176
- if !File.exists?(pfile) then
177
- File.open(pfile,"w"){|f|f.print spool.to_json}
178
- spool = Pool.new(spool)
179
- else
180
- File.open(pfile){|f|spool = Pool.new(f.read.parse)}
181
- end
182
- posts = Array.new
183
- next if pool.updated_at.to_i <= spool.updated_at.to_i
184
- (pool.post_count/24.0).ceil.times do |page|
185
- posts += pool.posts.map{|post|Post.new(post)}
186
- pool = Pool.new(api.get("show",{"id"=>pool.id,"page"=>page+2}))
177
+ Dir.chdir(File.expand_path("~/Dropbox/Furry/e621/pools")) do
178
+ pools = Array.new
179
+ File.open(File.expand_path("~/.hexagon/pools.json")) do |f|
180
+ pools = f.read.parse.sort.uniq
187
181
  end
188
- pool.name = pool.name.gsub("_"," ").encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "")
189
- name = pool.name.gsub(/[^0-9, ,_,a-z,\-]/i,"").sub(/\s+$/,"")
190
- Dir.mkdir(name) unless File.exist?(name)
191
- @log.info("Fetching pool #{pool.name}")
192
- posts.each_with_index do |post,id|
193
- id = id.succ
194
- next if spool.posts.include?(post.id)
195
- artist = post.tags.split(/\s+/).map do |t|
196
- @tags[@tags.index(t)] if @tags.index(t)
197
- end
182
+ pool_files = File.expand_path("~/.hexagon/pools")
183
+ api = API.new("pool")
184
+ pools = pools-(1..600).to_a
185
+ pools.each do |id|
186
+ spool = {"updated_at"=>0, "posts"=>[]}
187
+ npool = api.get("show",{"id"=>id})
198
188
  begin
199
- artist = artist.compact.first.sub("_(artist)","")
189
+ pool = Pool.new(npool)
190
+ @log.debug("Fetched pool \"#{pool.name.gsub("_"," ")}\"")
200
191
  rescue
201
- artist = "unknown"
192
+ #$stderr.puts "#{pool.inspect}"
193
+ puts "#{Time.now.strftime($form)}: #{id} raised an error!"
194
+ @log.debug("Pool object: #{pool.inspect}")
195
+ next
202
196
  end
203
- string = [pool.id.pad(5),id.pad(4),post.id.pad(8),artist,name.downcase.gsub(/\s/,"_"),post.file_ext]
204
- string = string.join(".")
205
197
  begin
206
- post.download("#{name}/#{string}")
198
+ pfile = pool_files+"/#{pool.id.pad(5)}.json"
207
199
  rescue
208
- puts $!
209
- sleep 1
210
- retry
200
+ @log.error("Error occured: #{npool.inspect}")
201
+ raise
202
+ end
203
+ if !File.exists?(pfile) then
204
+ File.open(pfile,"w"){|f|f.print spool.to_json}
205
+ spool = Pool.new(spool)
206
+ else
207
+ File.open(pfile){|f|spool = Pool.new(f.read.parse)}
208
+ end
209
+ posts = Array.new
210
+ @log.debug("Skipping pool \"#{pool.name.gsub("_"," ")}\" (#{pool.id.pad(4)})")
211
+ next if pool.updated_at.to_i <= spool.updated_at.to_i
212
+ (pool.post_count/24.0).ceil.times do |page|
213
+ posts += pool.posts.map{|post|Post.new(post)}
214
+ pool = Pool.new(api.get("show",{"id"=>pool.id,"page"=>page+2}))
215
+ end
216
+ pool.name = "Love_Can_Be_Different" if pool.name == "Love_can_be_different"
217
+ pool.name = pool.name.gsub("_"," ").encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "")
218
+ name = pool.name.gsub(/[^0-9, ,_,a-z,\-]/i,"").sub(/\s+$/,"")
219
+ Dir.mkdir(name) unless File.exist?(name)
220
+ @log.info("Fetching pool #{pool.name}")
221
+ posts.each_with_index do |post,id|
222
+ id = id.succ
223
+ next if spool.posts.include?(post.id)
224
+ artist = post.tags.split(/\s+/).map do |t|
225
+ @tags[@tags.index(t)] if @tags.index(t)
226
+ end
227
+ begin
228
+ artist = artist.compact.first.sub("_(artist)","")
229
+ rescue
230
+ artist = "unknown"
231
+ end
232
+ string = [pool.id.pad(5),id.pad(4),post.id.pad(8),artist,name.downcase.gsub(/\s/,"_"),post.file_ext]
233
+ string = string.join(".")
234
+ tries = 0
235
+ begin
236
+ post.download("#{name}/#{string}")
237
+ rescue
238
+ raise if tries > 4
239
+ tries += 1
240
+ puts "#{Time.now.strftime($form)}: #$!"
241
+ @log.info("#$!")
242
+ sleep 1
243
+ retry
244
+ end
245
+ File.utime(post.created_at,post.created_at,"#{name}/#{string}")
246
+ spool.posts << post.id
247
+ jposts = spool.to_json
248
+ File.open(pfile,"w"){|f|f.print jposts}
249
+ s = "Downloaded post #{post.id.pad(6," ")} (#{id.pad(posts.length.to_s.length," ")}/#{posts.length}) from \"#{pool.name}\"."
250
+ puts "#{Time.now.strftime($form)}: #{s}"
251
+ @log.info(s)
252
+ sleep(rand*max_wait)
211
253
  end
212
- File.utime(post.created_at,post.created_at,"#{name}/#{string}")
213
- spool.posts << post.id
254
+ spool.updated_at = pool.updated_at
214
255
  jposts = spool.to_json
215
256
  File.open(pfile,"w"){|f|f.print jposts}
216
- s = "Downloaded post #{post.id.pad(6," ")} (#{id.pad(posts.length.to_s.length," ")}/#{posts.length}) from \"#{pool.name}\"."
217
- puts s
218
- @log.info(s)
219
- sleep(rand*max_wait)
220
257
  end
221
- spool.updated_at = pool.updated_at
222
- jposts = spool.to_json
223
- File.open(pfile,"w"){|f|f.print jposts}
224
258
  end
259
+ ensure
260
+ File.unlink(run) unless running
225
261
  end
@@ -0,0 +1,57 @@
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(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(E621::Config.paths["j#{mod}s"]) do |f|
55
+ f.print pools
56
+ end
57
+ end
data/lib/rubyhexagon.rb CHANGED
@@ -30,5 +30,5 @@ require "pool"
30
30
 
31
31
  module E621
32
32
  Name = "rubyhexagon"
33
- Version = "0.0.5"
33
+ Version = "0.0.6"
34
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyhexagon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-15 00:00:00.000000000 Z
12
+ date: 2015-03-01 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Rubyhexagon provides Ruby bindings for the e621 [dot] net API.
15
15
  email: maxine_red1@yahoo.com
@@ -22,6 +22,7 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
  files:
24
24
  - lib/pool.rb
25
+ - lib/examples/add.rb
25
26
  - lib/rubyhexagon.rb
26
27
  - lib/standard/hash.rb
27
28
  - lib/standard/http.rb