stashboxr 0.1.0

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.
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "stashboxr"
8
+ gem.summary = %Q{A ruby api for the stashbox.org website}
9
+ gem.description = %Q{Upload files to stashbox.org and manage their metadata. User accounts or anonymous uploads!}
10
+ gem.email = "jphastings@gmail.com"
11
+ gem.homepage = "http://github.com/jphastings/StashboxR"
12
+ gem.authors = ["JP Hastings-Spital"]
13
+ gem.add_dependency "mechanize",'>= 1.0.0'
14
+ gem.add_development_dependency "Shoulda"
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/stashboxr.rb ADDED
@@ -0,0 +1,253 @@
1
+ require 'rubygems'
2
+ require 'mechanize'
3
+
4
+ # Allows percentages to be inspected and stringified in human
5
+ # form "33.3%", but kept in a float format for mathmatics
6
+ class Percentage < DelegateClass(Float)
7
+ def to_s(decimalplaces = 0)
8
+ (((self * 10**(decimalplaces+2)).round)/10**decimalplaces).to_s+"%"
9
+ end
10
+ alias :inspect :to_s
11
+ end
12
+
13
+ # A library for dealing with files on http://stashbox.org
14
+ class Stashboxr
15
+ # Settings for the browser emulation
16
+ Agent = Mechanize.new { |agent| agent.user_agent = 'Stashboxr' }
17
+
18
+ # Log into stashbox
19
+ def self.login(username,password)
20
+ res = Agent.post('http://stashbox.org/',{
21
+ :dologin => 1,
22
+ :user => username,
23
+ :password => password
24
+ })
25
+
26
+ raise RuntimeError, "Log in failed" if res.code != "200"
27
+ @@username = username
28
+ end
29
+
30
+ # Log out of stashbox
31
+ def self.logout
32
+ Agent.get('http://stashbox.org/logout.php')
33
+ @@username = nil
34
+ true
35
+ end
36
+
37
+ # Is someone logged in?
38
+ def self.loggedin?
39
+ !@@username.nil?
40
+ end
41
+
42
+ # Username of current logged in user (nil if not logged in)
43
+ def self.username
44
+ @@username
45
+ end
46
+
47
+ # Search stashbox.org - the site has this advice for formatting searches:
48
+ #
49
+ # You can use any number of terms in your search, all of which will be required in the results. You can also use the following search types (using "type:*the_type*" format): archives, audio, code, documents, images, movies
50
+ #
51
+ # Search types can be combined with normal search keywords to refine your results.
52
+ #
53
+ # In addition, remember you can search for both full and partial mimetypes, ie _application/pdf_.
54
+ def self.search(q)
55
+ res = Nokogiri::XML(Agent.get("http://stashbox.org/browse.php?wants_rss=1&q=#{URI.encode(q)}").body)
56
+
57
+ res.search('//item').collect do |item|
58
+ File.new(item.search('link').inner_text)
59
+ end
60
+ end
61
+
62
+ class File
63
+ attr_reader :filename, :url, :unsaved
64
+ attr_reader :know_code, :uploaded_on, :size, :views, :rating
65
+ attr_accessor :title, :description
66
+ attr_accessor :autosave
67
+
68
+ SIZES = {
69
+ '' => 9.765625e-4,
70
+ 'K' => 1,
71
+ 'M' => 1024
72
+ }
73
+
74
+ # Upload a file to stashbox and return a Stashbox::File object referencing it (which can be used to edit the metadata)
75
+ def self.upload(local_file,is_public = true)
76
+ # Does file exist?
77
+ raise RuntimeError, "This file does not exist - I can't upload it!" if !::File.exists? local_file
78
+ # Upload the file
79
+ res = Agent.post('http://stashbox.org/upload.php',{
80
+ :upload_type => "local_file",
81
+ :wants_rss => 1,
82
+ :file => open(local_file),
83
+ :is_public => is_public
84
+ })
85
+ body = Nokogiri::XML(res.body)
86
+
87
+ case res.code.to_i
88
+ when 200
89
+ new(body.search('//url').inner_text)
90
+ else
91
+ reason = body.search('//error').inner_text rescue nil
92
+ raise RuntimeError, "The upload wasn't allowed"<<((reason.nil?) ? "" : " because '#{reason}'")
93
+ end
94
+ end
95
+
96
+ def initialize(url)
97
+ if (url =~ /(?:http:\/\/)?(?:stashbox\.org)?(?:\/v)?\/?([0-9]+\/(.+))$/)
98
+ @stashboxid = $1
99
+ @filename = $2
100
+ else
101
+ raise RuntimeError, "That isn't a valid stashbox URL"
102
+ end
103
+
104
+ @autosave = true
105
+ @saved = true
106
+ end
107
+
108
+ # Has metadata been loaded
109
+ def has_metadata?; @metadata; end
110
+ # If you make alterations to the file's metadata with autosave turned off, this will become true until to #save it.
111
+ def autosave=(pref); @autosave = (pref != false); end
112
+ # Returns true if there are unsaved changes to the metadata for the file
113
+ def unsaved?; !@saved; end
114
+ def url; "http://stashbox.org/#{@stashboxid}"; end
115
+ def tags; refresh if not @metadata; @tags; end
116
+ def title; refresh if not @metadata; @title; end
117
+ def description; refresh if not @metadata; @description; end
118
+ def uploaded_on; refresh if not @metadata; @uploaded_on; end
119
+ def size; refresh if not @metadata; @size; end
120
+ def views; refresh if not @metadata; @views; end
121
+ def rating; refresh if not @metadata; @rating; end
122
+ def sfw?; refresh if not @metadata; @sfw; end
123
+ def public?; refresh if not @metadata; @public; end
124
+
125
+ # Add tags to the file on stashbox
126
+ def add_tag(new_tags)
127
+ # TODO: Parse input tags?
128
+ @tags = (tags + parse_tags(new_tags)).uniq
129
+ @saved = false
130
+ save if @autosave
131
+ end
132
+ alias :add_tags :add_tag
133
+
134
+ # Remove tags from the file on stashbox
135
+ def remove_tag(new_tags)
136
+ @tags = (tags - parse_tags(new_tags)).uniq
137
+ @saved = false
138
+ save if @autosave
139
+ end
140
+ alias :remove_tags :remove_tag
141
+
142
+ # Reset the tags for this file to the ones in the given array
143
+ def set_tags(new_tags)
144
+ @tags = parse_tags(new_tags)
145
+ @saved = false
146
+ save if @autosave
147
+ end
148
+
149
+ def title=(title)
150
+ @title = title
151
+ @saved = false
152
+ save if @autosave
153
+ end
154
+
155
+ def description=(description)
156
+ @description = description
157
+ @saved = false
158
+ save if @autosave
159
+ end
160
+
161
+ def sfw=(sfw)
162
+ @sfw = (sfw == true)
163
+ @saved = false
164
+ save if @autosave
165
+ end
166
+
167
+ def public=(ispublic)
168
+ @public = (ispublic == true)
169
+ @saved = false
170
+ save if @autosave
171
+ end
172
+
173
+ # Save the metadata to Stashboxr. Called automatically with any changes by default.
174
+ def save
175
+ res = Agent.post("http://stashbox.org/manage_file/"<<@stashboxid,{
176
+ :tags => @tags * " ",
177
+ :meta_title => @title,
178
+ :meta_description => @details,
179
+ :is_nsfw => !@sfw,
180
+ :is_public => @public
181
+ })
182
+
183
+ raise RuntimeError, "You don't have permission to edit this file" if res.body =~ /don't have permission/
184
+
185
+ return res.code == "200"
186
+ end
187
+
188
+ # Delete this file (permanently!) from stashbox.org
189
+ def delete
190
+ res = Agent.post("http://stashbox.org/delete_upload/"<<@stashboxid)
191
+
192
+ raise RuntimeError, "You don't have permission to delete this file" if res.body =~ /don't have permission/
193
+
194
+ return res.code == "200"
195
+ end
196
+
197
+ def inspect
198
+ keys = [@public ? "public" : "private"]
199
+ keys.push("nsfw") if !@sfw and @metadata
200
+ "<Stash: #{@filename} (#{keys * ", "})>"
201
+ end
202
+
203
+ # Grab metadata from stashbox.org
204
+ def refresh
205
+ # Get extended information
206
+ doc = Agent.get "http://stashbox.org/v/"<<@stashboxid
207
+
208
+ doc.search("//div[@class='subsection']").each do |sub|
209
+ value = sub.search("div[@class='value']").inner_text.strip
210
+ case sub.search("div[@class='label']").inner_text
211
+ when "Size"
212
+ @size = value[/^(\d+\.\d+)\ ([K|M]?)B$/,1].to_f * SIZES[$2]
213
+ when "Uploaded On"
214
+ @uploaded_on = Time.parse(value)
215
+ when "Views"
216
+ @size = value[/^(\d+)\ \(/,1].to_i
217
+ when "Rating"
218
+ @rating = Percentage.new(value[/(\d+\.\d+)\/5\ $/,1].to_f/5.0)
219
+ when "Tags"
220
+ @tags = sub.search("div[@class='value']/a").collect do |tag|
221
+ tag.inner_text
222
+ end
223
+ when "Title"
224
+ if sub.search("div[@class='value']/i").inner_text == ""
225
+ @title = value
226
+ else
227
+ @title = nil
228
+ end
229
+ when "KnowCode"
230
+ @know_code = value
231
+ when "Description"
232
+ if sub.search("div[@class='value']/i").inner_text == ""
233
+ @description = value
234
+ else
235
+ @description = nil
236
+ end
237
+ when "Is this file work safe?"
238
+ @sfw = (value == "Yes")
239
+ end
240
+ end
241
+ @metadata = true
242
+ return
243
+ end
244
+
245
+ private
246
+ def parse_tags(new_tags)
247
+ [new_tags].flatten.collect do |tag|
248
+ tag.downcase.gsub(/[^a-z0-9_-]/,"")
249
+ tag = nil if tag.empty?
250
+ end.compact.uniq
251
+ end
252
+ end
253
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'dmap'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,6 @@
1
+ require 'helper'
2
+
3
+ # TODO: Complete Tests!
4
+ class TestStashboxr < Test::Unit::TestCase
5
+
6
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stashboxr
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - JP Hastings-Spital
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-08 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mechanize
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: Shoulda
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: Upload files to stashbox.org and manage their metadata. User accounts or anonymous uploads!
52
+ email: jphastings@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - Rakefile
61
+ - VERSION
62
+ - lib/stashboxr.rb
63
+ - test/helper.rb
64
+ - test/test_stashboxr.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/jphastings/StashboxR
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --charset=UTF-8
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirements: []
93
+
94
+ rubyforge_project:
95
+ rubygems_version: 1.3.7
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: A ruby api for the stashbox.org website
99
+ test_files:
100
+ - test/helper.rb
101
+ - test/test_stashboxr.rb