rubyhexagon 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: