rubyhexagon 0.1.1 → 0.1.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 (3) hide show
  1. data/lib/examples/sync.rb +196 -0
  2. data/lib/rubyhexagon.rb +1 -1
  3. metadata +12 -11
@@ -0,0 +1,196 @@
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
+ $0 = "E621 #{mod.capitalize}-sync"
27
+ $form = "%b %e, %Y %I:%M:%S %p"
28
+
29
+ require mod
30
+
31
+ class Sync
32
+ def initialize
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
+ E621::Config.config = File.expand_path("~/.hexagon/conf.json")
44
+ api = API.new("user") # Used for login
45
+ @log.info("Program #$0 started.")
46
+ @uid = api.get("index",{"name"=>api.user}).first["id"]
47
+ @max_wait = 1
48
+ tags
49
+ end
50
+
51
+ def tags
52
+ tags = File.expand_path("~/.hexagon/tags.json")
53
+ if !File.exist?(tags) then
54
+ @tags = Array.new
55
+ else
56
+ File.open(tags) do |f|
57
+ @tags = f.read.parse
58
+ end
59
+ end
60
+ @tags = @tags.sort{|k1,k2|k1["id"]<=>k2["id"]}
61
+ api = API.new("tag")
62
+ body,page = [2],1
63
+ until body == Array.new do
64
+ body = api.get("index",{"limit"=>0,"order"=>"count","after_id"=>@tags.last["id"],"page"=>page})
65
+ body = body.map{|x|x["name"] = x["name"].encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "");x}
66
+ @tags += body
67
+ page += 1
68
+ end
69
+ jtags = @tags.to_json
70
+ File.open(tags,"w"){|f|f.print jtags}
71
+ @tags = @tags.reject{|x|x["type"]!=1}.map{|x|x["name"]}
72
+ end
73
+
74
+ def worker(mod)
75
+ @mod = mod
76
+ Dir.chdir(File.expand_path("~/Dropbox/Furry/e621/#{mod}s")) do
77
+ sets = Array.new
78
+ File.open(File.expand_path(E621::Config.paths["j#{mod}s"])) do |f|
79
+ sets = f.read.parse
80
+ end
81
+ @set_files = File.expand_path(E621::Config.paths["sets"])
82
+ api = API.new(mod)
83
+ sets.each do |oset|
84
+ id = mod == "set" ? oset["id"] : oset
85
+ if mod == "set" then
86
+ set = Set.new(api.get("show", {"id"=>id}))
87
+ elsif mod == "pool" then
88
+ set = Pool.new(api.get("show", {"id"=>id}))
89
+ end
90
+ set.name = set.name.gsub("_"," ")
91
+ @log.info("Fetching #{mod} \"#{set.name}\"")
92
+ set.name = "Love_Can_Be_Different" if set.name == "Love_can_be_different"
93
+ set.name = set.name.gsub("_"," ").encode("us-ascii", :invalid => :replace, :undef => :replace, :replace => "")
94
+ set.name = set.name.gsub(/[^0-9, ,_,a-z,\-]/i,"").sub(/\s+$/,"")
95
+ name = mod == "set" ? set.shortname : id.pad(5)
96
+ if !File.exists?(@set_files+"/#{name}.json") then
97
+ File.open(@set_files+"/#{name}.json","w"){|f|f.print "{\"downloads\":[],\"updated_at\":0}"}
98
+ end
99
+ File.open(@set_files+"/#{name}.json"){|f|@posts = f.read.parse}
100
+ @posts.store("updated_at",0) if !@posts.has_key?("updated_at")
101
+ next if set.updated_at.to_i <= @posts["updated_at"].to_i
102
+ dname = mod == "pool" ? set.name : name
103
+ Dir.mkdir(dname) unless File.exist?(dname)
104
+ i = 1
105
+ set.each_post do |post|
106
+ next if @posts["downloads"].include?(post.id)
107
+ download(post,dname,set,i)
108
+ i += 1
109
+ end
110
+ advanced_set(oset) if mod == "set"
111
+ end
112
+ end
113
+ @posts["updated_at"] = set.updated_at.to_i
114
+ jposts = @posts.to_json
115
+ File.open(@set_files+"/#{name}.json","w"){|f|f.print jposts}
116
+ end
117
+
118
+ def set(set)
119
+ sid, owner, query = set["id"], set["owner"], set["search"]
120
+ if owner == uid then
121
+ Search.new("fav:maxine_red #{query} order:id".split(" ")).each_post do |post|
122
+ next if @posts["downloads"].include?(post.id)
123
+ download(post,name,set)
124
+ end
125
+ set = api.get("show", {"id"=>sid})
126
+ posts = set["posts"].map{|post|Post.new(post).id}
127
+ name = set["shortname"]
128
+ local = Dir["#{name}/*"].reject{|x|x.match(/db$/)}.map{|x|x.split(".")[1].to_i}.sort.uniq
129
+ (posts-local).each do |id|
130
+ post = Post.new({"id"=>id})
131
+ f = post.remove_from_set(sid)
132
+ if f["success"] then
133
+ s = "Removed Post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set["name"]}\""
134
+ puts "#{Time.now.strftime($form)}: \e[1;33m#{s}\e[0m"
135
+ @log.info(s)
136
+ else
137
+ s = "#{f["reason"].to_s.gsub(/<.+?>/,"")}."
138
+ puts "#{Time.now.strftime($form)}: \e[1;31m#{s}\e[0m"
139
+ @log.info(s)
140
+ end
141
+ end
142
+ (local-posts).each do |id|
143
+ next if id == 0
144
+ post = Post.new({"id"=>id})
145
+ f = post.add_to_set(sid)
146
+ if f["success"] then
147
+ s = "Added Post #{" "*(6-post.id.to_s.length)}#{post.id} to \"#{set["name"]}\"."
148
+ puts "#{Time.now.strftime($form)}: #{s}"
149
+ @log.info(s)
150
+ else
151
+ s = "#{f["reason"].gsub(/<.+?>/,"")}. Removing local file."
152
+ puts "#{Time.now.strftime($form)}: #{s}"
153
+ @log.info(s)
154
+ File.unlink(Dir["#{set["shortname"]}/*.#{"0"*(8-post.id.to_s.length)}#{post.id}.*"].first)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ def download(post,name,set,id=0)
160
+ artist = post.tags.split(/\s+/).map do |t|
161
+ @tags[@tags.index(t)] if @tags.index(t)
162
+ end
163
+ begin
164
+ artist = artist.compact.first.sub("_(artist)","")
165
+ rescue
166
+ artist = "unknown"
167
+ end
168
+ if @mod == "set" then
169
+ string = [post.created_at.to_i,post.id.pad(8),artist+"_"+name,post.file_ext]
170
+ elsif @mod == "pool" then
171
+ string = [set.id.pad(5),id.pad(4),post.id.pad(8),artist,name.downcase.gsub(/\s/,"_"),post.file_ext]
172
+ end
173
+ string = string.join(".")
174
+ tries = 0
175
+ begin
176
+ post.download("#{name}/#{string}")
177
+ rescue
178
+ raise if tries > 4
179
+ tries += 1
180
+ puts "#{Time.now.strftime($form)}: #$!"
181
+ @log.info("#$!")
182
+ sleep 1
183
+ retry
184
+ end
185
+ File.utime(post.created_at,post.created_at,"#{name}/#{string}")
186
+ @posts["downloads"] << post.id
187
+ jposts = @posts.to_json
188
+ File.open(@set_files+"/#{name}.json","w"){|f|f.print jposts}
189
+ s = "Downloaded post #{" "*(6-post.id.to_s.length)}#{post.id} from \"#{set.name}\"."
190
+ puts "#{Time.now.strftime($form)}: #{s}"
191
+ sleep(rand*@max_wait)
192
+ @log.info(s)
193
+ end
194
+ end
195
+ sync = Sync.new
196
+ sync.worker(mod)
data/lib/rubyhexagon.rb CHANGED
@@ -30,5 +30,5 @@ require "pool"
30
30
 
31
31
  module E621
32
32
  Name = "rubyhexagon"
33
- Version = "0.1.1"
33
+ Version = "0.1.2"
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.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -18,21 +18,22 @@ executables:
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - lib/examples/add.rb
22
+ - lib/examples/sync.rb
21
23
  - lib/config.rb
22
- - lib/set.rb
23
- - lib/standard/error.rb
24
- - lib/standard/http.rb
24
+ - lib/post.rb
25
+ - lib/rubyhexagon.rb
26
+ - lib/pool.rb
27
+ - lib/container.rb
25
28
  - lib/standard/string.rb
26
- - lib/standard/time.rb
29
+ - lib/standard/http.rb
30
+ - lib/standard/error.rb
27
31
  - lib/standard/int.rb
28
32
  - lib/standard/hash.rb
29
- - lib/api.rb
30
- - lib/rubyhexagon.rb
31
- - lib/pool.rb
33
+ - lib/standard/time.rb
32
34
  - lib/search.rb
33
- - lib/container.rb
34
- - lib/post.rb
35
- - lib/examples/add.rb
35
+ - lib/set.rb
36
+ - lib/api.rb
36
37
  - bin/e621
37
38
  homepage: https://github.com/maxine-red/rubyhexagon
38
39
  licenses: