diff --git a/CHANGELOG.md b/CHANGELOG.md index 1206b1a..e1919d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,3 +10,4 @@ For more information about changelogs, check * [FEATURE] Added `Fb::User` * [FEATURE] Added `Fb::Page` +* [FEATURE] Added `Fb::Page#posts` diff --git a/README.md b/README.md index 7a7885d..c17fdf9 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ user.email # => 'john.smith@example.com' Fb::User#pages -------------- -Given an user access token with the `manage_pages` scope, you can get the list of Facebook pages managed by the user by calling: +Given an user access token with the `pages_show_list` scope, you can get the list of Facebook pages managed by the user by calling: ```ruby user = Fb::User.new access_token: '--valid-access-token--' @@ -41,6 +41,17 @@ user.pages # => [#, #] ``` +Fb::Page#posts +-------------- + +Given a page with posts, you can get the posts on the page since creation by calling: + +```ruby +user = Fb::User.new access_token: '--valid-access-token--' +user.pages.first.posts +# => [#, #] +``` + ## Development To run tests, obtain a long-term access token for a Facebook user who manages diff --git a/lib/fb/core.rb b/lib/fb/core.rb index 8e23751..24edaca 100644 --- a/lib/fb/core.rb +++ b/lib/fb/core.rb @@ -1,7 +1,8 @@ require 'fb/support' require 'fb/page' require 'fb/user' - +require 'fb/post' +require 'fb/data_helper' # An object-oriented Ruby client for the Facebook Graph API. # @see http://www.rubydoc.info/gems/fb-core/ module Fb diff --git a/lib/fb/core/version.rb b/lib/fb/core/version.rb index e562127..6b52a6a 100644 --- a/lib/fb/core/version.rb +++ b/lib/fb/core/version.rb @@ -3,6 +3,6 @@ module Fb class Core # @return [String] the SemVer-compatible gem version. # @see http://semver.org - VERSION = '1.0.0.alpha2' + VERSION = '1.0.0.alpha3' end end diff --git a/lib/fb/data_helper.rb b/lib/fb/data_helper.rb new file mode 100644 index 0000000..10d9fb2 --- /dev/null +++ b/lib/fb/data_helper.rb @@ -0,0 +1,10 @@ +module Fb + # @private + class DataHelper + def self.symbolize_keys(hash) + {}.tap do |new_hash| + hash.each_key{|key| new_hash[key.to_sym] = hash[key]} + end + end + end +end diff --git a/lib/fb/page.rb b/lib/fb/page.rb index 0a41e5a..de3f1f3 100644 --- a/lib/fb/page.rb +++ b/lib/fb/page.rb @@ -21,9 +21,47 @@ def initialize(options = {}) @category = options[:category] end + # @return [Array] a collection of posts. + def posts + @posts ||= begin + fetch_posts.map do |post_data| + Fb::Post.new DataHelper.symbolize_keys(post_data) + end + end + end + # @return [String] the representation of the page. def to_s %Q(#<#{self.class.name} #{@id} "#{@name}">) end + + private + + def fetch_posts + result = [] + response = HTTPRequest.new(path: "/v2.9/#{@id}/posts", + params: posts_params).run.body + loop do + if response["paging"].key?("next") + result << response["data"] + next_page = response["paging"]["cursors"]["after"] + paging_params = posts_params.merge(after: next_page) + response = HTTPRequest.new(path: "/v2.9/#{@id}/posts", + params: paging_params).run.body + else + result << response["data"] + break + end + end + result.flatten + end + + def posts_params + { + fields: 'type,created_time,message,story,permalink_url', + limit: 100, + access_token: ENV['FB_TEST_ACCESS_TOKEN'] + } + end end end diff --git a/lib/fb/post.rb b/lib/fb/post.rb new file mode 100644 index 0000000..6c96e5a --- /dev/null +++ b/lib/fb/post.rb @@ -0,0 +1,34 @@ +# Ruby client to authenticate a Facebook user. +# @see http://www.rubydoc.info/gems/Fb/ +module Fb + # Fb::Post reprensents a Facebook post. Post provides getters for: + # :id, :title, :url, :created_time, and :type. + class Post + attr_reader :id, :title, :url, :created_time, :type + + # @param [Hash] options the options to initialize an instance of Fb::Post. + # @option [String] :id The post id. + # @option [String] :title The status message in the post or post story. + # @option [String] :url URL to the permalink page of the post. + # @option [String] :created_time The time the post was initially published. + # @option [String] :type A string indicating the object type of this post. + def initialize(options = {}) + @id = options[:id] + @url = options[:permalink_url] + @created_time = options[:created_time] + @type = options[:type] + @title = options[:message] || options[:story] || build_title + end + + # @return [String] the representation of the post. + def to_s + %Q(#<#{self.class.name} #{@id} "#{@type}">) + end + + private + + def build_title + "#{@type} posted #{@created_time} available at #{@url}" + end + end +end diff --git a/lib/fb/user.rb b/lib/fb/user.rb index 364cdc8..94692e1 100644 --- a/lib/fb/user.rb +++ b/lib/fb/user.rb @@ -23,17 +23,9 @@ def pages params = {access_token: @access_token} request = HTTPRequest.new path: '/me/accounts', params: params request.run.body['data'].map do |page_data| - Page.new symbolize_keys(page_data) + Page.new DataHelper.symbolize_keys(page_data) end end end - - private - - def symbolize_keys(hash) - {}.tap do |new_hash| - hash.each_key{|key| new_hash[key.to_sym] = hash[key]} - end - end end end diff --git a/spec/page/posts_spec.rb b/spec/page/posts_spec.rb new file mode 100644 index 0000000..6ce287b --- /dev/null +++ b/spec/page/posts_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +RSpec.describe 'Fb::Page#posts' do + context 'given valid options and an existing page with over 100 posts' do + let(:posts) { Fb::Page.new(id: '221406534569729').posts } + + it 'returns an array of posts' do + expect(posts).to be_a(Array) + expect(posts).to all (be_a Fb::Post) + expect(posts.map &:id).to all(be_a String) + expect(posts.map &:url).to all(be_a String) + expect(posts.map &:type).to all(be_a String) + expect(posts.map &:created_time).to all(be_a String) + expect(posts.map &:title).to all(be_a String) + end + end +end diff --git a/spec/post/to_s_spec.rb b/spec/post/to_s_spec.rb new file mode 100644 index 0000000..c5c35cc --- /dev/null +++ b/spec/post/to_s_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +RSpec.describe 'Fb::Post#to_s' do + let(:post) { Fb::Post.new id: 123, type: 'video' } + + it 'returns a pretty string representation' do + expect(post.to_s).to eq '#' + end +end