cameraplus 0.0.1

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 (45) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +55 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +22 -0
  5. data/README.md +227 -0
  6. data/Rakefile +2 -0
  7. data/cameraplus.gemspec +25 -0
  8. data/lib/cameraplus.rb +18 -0
  9. data/lib/cameraplus/api/page.rb +17 -0
  10. data/lib/cameraplus/api/request.rb +45 -0
  11. data/lib/cameraplus/api/search.rb +25 -0
  12. data/lib/cameraplus/api/user.rb +17 -0
  13. data/lib/cameraplus/comment.rb +14 -0
  14. data/lib/cameraplus/exceptions.rb +7 -0
  15. data/lib/cameraplus/page.rb +34 -0
  16. data/lib/cameraplus/page_metadata.rb +73 -0
  17. data/lib/cameraplus/photo.rb +49 -0
  18. data/lib/cameraplus/photo_exif.rb +13 -0
  19. data/lib/cameraplus/photo_recipe.rb +12 -0
  20. data/lib/cameraplus/search.rb +45 -0
  21. data/lib/cameraplus/user.rb +72 -0
  22. data/lib/cameraplus/version.rb +3 -0
  23. data/lib/core_ext/hash.rb +13 -0
  24. data/spec/cameraplus/api/page_spec.rb +17 -0
  25. data/spec/cameraplus/api/request_spec.rb +47 -0
  26. data/spec/cameraplus/api/search_spec.rb +37 -0
  27. data/spec/cameraplus/api/user_spec.rb +17 -0
  28. data/spec/cameraplus/comment_spec.rb +32 -0
  29. data/spec/cameraplus/page_metadata_spec.rb +117 -0
  30. data/spec/cameraplus/page_spec.rb +84 -0
  31. data/spec/cameraplus/photo_exif_spec.rb +23 -0
  32. data/spec/cameraplus/photo_recipe_spec.rb +19 -0
  33. data/spec/cameraplus/photo_spec.rb +82 -0
  34. data/spec/cameraplus/search_spec.rb +51 -0
  35. data/spec/cameraplus/user_spec.rb +82 -0
  36. data/spec/core_ext/hash_spec.rb +53 -0
  37. data/spec/spec_helper.rb +6 -0
  38. data/spec/vcr_cassettes/api_request_invalid.yml +56 -0
  39. data/spec/vcr_cassettes/api_request_valid.yml +78 -0
  40. data/spec/vcr_cassettes/more_results.yml +369 -0
  41. data/spec/vcr_cassettes/page.yml +58 -0
  42. data/spec/vcr_cassettes/search.yml +55 -0
  43. data/spec/vcr_cassettes/user.yml +78 -0
  44. data/spec/vcr_config.rb +7 -0
  45. metadata +177 -0
@@ -0,0 +1,17 @@
1
+ module Cameraplus
2
+ module API
3
+ class User
4
+
5
+ def self.find(identifier, options = {})
6
+ Request.call uri(identifier), options
7
+ end
8
+
9
+ private
10
+
11
+ def self.uri(identifier)
12
+ "/user/#{identifier}:pages"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Cameraplus
2
+ class Comment
3
+
4
+ attr_reader :author, :avatar, :url, :text
5
+
6
+ def initialize(data)
7
+ @author = data.author
8
+ @avatar = data.avatar
9
+ @url = data.url
10
+ @text = data.text
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Cameraplus
2
+ class InvalidArgumentError < StandardError
3
+ end
4
+
5
+ class InvalidResponseError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Cameraplus
2
+ class Page
3
+
4
+ attr_reader :url, :created_at, :location, :location_name, :tweet_text, :tweet_id, :view_count, :comment_count, :photos
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ parse
9
+ end
10
+
11
+ private
12
+
13
+ def parse
14
+ parse_page
15
+ parse_photos
16
+ end
17
+
18
+ def parse_page
19
+ @url = @data.url
20
+ @created_at = DateTime.parse @data.timestamp
21
+ @location = @data.location
22
+ @location_name = @data.locationname
23
+ @tweet_text = @data.tweettext
24
+ @tweet_id = @data.tweetid.to_i
25
+ @view_count = @data.views
26
+ @comment_count = @data.comments.to_i
27
+ end
28
+
29
+ def parse_photos
30
+ @photos ||= @data.images.map { |image| Photo.new image }
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,73 @@
1
+ module Cameraplus
2
+ class PageMetadata
3
+
4
+ attr_reader :url, :created_at, :location, :location_name, :tweet_text, :tweet_id, :view_count, :comment_count, :user, :photos, :comments
5
+
6
+ def self.find(identifier, options = {})
7
+ new Cameraplus::API::Page.find(identifier, options), identifier
8
+ end
9
+
10
+ def initialize(data, identifier)
11
+ @data = data
12
+ @identifier = identifier
13
+ parse
14
+ end
15
+
16
+ private
17
+
18
+ def parse
19
+ parse_metadata
20
+ parse_user
21
+ parse_photos
22
+ parse_comments
23
+ end
24
+
25
+ def parse_metadata
26
+ @url = parsed_url
27
+ @created_at = parsed_created_at
28
+ @location = parsed_location
29
+ @location_name = parsed_location_name
30
+ @tweet_text = @data.page.tweet.text
31
+ @tweet_id = @data.page.tweet.id.to_i
32
+ @view_count = @data.page.views
33
+ @comment_count = @data.page.comments.to_i
34
+ end
35
+
36
+ def parse_user
37
+ @user ||= Cameraplus::User.new user: @data.page.tweet
38
+ end
39
+
40
+ def parse_photos
41
+ @photos ||= @data.pictures.map { |photo| Photo.new photo }
42
+ end
43
+
44
+ def parse_comments
45
+ @comments ||= @data.comments.map { |comment| Comment.new comment }
46
+ end
47
+
48
+ def parsed_url
49
+ "#{Cameraplus::API::Request.base_uri}/#{@identifier}"
50
+ end
51
+
52
+ def parsed_created_at
53
+ DateTime.parse @data.page.timestamp if has_timestamp?
54
+ end
55
+
56
+ def parsed_location
57
+ @data.page.location.coords if has_location?
58
+ end
59
+
60
+ def parsed_location_name
61
+ @data.page.location.name if has_location?
62
+ end
63
+
64
+ def has_timestamp?
65
+ @data.page.has_key? "timestamp"
66
+ end
67
+
68
+ def has_location?
69
+ @data.page.has_key? "location"
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+ module Cameraplus
2
+ class Photo
3
+
4
+ attr_reader :small, :medium, :large, :width, :height, :location, :recipes, :exif
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ parse
9
+ end
10
+
11
+ private
12
+
13
+ def parse
14
+ parse_photo
15
+ parse_recipes if has_recipes?
16
+ parse_exif if has_exif?
17
+ end
18
+
19
+ def parse_photo
20
+ @small = @data["120px"]
21
+ @medium = @data["480px"]
22
+ @large = @data["800px"]
23
+ @width = @data.fullwidth.to_i
24
+ @height = @data.fullheight.to_i
25
+ @location = @data.location if has_location?
26
+ end
27
+
28
+ def parse_recipes
29
+ @recipes ||= @data.recipe.map { |recipe| PhotoRecipe.new recipe }
30
+ end
31
+
32
+ def parse_exif
33
+ @exif ||= @data.exifdata.map { |exif| PhotoExif.new exif }
34
+ end
35
+
36
+ def has_recipes?
37
+ @data.has_key? "recipe"
38
+ end
39
+
40
+ def has_exif?
41
+ @data.has_key? "exifdata"
42
+ end
43
+
44
+ def has_location?
45
+ @data.has_key? "location"
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ module Cameraplus
2
+ class PhotoExif
3
+
4
+ attr_reader :title, :value, :style
5
+
6
+ def initialize(data)
7
+ @title = data.title
8
+ @value = data.value
9
+ @style = data.style
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Cameraplus
2
+ class PhotoRecipe
3
+
4
+ attr_reader :type, :value
5
+
6
+ def initialize(data)
7
+ @type = data.type
8
+ @value = data.value
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ module Cameraplus
2
+ class Search
3
+
4
+ attr_reader :page, :user, :photos
5
+
6
+ def self.find(filters)
7
+ results = Cameraplus::API::Search.find filters
8
+ results.map { |result| new result }
9
+ end
10
+
11
+ def initialize(result)
12
+ @result ||= result
13
+ parse
14
+ end
15
+
16
+ private
17
+
18
+ def parse
19
+ parse_page
20
+ parse_user if has_user?
21
+ parse_photos if has_photos?
22
+ end
23
+
24
+ def parse_page
25
+ @page ||= Page.new @result
26
+ end
27
+
28
+ def parse_user
29
+ @user ||= User.new @result
30
+ end
31
+
32
+ def parse_photos
33
+ @photos ||= @result.images.map { |photo| Photo.new photo }
34
+ end
35
+
36
+ def has_user?
37
+ @result.has_key? "user"
38
+ end
39
+
40
+ def has_photos?
41
+ @result.has_key? "images"
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,72 @@
1
+ module Cameraplus
2
+ class User
3
+
4
+ attr_reader :id, :username, :name, :avatar, :page_count, :photo_count, :pages
5
+
6
+ def self.find(identifier, options = {})
7
+ new Cameraplus::API::User.find(identifier, options)
8
+ end
9
+
10
+ def initialize(data)
11
+ @data = data
12
+ parse
13
+ end
14
+
15
+ def more_results
16
+ @more_results ||= User.find(username, continue: next_page_id) if has_more_pages?
17
+ end
18
+
19
+ private
20
+
21
+ def parse
22
+ parse_user
23
+ parse_pages if has_pages?
24
+ end
25
+
26
+ def parse_user
27
+ @id = @data.user.userid.to_i
28
+ @username = @data.user.username
29
+ @name = @data.user.realname
30
+ @avatar = @data.user.avatar
31
+ @page_count = parsed_page_count
32
+ @photo_count = parsed_photo_count
33
+ end
34
+
35
+ def parse_pages
36
+ @pages ||= @data.pages.map { |page| Page.new page }
37
+ end
38
+
39
+ def parsed_page_count
40
+ @data.user.pages.to_i if has_page_count?
41
+ end
42
+
43
+ def parsed_photo_count
44
+ @data.user.pictures.to_i if has_photo_count?
45
+ end
46
+
47
+ def next_page_id
48
+ @data.next.match(next_page_regex).to_a.last
49
+ end
50
+
51
+ def next_page_regex
52
+ /http:\/\/camerapl.us\/user\/#{username}:pages\?continue=(.*)/
53
+ end
54
+
55
+ def has_pages?
56
+ @data.has_key? "pages"
57
+ end
58
+
59
+ def has_more_pages?
60
+ @data.has_key? "next"
61
+ end
62
+
63
+ def has_page_count?
64
+ @data.user.has_key? "pages"
65
+ end
66
+
67
+ def has_photo_count?
68
+ @data.user.has_key? "pictures"
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Cameraplus
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ class Hash
2
+
3
+ def method_missing(method, *args, &block)
4
+ if self.has_key? method
5
+ return self[method]
6
+ elsif self.has_key? method.to_s
7
+ return self[method.to_s]
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe Cameraplus::API::Page do
4
+
5
+ use_vcr_cassette :page
6
+
7
+ it "should receive a Hash" do
8
+ response = Cameraplus::API::Page.find "b72Z"
9
+ response.should be_a Hash
10
+ end
11
+
12
+ it "should make a request to the Camera+ API" do
13
+ Cameraplus::API::Request.should_receive(:call).with "/b72Z:info", {}
14
+ Cameraplus::API::Page.find "b72Z"
15
+ end
16
+
17
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe Cameraplus::API::Request do
4
+
5
+ subject { Cameraplus::API::Request }
6
+
7
+ context "configuration" do
8
+
9
+ it "should know it's base URI" do
10
+ subject.base_uri.should eq "http://camerapl.us"
11
+ end
12
+
13
+ end
14
+
15
+ context "connecting with the api" do
16
+
17
+ use_vcr_cassette :api_request_valid
18
+
19
+ let(:response) { subject.call "/user/mostlylisa:pages" }
20
+
21
+ it "should have a response" do
22
+ response.should_not be_nil
23
+ end
24
+
25
+ it "should contain user data" do
26
+ response.should have_key "user"
27
+ end
28
+
29
+ it "should contain user pages" do
30
+ response.should have_key "pages"
31
+ end
32
+
33
+ end
34
+
35
+ context "connecting with an invalid api call" do
36
+
37
+ use_vcr_cassette :api_request_invalid
38
+
39
+ let(:response) { subject.call "/non-existing-page" }
40
+
41
+ it "should raise an error" do
42
+ expect { response }.to raise_error Cameraplus::InvalidResponseError
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe Cameraplus::API::Search do
4
+
5
+ context "with a valid argument" do
6
+
7
+ use_vcr_cassette :search
8
+
9
+ it "should receive an Array" do
10
+ response = Cameraplus::API::Search.find username: "mostlylisa"
11
+ response.should be_a Array
12
+ end
13
+
14
+ it "should make a request to the Camera+ API" do
15
+ Cameraplus::API::Request.should_receive(:call).with "/search", { username: "mostlylisa" }
16
+ Cameraplus::API::Search.find username: "mostlylisa"
17
+ end
18
+
19
+ end
20
+
21
+ context "with an invalid argument" do
22
+
23
+ it "when searching for an non-existing argument should raise an error" do
24
+ expect { Cameraplus::API::Search.find foo: "bar" }.to raise_error Cameraplus::InvalidArgumentError
25
+ end
26
+
27
+ end
28
+
29
+ context "with no arguments" do
30
+
31
+ it "should raise an argument error" do
32
+ expect { Cameraplus::API::Search.find() }.to raise_error ArgumentError
33
+ end
34
+
35
+ end
36
+
37
+ end