├── .github └── FUNDING.yml ├── .gitignore ├── .rspec ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── VERSION ├── fb_graph2.gemspec ├── lib ├── fb_graph2.rb ├── fb_graph2 │ ├── achievement.rb │ ├── achievement_type.rb │ ├── album.rb │ ├── app.rb │ ├── app_link_host.rb │ ├── attribute_assigner.rb │ ├── auth.rb │ ├── auth │ │ └── signed_request.rb │ ├── collection.rb │ ├── comment.rb │ ├── conversation.rb │ ├── domain.rb │ ├── edge.rb │ ├── edge │ │ ├── accounts.rb │ │ ├── achievements.rb │ │ ├── activities.rb │ │ ├── admins.rb │ │ ├── albums.rb │ │ ├── app_event_types.rb │ │ ├── app_insights.rb │ │ ├── app_link_hosts.rb │ │ ├── app_requests.rb │ │ ├── attending.rb │ │ ├── banned.rb │ │ ├── blocked.rb │ │ ├── books.rb │ │ ├── comments.rb │ │ ├── conversations.rb │ │ ├── declined.rb │ │ ├── dispute.rb │ │ ├── docs.rb │ │ ├── domains.rb │ │ ├── events.rb │ │ ├── family.rb │ │ ├── feed.rb │ │ ├── files.rb │ │ ├── friend_lists.rb │ │ ├── friends.rb │ │ ├── games.rb │ │ ├── global_brand_children.rb │ │ ├── groups.rb │ │ ├── insights.rb │ │ ├── interests.rb │ │ ├── invitable_friends.rb │ │ ├── likes.rb │ │ ├── locations.rb │ │ ├── maybe.rb │ │ ├── members.rb │ │ ├── messages.rb │ │ ├── milestones.rb │ │ ├── movies.rb │ │ ├── music.rb │ │ ├── noreply.rb │ │ ├── offers.rb │ │ ├── open_graph.rb │ │ ├── payment_transactions.rb │ │ ├── permissions.rb │ │ ├── photos.rb │ │ ├── picture.rb │ │ ├── pokes.rb │ │ ├── posts.rb │ │ ├── promotable_posts.rb │ │ ├── ratings.rb │ │ ├── refunds.rb │ │ ├── roles.rb │ │ ├── scores.rb │ │ ├── send_api.rb │ │ ├── settings.rb │ │ ├── shared_posts.rb │ │ ├── static_resources.rb │ │ ├── subscriptions.rb │ │ ├── taggable_friends.rb │ │ ├── tagged.rb │ │ ├── tagged_places.rb │ │ ├── tags.rb │ │ ├── television.rb │ │ ├── test_users.rb │ │ ├── translations.rb │ │ └── videos.rb │ ├── event.rb │ ├── exception.rb │ ├── friend_list.rb │ ├── group.rb │ ├── group_doc.rb │ ├── insight.rb │ ├── message.rb │ ├── milestone.rb │ ├── node.rb │ ├── notification.rb │ ├── offer.rb │ ├── open_graph.rb │ ├── order.rb │ ├── page.rb │ ├── page_category.rb │ ├── payment.rb │ ├── photo.rb │ ├── place.rb │ ├── place_tag.rb │ ├── post.rb │ ├── request.rb │ ├── request_filter │ │ ├── authenticator.rb │ │ └── debugger.rb │ ├── review.rb │ ├── searchable.rb │ ├── searchable │ │ └── result.rb │ ├── struct.rb │ ├── struct │ │ ├── action.rb │ │ ├── age_range.rb │ │ ├── app_event_type.rb │ │ ├── app_insight.rb │ │ ├── app_link.rb │ │ ├── context.rb │ │ ├── currency.rb │ │ ├── device.rb │ │ ├── education.rb │ │ ├── friend.rb │ │ ├── group_file.rb │ │ ├── image_source.rb │ │ ├── location.rb │ │ ├── parking.rb │ │ ├── payment_options.rb │ │ ├── permission.rb │ │ ├── picture.rb │ │ ├── poke.rb │ │ ├── privacy.rb │ │ ├── property.rb │ │ ├── rating.rb │ │ ├── restaurant_services.rb │ │ ├── restaurant_specialties.rb │ │ ├── role.rb │ │ ├── score.rb │ │ ├── setting.rb │ │ ├── share.rb │ │ ├── static_resource.rb │ │ ├── subscription.rb │ │ ├── tag.rb │ │ └── work.rb │ ├── tagged_profile.rb │ ├── test_user.rb │ ├── thread.rb │ ├── token_metadata.rb │ ├── translation.rb │ ├── user.rb │ ├── util.rb │ └── video.rb └── patch │ └── rack │ └── oauth2 │ └── util.rb └── spec ├── fb_graph2 ├── app_link_host_spec.rb ├── app_spec.rb ├── auth_spec.rb ├── collection_spec.rb ├── edge │ ├── accounts_spec.rb │ ├── achievements_spec.rb │ ├── activities_spec.rb │ ├── admins_spec.rb │ ├── albums_spec.rb │ ├── app_insights_spec.rb │ ├── app_link_hosts_spec.rb │ ├── attending_spec.rb │ ├── banned_spec.rb │ ├── blocked_spec.rb │ ├── books_spec.rb │ ├── comments_spec.rb │ ├── conversations_spec.rb │ ├── declined_spec.rb │ ├── events_spec.rb │ ├── feed_spec.rb │ ├── friend_lists_spec.rb │ ├── friends_spec.rb │ ├── groups_spec.rb │ ├── interests_spec.rb │ ├── invitable_friends_spec.rb │ ├── likes_spec.rb │ ├── maybe_spec.rb │ ├── members_spec.rb │ ├── messages_spec.rb │ ├── milestones_spec.rb │ ├── movies_spec.rb │ ├── music_spec.rb │ ├── noreply_spec.rb │ ├── offers_spec.rb │ ├── permissions_spec.rb │ ├── photos_spec.rb │ ├── picture_spec.rb │ ├── pokes_spec.rb │ ├── posts_spec.rb │ ├── promotable_posts_spec.rb │ ├── ratings_spec.rb │ ├── roles_spec.rb │ ├── scores_spec.rb │ ├── settings_spec.rb │ ├── shared_posts_spec.rb │ ├── subscriptions_spec.rb │ ├── taggable_friends_spec.rb │ ├── tagged_places_spec.rb │ ├── television_spec.rb │ ├── test_users_spec.rb │ └── videos_spec.rb ├── edge_spec.rb ├── exception_spec.rb ├── node_spec.rb ├── node_subclass_spec.rb ├── page_spec.rb ├── place_spec.rb ├── request_filter │ ├── authenticator_spec.rb │ └── debugger_spec.rb ├── searchable_spec.rb ├── struct │ ├── app_insight_spec.rb │ └── app_link_spec.rb ├── tagged_profile_spec.rb ├── test_user_spec.rb ├── token_metadata_spec.rb ├── user_spec.rb └── util_spec.rb ├── fb_graph2_spec.rb ├── mock_json ├── app │ ├── app.json │ ├── app_insights.json │ ├── app_link_hosts.json │ ├── banned.json │ ├── roles.json │ ├── subscriptions.json │ └── test_users.json ├── blank_collection.json ├── conversation │ └── messages.json ├── error │ ├── 400 │ │ ├── 191.json │ │ └── 2500.json │ └── invalid_format.json ├── event │ ├── attending.json │ ├── declined.json │ ├── maybe.json │ └── noreply.json ├── group │ └── members.json ├── page │ ├── admins.json │ ├── block_succeeded.json │ ├── blocked.json │ ├── conversations.json │ ├── milestones.json │ ├── offers.json │ ├── promotable_posts.json │ ├── ratings.json │ ├── roles.json │ ├── roles_single.json │ ├── settings.json │ └── with_optional_fields.json ├── post │ ├── comments.json │ ├── comments_with_summary.json │ ├── liked_and_commented.json │ ├── likes.json │ ├── shared_posts.json │ └── test_users.json ├── search │ └── user.json ├── success_true.json ├── success_with_id.json ├── token_metadata │ ├── app_token.json │ ├── invalid_token.json │ ├── page_token.json │ └── user_token.json ├── token_response.json ├── true.json └── user │ ├── accounts.json │ ├── achievements.json │ ├── activities.json │ ├── albums.json │ ├── books.json │ ├── events.json │ ├── feed.json │ ├── friend_lists.json │ ├── friends.json │ ├── groups.json │ ├── interests.json │ ├── invitable_friends.json │ ├── likes.json │ ├── me.json │ ├── me_with_ext_attrs.json │ ├── movies.json │ ├── music.json │ ├── permissions.json │ ├── photos.json │ ├── picture.json │ ├── pokes.json │ ├── posts.json │ ├── scores.json │ ├── taggable_friends.json │ ├── tagged_places.json │ ├── television.json │ ├── videos.json │ └── with_picture.json ├── spec_helper.rb └── spec_helper └── mock_graph.rb /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: nov 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | *.bundle 19 | *.so 20 | *.o 21 | *.a 22 | mkmf.log 23 | wiki 24 | samples 25 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format=documentation 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - gem install bundler 3 | 4 | rvm: 5 | - 2.5.8 6 | - 2.6.6 7 | - 2.7.2 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in fb_graph2.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 nov matake 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FbGraph2 2 | ==== 3 | 4 | Facebook Graph API v2.x Wrapper in Ruby 5 | 6 | [![Build Status](https://img.shields.io/travis/nov/fb_graph2/master.svg)](http://travis-ci.org/nov/fb_graph2) 7 | 8 | ## Installation 9 | 10 | Add this line to your application's Gemfile: 11 | 12 | gem 'fb_graph2' 13 | 14 | And then execute: 15 | 16 | $ bundle 17 | 18 | Or install it yourself as: 19 | 20 | $ gem install fb_graph2 21 | 22 | ## Usage 23 | 24 | See [fb_graph2 Wiki](https://github.com/nov/fb_graph2/wiki). 25 | 26 | ## Contributing 27 | 28 | 1. Fork it ( https://github.com/nov/fb_graph2/fork ) 29 | 2. Create your feature branch (`git checkout -b my-new-feature`) 30 | 3. Commit your changes (`git commit -am 'Add some feature'`) 31 | 4. Push to the branch (`git push origin my-new-feature`) 32 | 5. Create a new Pull Request 33 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | 3 | require 'rspec/core/rake_task' 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | namespace :coverage do 7 | desc 'Open coverage report' 8 | task :report do 9 | require 'simplecov' 10 | `open '#{File.join SimpleCov.coverage_path, 'index.html'}'` 11 | end 12 | end 13 | 14 | task :spec do 15 | Rake::Task[:'coverage:report'].invoke unless ENV['TRAVIS_RUBY_VERSION'] 16 | end 17 | 18 | task default: :spec -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.3.0 -------------------------------------------------------------------------------- /fb_graph2.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |gem| 2 | gem.name = 'fb_graph2' 3 | gem.version = File.read('VERSION').delete("\n\r") 4 | gem.authors = ['nov matake'] 5 | gem.email = ['nov@matake.jp'] 6 | gem.summary = %q{Facebook Graph API v2.x Wrapper in Ruby} 7 | gem.description = %q{Facebook Graph API v2.x Wrapper in Ruby} 8 | gem.homepage = 'https://github.com/nov/fb_graph2' 9 | gem.license = 'MIT' 10 | 11 | gem.files = `git ls-files -z`.split("\x0") 12 | gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) } 13 | gem.test_files = gem.files.grep(%r{^(test|gem|features)/}) 14 | gem.require_paths = ['lib'] 15 | 16 | gem.add_runtime_dependency 'httpclient', '>= 2.4' 17 | gem.add_runtime_dependency 'rack-oauth2', '>= 1.1' 18 | gem.add_runtime_dependency 'url_safe_base64' 19 | gem.add_runtime_dependency 'multi_json' 20 | gem.add_runtime_dependency 'activesupport', '>= 3.2' 21 | gem.add_development_dependency 'rake' 22 | gem.add_development_dependency 'simplecov' 23 | gem.add_development_dependency 'webmock' 24 | gem.add_development_dependency 'rspec' 25 | gem.add_development_dependency 'rspec-its' 26 | end 27 | -------------------------------------------------------------------------------- /lib/fb_graph2.rb: -------------------------------------------------------------------------------- 1 | require 'active_support' 2 | require 'active_support/core_ext' 3 | require 'active_support/concern' 4 | require 'multi_json' 5 | require 'rack/oauth2' 6 | require 'patch/rack/oauth2/util' 7 | 8 | module FbGraph2 9 | mattr_accessor :gem_version, :logger, :debugging, :_http_config_, :object_classes 10 | 11 | DEFAULT_ROOT_URL = 'https://graph.facebook.com' 12 | DEFAULT_API_VERSION = 'v7.0' 13 | self.gem_version = File.read(File.join(__dir__, '../VERSION')).strip 14 | self.logger = Logger.new(STDOUT) 15 | self.logger.progname = 'FbGraph2' 16 | 17 | class << self 18 | def root_url 19 | ::Thread.current['fb_graph2_root_url'] || DEFAULT_ROOT_URL 20 | end 21 | 22 | def root_url=(value) 23 | ::Thread.current['fb_graph2_root_url'] = value 24 | end 25 | 26 | def api_version 27 | ::Thread.current['fb_graph2_api_version'] || DEFAULT_API_VERSION 28 | end 29 | 30 | def api_version=(value) 31 | ::Thread.current['fb_graph2_api_version'] = value 32 | end 33 | 34 | def object_classes 35 | FbGraph2::Node.descendants 36 | end 37 | 38 | def debugging? 39 | !!self.debugging 40 | end 41 | def debug! 42 | Rack::OAuth2.debug! 43 | self.debugging = true 44 | end 45 | 46 | def http_client(access_token = nil) 47 | _http_client_ = HTTPClient.new( 48 | agent_name: "FbGraph2 (#{gem_version})" 49 | ) 50 | 51 | # NOTE: httpclient gem seems stopped maintaining root certtificate set, use OS default. 52 | _http_client_.ssl_config.clear_cert_store 53 | _http_client_.ssl_config.cert_store.set_default_paths 54 | 55 | _http_client_.request_filter.delete_if do |filter| 56 | filter.is_a? HTTPClient::WWWAuth 57 | end 58 | _http_client_.request_filter << RequestFilter::Authenticator.new(access_token) if access_token.present? 59 | _http_client_.request_filter << RequestFilter::Debugger.new if self.debugging? 60 | _http_config_.try(:call, _http_client_) 61 | _http_client_ 62 | end 63 | def http_config(&block) 64 | Rack::OAuth2.http_config &block unless Rack::OAuth2.http_config 65 | self._http_config_ ||= block 66 | end 67 | end 68 | end 69 | 70 | require_relative 'fb_graph2/exception' 71 | require_relative 'fb_graph2/attribute_assigner' 72 | require_relative 'fb_graph2/node' 73 | require_relative 'fb_graph2/collection' 74 | require_relative 'fb_graph2/searchable' 75 | require_relative 'fb_graph2/edge' 76 | [ 77 | '', 78 | 'request_filter' 79 | ].each do |dir| 80 | Dir[File.join(__dir__, 'fb_graph2', dir, '*.rb')].each do |file| 81 | require file 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/fb_graph2/achievement.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Achievement < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | 6 | register_attributes( 7 | raw: [:type, :no_feed_story], 8 | time: [:publish_time], 9 | app: [:application], 10 | user: [:from], 11 | custom: [:data] 12 | ) 13 | 14 | def initialize(id, attributes = {}) 15 | super 16 | if attributes.include? :data 17 | self.data = attributes[:data] 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /lib/fb_graph2/achievement_type.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class AchievementType < Node 3 | register_attributes( 4 | raw: [:type, :title, :url, :description, :is_scraped], 5 | time: [:updated_time, :created_time], 6 | picture: [:image], 7 | app: [:application], 8 | custom: [:data, :context] 9 | ) 10 | end 11 | end -------------------------------------------------------------------------------- /lib/fb_graph2/album.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Album < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | include Edge::Picture 6 | include Edge::Photos 7 | include Edge::SharedPosts 8 | 9 | register_attributes( 10 | raw: [:can_upload, :count, :cover_photo, :description, :link, :location, :name, :privacy, :type], 11 | time: [:created_time, :updated_time], 12 | user: [:from], 13 | place: [:place] 14 | ) 15 | end 16 | end -------------------------------------------------------------------------------- /lib/fb_graph2/app.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class App < Node 3 | include Edge::Achievements 4 | include Edge::AppInsights 5 | include Edge::AppLinkHosts 6 | include Edge::AppEventTypes 7 | include Edge::Banned 8 | include Edge::Groups 9 | include Edge::Permissions 10 | include Edge::Picture 11 | include Edge::Roles::AppContext 12 | include Edge::Scores 13 | include Edge::StaticResources 14 | include Edge::Subscriptions 15 | include Edge::TestUsers # called "accounts" edge on Graph API Doc. 16 | include Edge::Translations 17 | 18 | register_attributes( 19 | raw: [ 20 | :android_key_hash, :app_domains, :app_events_feature_bitmask, :app_name, :app_type, :auth_dialog_data_help_url, 21 | :auth_dialog_headline, :auth_dialog_perms_explanation, :auth_referral_default_activity_privacy, :auth_referral_enabled, 22 | :auth_referral_extended_perms, :auth_referral_friend_perms, :auth_referral_response_type, :auth_referral_user_perms, 23 | :canvas_fluid_height, :canvas_fluid_width, :canvas_url, :category, :client_config, :company, :configured_ios_sso, 24 | :contact_email, :creator_uid, :daily_active_users, :daily_active_users_rank, :deauth_callback_url, :description, 25 | :hosting_url, :icon_url, :ios_bundle_id, :ios_supports_system_auth, :ipad_app_store_id, :iphone_app_store_id, 26 | :link, :logo_url, :migrations, :mobile_profile_section_url, :mobile_web_url, :monthly_active_users, :monthly_active_users_rank, 27 | :name, :namespace, :page_tab_default_name, :page_tab_url, :privacy_policy_url, :profile_section_url, :secure_canvas_url, 28 | :secure_page_tab_url, :server_ip_whitelist, :social_discovery, :subcategory, :supports_attribution, :supports_implicit_sdk_logging, 29 | :suppress_native_ios_gdp, :terms_of_service_url, :url_scheme_suffix, :use_legacy_auth, :user_support_email, :user_support_url, 30 | :website_url, :weekly_active_users, :gdpv4_enabled, :gdpv4_nux_enabled, :gdpv4_nux_content 31 | ], 32 | timestamp: [:created_time], 33 | custom: [ 34 | :android_sdk_error_categories, :context, :ios_sdk_error_categories, :object_store_urls, :restrictions, 35 | :supports_apprequests_fast_app_switch 36 | ] 37 | ) 38 | 39 | def initialize(id, attributes = {}) 40 | super 41 | if attributes.include? :context 42 | self.context = Struct::Context::AppContext.new attributes[:context] 43 | end 44 | # TODO: handle custom attributes. 45 | end 46 | 47 | def self.app(access_token) 48 | new(:app).authenticate access_token 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/fb_graph2/app_link_host.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class AppLinkHost < Node 3 | register_attributes( 4 | raw: [:name, :canonical_url], 5 | custom: [:ios, :iphone, :ipad, :android, :windows_phone, :web] 6 | ) 7 | 8 | def initialize(id, attributes = {}) 9 | super 10 | [:ios, :iphone, :ipad, :android, :windows_phone].each do |link_attr| 11 | if attributes.include? link_attr 12 | self.send :"#{link_attr}=", collect_links(attributes, link_attr) 13 | end 14 | end 15 | if attributes.include? :web 16 | self.web = Struct::AppLink::Web.new attributes[:web] 17 | end 18 | end 19 | 20 | private 21 | 22 | def collect_links(attributes, link_attr) 23 | Collection.new(attributes[link_attr]).collect! do |link| 24 | klass = case link_attr 25 | when :ios, :iphone, :ipad 26 | Struct::AppLink::Native::IOS 27 | when :android 28 | Struct::AppLink::Native::Android 29 | when :windows_phone 30 | Struct::AppLink::Native::WindowsPhone 31 | end 32 | klass.new link 33 | end 34 | end 35 | end 36 | end -------------------------------------------------------------------------------- /lib/fb_graph2/auth.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Auth < Rack::OAuth2::Client 3 | attr_required :client_code_endpoint 4 | 5 | class Grant 6 | class FbExchangeToken < Rack::OAuth2::Client::Grant 7 | attr_required :fb_exchange_token 8 | end 9 | end 10 | 11 | def initialize(client_id, client_secret, options = {}) 12 | super options.merge( 13 | identifier: client_id, 14 | secret: client_secret, 15 | host: URI.parse(FbGraph2.root_url).host, 16 | authorization_endpoint: File.join('/', FbGraph2.api_version, '/oauth/authorize'), 17 | token_endpoint: File.join('/', FbGraph2.api_version, '/oauth/access_token'), 18 | client_code_endpoint: File.join('/', FbGraph2.api_version, '/oauth/client_code') 19 | ) 20 | end 21 | 22 | def fb_exchange_token=(access_token) 23 | @grant = Grant::FbExchangeToken.new( 24 | fb_exchange_token: access_token 25 | ) 26 | end 27 | 28 | def access_token!(options = {}) 29 | super options.merge( 30 | client_auth_method: :body 31 | ) 32 | rescue Rack::OAuth2::Client::Error => e 33 | raise Exception.detect(e.status, e.response) 34 | end 35 | 36 | def client_code!(access_token, options = {}) 37 | params = { 38 | access_token: access_token, 39 | client_id: identifier, 40 | client_secret: secret, 41 | redirect_uri: redirect_uri 42 | }.merge(options) 43 | response = Rack::OAuth2.http_client.post( 44 | absolute_uri_for(client_code_endpoint), 45 | params 46 | ) 47 | response_json = JSON.parse(response.body).with_indifferent_access 48 | case response.status 49 | when 200..201 50 | response_json 51 | else 52 | raise Exception.detect(response.status, response_json) 53 | end 54 | end 55 | 56 | def debug_token!(input_token) 57 | token_metadata = TokenMetadata.new 58 | token_metadata.authenticate access_token! 59 | token_metadata.fetch( 60 | input_token: input_token.to_s 61 | ) 62 | end 63 | 64 | def from_cookie(cookie) 65 | token = case cookie 66 | when String 67 | cookie 68 | else 69 | cookie.delete "fbsr_#{identifier}" 70 | end 71 | from_signed_request token 72 | end 73 | 74 | def from_signed_request(token) 75 | SignedRequest.new(token).verify! self 76 | end 77 | end 78 | end 79 | 80 | Dir[File.join(__dir__, 'auth/*.rb')].each do |file| 81 | require file 82 | end 83 | -------------------------------------------------------------------------------- /lib/fb_graph2/auth/signed_request.rb: -------------------------------------------------------------------------------- 1 | require 'url_safe_base64' 2 | 3 | module FbGraph2 4 | class Auth 5 | class SignedRequest 6 | class VerificationFailed < Exception::BadRequest; end 7 | 8 | attr_accessor :payload, :access_token, :user 9 | 10 | def initialize(token) 11 | signature_str, @payload_str = token.split('.', 2) 12 | @signature = UrlSafeBase64.decode64 signature_str 13 | payload_json = UrlSafeBase64.decode64 @payload_str 14 | self.payload = MultiJson.load(payload_json).with_indifferent_access 15 | rescue => e 16 | raise VerificationFailed.new 'Decode failed' 17 | end 18 | 19 | def verify!(client) 20 | signature = OpenSSL::HMAC.digest OpenSSL::Digest::SHA256.new, client.secret, @payload_str 21 | raise VerificationFailed.new('Verification failed') unless @signature == signature 22 | instantiate client 23 | end 24 | 25 | private 26 | 27 | def instantiate(client) 28 | if payload[:code].present? 29 | client.redirect_uri ||= '' 30 | client.authorization_code = payload[:code] 31 | self.access_token = client.access_token! 32 | else 33 | self.access_token = payload[:oauth_token] 34 | end 35 | self.user = User.new(payload[:user_id], payload[:user] || {}).authenticate(access_token) 36 | self 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/fb_graph2/collection.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Collection < Array 3 | attr_accessor :before, :after, :next, :previous, :total_count, :summary 4 | 5 | def initialize(collection = []) 6 | collection = normalize collection 7 | paginate collection[:paging] 8 | summarize collection[:summary] 9 | replace Array(collection[:data]) 10 | end 11 | 12 | private 13 | 14 | def normalize(collection) 15 | case collection 16 | when Hash 17 | collection 18 | when Array 19 | { 20 | data: collection, 21 | count: collection.size 22 | } 23 | else 24 | raise ArgumentError.new("Invalid collection") 25 | end 26 | end 27 | 28 | def paginate(paging) 29 | cursors = paging.try(:[], :cursors) 30 | self.before = cursors.try(:[], :before) 31 | self.after = cursors.try(:[], :after) 32 | self.next = params_in paging.try(:[], :next) 33 | self.previous = params_in paging.try(:[], :previous) 34 | end 35 | 36 | def summarize(summary) 37 | self.summary = summary 38 | self.total_count = summary.try(:[], :total_count) 39 | if summary.try(:[], :updated_time) 40 | self.summary[:updated_time] = Time.parse summary[:updated_time] 41 | end 42 | end 43 | 44 | def params_in(url) 45 | if url 46 | Rack::Utils.parse_nested_query( 47 | URI.parse(url).query 48 | ).inject({}) do |params, (key, value)| 49 | params.merge! key => value 50 | end.with_indifferent_access 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/fb_graph2/comment.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Comment < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | 6 | register_attributes( 7 | raw: [:can_comment, :can_remove, :comment_count, :like_count, :message, :user_likes, :is_hidden, :can_hide], 8 | time: [:created_time], 9 | comment: [:parent], 10 | profile: [:from], 11 | profiles: [:message_tags], 12 | custom: [:attachment] 13 | ) 14 | 15 | def initialize(id, attributes = {}) 16 | super 17 | # TODO: handle custom attributes. 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /lib/fb_graph2/conversation.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Conversation < Node 3 | include Edge::Messages 4 | register_attributes( 5 | raw: [:snippet, :message_count, :unread_count, :can_reply, :is_subscribed], 6 | time: [:updated_time], 7 | users: [:participants, :senders], 8 | tags: [:tags] 9 | ) 10 | end 11 | end -------------------------------------------------------------------------------- /lib/fb_graph2/domain.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Domain < Node 3 | include Edge::Insights 4 | 5 | register_attributes( 6 | raw: [:name] 7 | ) 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge < Collection 3 | attr_accessor :owner, :edge, :params, :options, :collection 4 | delegate :summary, :total_count, to: :collection 5 | 6 | def initialize(owner, edge, params = {}, options = {}) 7 | self.owner = owner 8 | self.edge = edge 9 | self.params = params 10 | self.options = options 11 | self.collection = options.delete(:collection) || Collection.new 12 | replace collection 13 | end 14 | 15 | def next(_options_ = {}) 16 | if collection.next.present? 17 | owner.send edge, options.merge(collection.next).merge(_options_) 18 | elsif collection.after.present? 19 | owner.send edge, options.merge(after: collection.after).merge(_options_) 20 | else 21 | self.class.new owner, edge 22 | end 23 | end 24 | 25 | def previous(_options_ = {}) 26 | if self.collection.previous.present? 27 | owner.send edge, options.merge(collection.previous).merge(_options_) 28 | elsif collection.before.present? 29 | owner.send edge, options.merge(before: collection.before).merge(_options_) 30 | else 31 | self.class.new owner, edge 32 | end 33 | end 34 | end 35 | end 36 | 37 | Dir[File.join(__dir__, 'edge/*.rb')].each do |file| 38 | require file 39 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/accounts.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Accounts 4 | def accounts(params = {}) 5 | pages = self.edge :accounts, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate page[:access_token] 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/achievements.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Achievements 4 | def achievements(params = {}) 5 | achievements = self.edge :achievements, params 6 | achievements.collect! do |achievement| 7 | Achievement.new(achievement[:id], achievement).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/activities.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Activities 4 | def activities(params = {}) 5 | pages = self.edge :activities, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/admins.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Admins 4 | def admins(params = {}) 5 | users = self.edge :admins, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | 11 | def admin?(user, params = {}) 12 | users = self.edge :admins, params, edge_scope: user 13 | users.present? 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/albums.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Albums 4 | def albums(params = {}) 5 | albums = self.edge :albums, params 6 | albums.collect! do |album| 7 | Album.new(album[:id], album).authenticate self.access_token 8 | end 9 | end 10 | 11 | def album!(params = {}) 12 | album = self.post params, edge: :albums 13 | Album.new(album[:id], params.merge(album)).authenticate self.access_token 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/app_event_types.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module AppEventTypes 4 | def app_event_types(params = {}) 5 | types = self.edge :app_event_types, params 6 | types.collect! do |type| 7 | Struct::AppEventType.new type 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/app_insights.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module AppInsights 4 | def app_insights(metric, params = {}) 5 | insights = self.edge :app_insights, params, { edge_scope: metric } 6 | insights.collect! do |insight| 7 | FbGraph2::Struct::AppInsight.new insight 8 | end 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/app_link_hosts.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module AppLinkHosts 4 | def app_link_hosts(params = {}) 5 | hosts = self.edge :app_link_hosts, params 6 | hosts.collect! do |host| 7 | AppLinkHost.new(host[:id], host).authenticate self.access_token 8 | end 9 | end 10 | 11 | def app_link_host!(params = {}) 12 | jsonized_params = params.inject({}) do |jsonized_params, (key, value)| 13 | jsonized_param = case value 14 | when Hash, Array 15 | value.to_json 16 | else 17 | value 18 | end 19 | jsonized_params.merge! key => jsonized_param 20 | end 21 | host = self.post jsonized_params, edge: :app_link_hosts 22 | AppLinkHost.new(host[:id], params.merge(host)).authenticate self.access_token 23 | end 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/app_requests.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module AppRequests 4 | def app_requests(params = {}) 5 | requests = self.edge :apprequests, params 6 | requests.collect! do |request| 7 | Request.new(request[:id], request).authenticate self.access_token 8 | end 9 | end 10 | alias_method :apprequests, :app_requests 11 | 12 | def app_request!(params = {}) 13 | response = self.post params, edge: :apprequests 14 | if request = response[:request] 15 | response[:request] = Request.new(request[:id], request).authenticate self.access_token 16 | end 17 | response 18 | end 19 | alias_method :apprequest!, :app_request! 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/attending.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Attending 4 | def attending(params = {}) 5 | users = self.edge :attending, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/banned.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Banned 4 | def banned(params = {}) 5 | users = self.edge :banned, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | 11 | def banned?(user, params = {}) 12 | users = self.edge :banned, params, edge_scope: user 13 | users.present? 14 | end 15 | 16 | def ban!(user, params = {}) 17 | self.post params.merge( 18 | uid: Util.as_identifier(user) 19 | ), edge: :banned 20 | end 21 | 22 | def unban!(user, params = {}) 23 | self.delete params.merge( 24 | uid: Util.as_identifier(user) 25 | ), edge: :banned 26 | end 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/blocked.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Blocked 4 | def blocked(params = {}) 5 | users = self.edge :blocked, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | 11 | def blocked?(user, params = {}) 12 | users = self.edge :blocked, params, edge_scope: user 13 | users.present? 14 | end 15 | 16 | def block!(user, params = {}) 17 | self.post params.merge( 18 | user: Util.as_identifier(user) 19 | ), edge: :blocked 20 | end 21 | 22 | def unblock!(user, params = {}) 23 | self.delete params.merge( 24 | user: Util.as_identifier(user) 25 | ), edge: :blocked 26 | end 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/books.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Books 4 | def books(params = {}) 5 | pages = self.edge :books, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/comments.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Comments 4 | def assign(attributes) 5 | super 6 | if attributes.include? :comments 7 | @_cached_comments = Collection.new attributes[:comments] 8 | end 9 | end 10 | 11 | def comments(params = {}) 12 | comments = if @_cached_comments.present? && params.blank? 13 | @_cached_comments 14 | else 15 | self.edge :comments, params 16 | end 17 | comments.collect! do |comment| 18 | Comment.new(comment[:id], comment).authenticate self.access_token 19 | end 20 | end 21 | 22 | def comment!(params = {}) 23 | comment = self.post params, edge: :comments 24 | Comment.new(comment[:id], params.merge(comment)).authenticate self.access_token 25 | end 26 | end 27 | end 28 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/conversations.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Conversations 4 | def conversations(params = {}) 5 | conversations = self.edge :conversations, params 6 | conversations.collect! do |conversation| 7 | Conversation.new(conversation[:id], conversation).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/declined.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Declined 4 | def declined(params = {}) 5 | users = self.edge :declined, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/dispute.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Dispute 4 | def dispute!(params = {}) 5 | self.post params, edge: :dispute 6 | end 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/docs.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Docs 4 | def docs(params = {}) 5 | docs = self.edge :docs, params 6 | docs.collect! do |doc| 7 | GroupDoc.new(doc[:id], doc).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/domains.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Domains 4 | def domains(params = {}) 5 | domains = self.edge :domains, params 6 | domains.collect! do |domain| 7 | Domain.new(domain[:id], domain).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/events.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Events 4 | def events(*args) 5 | params = args.extract_options! 6 | events = self.edge :events, params, edge_scope: args.first 7 | events.collect! do |event| 8 | Event.new(event[:id], event).authenticate self.access_token 9 | end 10 | end 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/family.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Family 4 | def family(params = {}) 5 | users = self.edge :family, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/feed.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Feed 4 | def feed(params = {}) 5 | posts = self.edge :feed, params 6 | posts.collect! do |post| 7 | Post.new(post[:id], post).authenticate self.access_token 8 | end 9 | end 10 | 11 | def feed!(params = {}) 12 | post = self.post params, edge: :feed 13 | Post.new(post[:id], params.merge(post)).authenticate self.access_token 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/files.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Files 4 | def files(params = {}) 5 | files = self.edge :files, params 6 | files.collect! do |file| 7 | Struct::GroupFile.new file 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/friend_lists.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module FriendLists 4 | def friend_lists(params = {}) 5 | friend_lists = self.edge :friendlists, params 6 | friend_lists.collect! do |friend_list| 7 | FriendList.new(friend_list[:id], friend_list).authenticate self.access_token 8 | end 9 | end 10 | alias_method :friendlists, :friend_lists 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/friends.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Friends 4 | def friends(params = {}) 5 | users = self.edge :friends, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | 11 | def friend?(user, params = {}) 12 | users = self.edge :friends, params, edge_scope: user 13 | users.present? 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/games.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Games 4 | def games(params = {}) 5 | pages = self.edge :games, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/global_brand_children.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module GlobalBrandChildren 4 | def global_brand_children(params = {}) 5 | pages = self.edge :global_brand_children, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/groups.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Groups 4 | def groups(params = {}) 5 | groups = self.edge :groups, params 6 | groups.collect! do |group| 7 | Group.new(group[:id], group).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/insights.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Insights 4 | def insights(params = {}) 5 | insights = self.edge :insights, params.except(:metrics), edge_scope: params[:metrics] 6 | insights.collect! do |insight| 7 | Insight.new(insight[:id], insight).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/interests.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Interests 4 | def interests(params = {}) 5 | pages = self.edge :interests, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/invitable_friends.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module InvitableFriends 4 | def invitable_friends(params = {}) 5 | invitable_friends = self.edge :invitable_friends, params 6 | invitable_friends.collect! do |friend| 7 | Struct::Friend.new friend 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/likes.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Likes 4 | module LikerContext 5 | def likes(params = {}) 6 | pages = self.edge :likes, params 7 | pages.collect! do |page| 8 | Page.new(page[:id], page).authenticate self.access_token 9 | end 10 | end 11 | 12 | def liked?(page, params = {}) 13 | pages = self.edge :likes, params, edge_scope: page 14 | pages.present? 15 | end 16 | end 17 | 18 | module LikeeContext 19 | def assign(attributes) 20 | super 21 | if attributes.include? :likes 22 | @_cached_likes = Collection.new attributes[:likes] 23 | end 24 | end 25 | 26 | def likes(params = {}) 27 | users = if @_cached_likes.present? && params.blank? 28 | @_cached_likes 29 | else 30 | self.edge :likes, params 31 | end 32 | users.collect! do |user| 33 | User.new(user[:id], user).authenticate self.access_token 34 | end 35 | end 36 | 37 | def like!(params = {}) 38 | self.post params, edge: :likes 39 | end 40 | 41 | def unlike!(params = {}) 42 | self.delete params, edge: :likes 43 | end 44 | end 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/locations.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Locations 4 | def locations(params = {}) 5 | pages = self.edge :locations, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | 11 | # TODO: add, delete and update locations 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/maybe.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Maybe 4 | def maybe(params = {}) 5 | users = self.edge :maybe, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/members.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Members 4 | def members(params = {}) 5 | users = self.edge :members, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/messages.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Messages 4 | def assign(attributes) 5 | super 6 | if attributes.include? :messages 7 | @_cached_messages = Collection.new attributes[:messages] 8 | end 9 | end 10 | 11 | def messages(params = {}) 12 | messages = if @_cached_messages.present? && params.blank? 13 | @_cached_messages 14 | else 15 | self.edge :messages, params 16 | end 17 | messages.collect! do |message| 18 | Message.new(message[:id], message).authenticate self.access_token 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/milestones.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Milestones 4 | def milestones(params = {}) 5 | milestones = self.edge :milestones, params 6 | milestones.collect! do |milestone| 7 | Milestone.new(milestone[:id], milestone).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/movies.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Movies 4 | def movies(params = {}) 5 | pages = self.edge :movies, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/music.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Music 4 | def music(params = {}) 5 | pages = self.edge :music, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/noreply.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Noreply 4 | def noreply(params = {}) 5 | users = self.edge :noreply, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/offers.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Offers 4 | def offers(params = {}) 5 | offers = self.edge :offers, params 6 | offers.collect! do |offer| 7 | Offer.new(offer[:id], offer).authenticate self.access_token 8 | end 9 | end 10 | 11 | def offer!(params = {}) 12 | offer = self.post params, edge: :offers 13 | Offer.new(offer[:id], params.merge(offer)).authenticate self.access_token 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/open_graph.rb: -------------------------------------------------------------------------------- 1 | Dir[File.join(__dir__, 'open_graph/*.rb')].each do |file| 2 | require file 3 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/payment_transactions.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module PaymentTransactions 4 | def payment_transactions(params = {}) 5 | payments = self.edge :payment_transactions, params 6 | payments.collect! do |payment| 7 | Payment.new(payment[:id], payment).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/permissions.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Permissions 4 | def permissions(params = {}) 5 | permissions = self.edge :permissions, params 6 | permissions.collect! do |permission| 7 | Struct::Permission.new permission 8 | end 9 | end 10 | 11 | def revoke!(permission = nil, params = {}) 12 | destroy params, edge: :permissions, edge_scope: permission 13 | end 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/photos.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Photos 4 | def photos(*args) 5 | params = args.extract_options! 6 | photos = self.edge :photos, params, edge_scope: args.first 7 | photos.collect! do |photo| 8 | Photo.new(photo[:id], photo).authenticate self.access_token 9 | end 10 | end 11 | 12 | def photo!(params = {}) 13 | photo = self.post params, edge: :photos 14 | Photo.new(photo[:id], params.merge(photo)).authenticate self.access_token 15 | end 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/picture.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Picture 4 | def assign(attributes) 5 | super 6 | if attributes.include? :picture 7 | @_cached_picture = attributes[:picture] 8 | end 9 | end 10 | 11 | def picture(*args) 12 | params = args.extract_options! 13 | params[:type] = args.first if args.first 14 | picture = if @_cached_picture.present? && params.blank? 15 | @_cached_picture 16 | else 17 | self.get params.merge(redirect: false), edge: :picture 18 | end 19 | Struct::Picture.new picture[:data] 20 | end 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/pokes.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Pokes 4 | def pokes(params = {}) 5 | pokes = self.edge :pokes, params 6 | pokes.collect! do |poke| 7 | Struct::Poke.new poke 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/posts.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Posts 4 | def posts(params = {}) 5 | posts = self.edge :posts, params 6 | posts.collect! do |post| 7 | Post.new(post[:id], post).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/promotable_posts.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module PromotablePosts 4 | def promotable_posts(params = {}) 5 | posts = self.edge :promotable_posts, params 6 | posts.collect! do |post| 7 | Post.new(post[:id], post).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/ratings.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Ratings 4 | def ratings(params = {}) 5 | ratings = self.edge :ratings, params 6 | ratings.collect! do |rating| 7 | Struct::Rating.new rating 8 | end 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/refunds.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Refunds 4 | def refund!(params = {}) 5 | self.post params, edge: :refund 6 | end 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/roles.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Roles 4 | module AppContext 5 | def roles(params = {}) 6 | roles = self.edge :roles, params 7 | roles.collect! do |role| 8 | Struct::Role.new role 9 | end 10 | end 11 | 12 | def role!(user, params = {}) 13 | self.post params.merge( 14 | user: Util.as_identifier(user) 15 | ), edge: :roles 16 | end 17 | 18 | def unrole!(user, params = {}) 19 | self.post params.merge( 20 | user: Util.as_identifier(user) 21 | ), edge: :roles 22 | end 23 | end 24 | 25 | module PageContext 26 | def roles(*args) 27 | params = args.extract_options! 28 | users = self.edge :roles, params, edge_scope: args.first 29 | users.collect! do |user| 30 | User.new(user[:id], user).authenticate self.access_token 31 | end 32 | if args.first.present? 33 | users.first 34 | else 35 | users 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/scores.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Scores 4 | def scores(params = {}) 5 | scores = self.edge :scores, params 6 | scores.collect! do |score| 7 | Struct::Score.new score 8 | end 9 | end 10 | 11 | def score!(score, params = {}) 12 | self.post params.merge(score: score), edge: :scores 13 | end 14 | 15 | def unscore!(params = {}) 16 | self.delete params, edge: :scores 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/send_api.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module SendApi 4 | def message!(params = {}) 5 | message = self.post params, edge: :messages 6 | Message.new(message[:message_id], params.merge(message)).authenticate self.access_token 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/settings.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Settings 4 | def settings(params = {}) 5 | settings = self.edge :settings, params 6 | settings.collect! do |setting| 7 | Struct::Setting.new setting 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/shared_posts.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module SharedPosts 4 | def shared_posts(params = {}) 5 | posts = self.edge :sharedposts, params 6 | posts.collect! do |post| 7 | Post.new(post[:id], post).authenticate self.access_token 8 | end 9 | end 10 | alias_method :sharedposts, :shared_posts 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/static_resources.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module StaticResources 4 | def static_resources(params = {}) 5 | resources = self.edge :staticresources, params 6 | resources.collect! do |resource| 7 | Struct::StaticResource.new resource 8 | end 9 | end 10 | alias_method :staticresources, :static_resources 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/subscriptions.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Subscriptions 4 | def subscriptions(params = {}) 5 | subscriptions = self.edge :subscriptions, params 6 | subscriptions.collect! do |subscription| 7 | Struct::Subscription.new subscription 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/taggable_friends.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module TaggableFriends 4 | def taggable_friends(params = {}) 5 | taggable_friends = self.edge :taggable_friends, params 6 | taggable_friends.collect! do |friend| 7 | Struct::Friend.new friend 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/tagged.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Tagged 4 | def tagged(params = {}) 5 | posts = self.edge :tagged, params 6 | posts.collect! do |post| 7 | Post.new(post[:id], post).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/tagged_places.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module TaggedPlaces 4 | def tagged_places(params = {}) 5 | place_tags = self.edge :tagged_places, params 6 | place_tags.collect! do |place_tag| 7 | PlaceTag.new(place_tag[:id], place_tag).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/tags.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Tags 4 | def tags(params = {}) 5 | users = self.edge :tags, params 6 | users.collect! do |user| 7 | User.new(user[:id], user).authenticate self.access_token 8 | end 9 | end 10 | 11 | # NOTE: available both for create & update 12 | def tag!(params = {}) 13 | self.post params, edge: :tags 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/television.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Television 4 | def television(params = {}) 5 | pages = self.edge :television, params 6 | pages.collect! do |page| 7 | Page.new(page[:id], page).authenticate self.access_token 8 | end 9 | end 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/test_users.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module TestUsers 4 | def test_users(params = {}) 5 | users = self.edge :accounts, params, edge_scope: :'test-users' 6 | users.collect! do |user| 7 | TestUser.new(user[:id], user) 8 | end 9 | end 10 | 11 | def test_user!(params = {}) 12 | user = self.post params, edge: :accounts, edge_scope: :'test-users' 13 | params.delete(:access_token) # so as not to keep app token 14 | TestUser.new(user[:id], user.merge(params)) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/fb_graph2/edge/translations.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Translations 4 | def translations(params = {}) 5 | translations = self.edge :translations, params 6 | translations.collect! do |translation| 7 | Translation.new(translation[:id], translation).authenticate self.authenticate 8 | end 9 | end 10 | 11 | def translation!(params = {}) 12 | self.post params, edge: :translations 13 | end 14 | alias_method :translate!, :translation! 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/edge/videos.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Edge 3 | module Videos 4 | def videos(*args) 5 | params = args.extract_options! 6 | videos = self.edge :videos, params, edge_scope: args.first 7 | videos.collect! do |video| 8 | Video.new(video[:id], video).authenticate self.access_token 9 | end 10 | end 11 | 12 | def video!(params = {}) 13 | video = self.post params, edge: :videos 14 | Video.new(video[:id], params.merge(video)).authenticate self.access_token 15 | end 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /lib/fb_graph2/event.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Event < Node 3 | include Edge::Attending 4 | include Edge::Declined 5 | include Edge::Feed 6 | include Edge::Maybe 7 | include Edge::Noreply 8 | include Edge::Picture 9 | include Edge::Photos 10 | include Edge::Videos 11 | extend Searchable 12 | 13 | register_attributes( 14 | raw: [:description, :location, :name, :ticket_uri, :timezone], 15 | time: [:end_time, :start_time, :updated_time], 16 | page: [:venue], 17 | profile: [:owner], 18 | group: [:parent_group], 19 | photo: [:cover] 20 | ) 21 | end 22 | end -------------------------------------------------------------------------------- /lib/fb_graph2/exception.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Exception < StandardError 3 | attr_accessor :status, :type, :code, :error_subcode 4 | alias_method :error_code, :code 5 | 6 | class << self 7 | def detect(status, body = {}, headers = {}) 8 | error = body[:error] 9 | message = error.try(:[], :message) 10 | klass = detect_from_header(headers, error) || detect_from_status(status) 11 | if klass 12 | klass.new message, error 13 | else 14 | new status, message, error 15 | end 16 | end 17 | 18 | def detect_from_status(status) 19 | case status 20 | when 400 21 | BadRequest 22 | when 401 23 | Unauthorized 24 | when 404 25 | NotFound 26 | when 500 27 | InternalServerError 28 | end 29 | end 30 | 31 | def detect_from_header(headers, error) 32 | key, value = headers.detect do |name, value| 33 | name.upcase == "WWW-Authenticate".upcase 34 | end || return 35 | matched, klass = ERROR_HEADER_MATCHERS.detect do |matcher, klass_name| 36 | matcher =~ value 37 | end || return 38 | klass 39 | end 40 | end 41 | 42 | def initialize(status, message, error = {}) 43 | super message 44 | self.status = status 45 | self.type = error[:type] 46 | self.code = error[:code] 47 | self.error_subcode = error[:error_subcode] 48 | end 49 | 50 | class BadRequest < Exception 51 | def initialize(message, details = {}) 52 | super 400, message, details 53 | end 54 | end 55 | 56 | class Unauthorized < Exception 57 | def initialize(message, details = {}) 58 | super 401, message, details 59 | end 60 | end 61 | 62 | class NotFound < Exception 63 | def initialize(message, details = {}) 64 | super 404, message, details 65 | end 66 | end 67 | 68 | class InternalServerError < Exception 69 | def initialize(message, details = {}) 70 | super 500, message, details 71 | end 72 | end 73 | 74 | class InvalidToken < Unauthorized; end 75 | class InvalidRequest < BadRequest; end 76 | 77 | ERROR_HEADER_MATCHERS = { 78 | /not_found/ => NotFound, 79 | /invalid_token/ => InvalidToken, 80 | /invalid_request/ => InvalidRequest 81 | } 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/fb_graph2/friend_list.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class FriendList < Node 3 | register_attributes( 4 | raw: [:name, :list_type] 5 | ) 6 | end 7 | end -------------------------------------------------------------------------------- /lib/fb_graph2/group.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Group < Node 3 | include Edge::Docs 4 | include Edge::Events 5 | include Edge::Feed 6 | include Edge::Files 7 | include Edge::Members 8 | extend Searchable 9 | 10 | register_attributes( 11 | raw: [ 12 | :description, :email, :icon, :link, :name, :privacy, 13 | # NOTE: in groups edge context 14 | :administrator, :bookmark_order, :unread 15 | ], 16 | time: [:updated_time], 17 | profile: [:owner, :parent], 18 | photo: [:cover] 19 | ) 20 | end 21 | end -------------------------------------------------------------------------------- /lib/fb_graph2/group_doc.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class GroupDoc < Node 3 | register_attributes( 4 | raw: [:subject, :message, :icon, :revision, :can_edit, :can_delete], 5 | time: [:created_time, :updated_time], 6 | profile: [:from] 7 | ) 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/insight.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Insight < Node 3 | register_attributes( 4 | raw: [:name, :description, :title, :period], 5 | custom: [:values] 6 | ) 7 | 8 | def initialize(id, attributes = {}) 9 | super 10 | self.values = attributes[:values].collect(&:with_indifferent_access) 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/message.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Message < Node 3 | register_attributes( 4 | raw: [:message, :subject], 5 | time: [:created_time], 6 | profile: [:from], 7 | profiles: [:to], 8 | tags: [:tags] 9 | ) 10 | end 11 | end -------------------------------------------------------------------------------- /lib/fb_graph2/milestone.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Milestone < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | include Edge::Photos 6 | 7 | register_attributes( 8 | raw: [:title, :description], 9 | time: [:created_time, :updated_time, :start_time, :end_time], 10 | page: [:from] 11 | ) 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/notification.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Notification < Node 3 | register_attributes( 4 | raw: [:title, :link, :unread], 5 | time: [:created_time, :updated_time], 6 | profile: [:from], 7 | user: [:to], 8 | app: [:application], 9 | custom: [:object] 10 | ) 11 | 12 | def initialize(id, attributes = {}) 13 | super 14 | # TODO: handle custom attributes. 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/offer.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Offer < Node 3 | register_attributes( 4 | raw: [:claim_limit, :coupon_type, :image_url, :redemption_code, :redemption_link, :terms, :title, :message], 5 | time: [:created_time, :expiration_time], 6 | page: [:from] 7 | ) 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/open_graph.rb: -------------------------------------------------------------------------------- 1 | Dir[File.join(__dir__, 'open_graph/*.rb')].each do |file| 2 | require file 3 | end -------------------------------------------------------------------------------- /lib/fb_graph2/order.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Order < Node 3 | register_attributes( 4 | raw: [:amount, :country, :from, :refund_reason_code, :status], 5 | time: [:created_time, :updated_time], 6 | app: [:application] 7 | ) 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/page_category.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class PageCategory < Node 3 | register_attributes( 4 | raw: [:name] 5 | ) 6 | end 7 | end -------------------------------------------------------------------------------- /lib/fb_graph2/payment.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Payment < Node 3 | include Edge::Dispute 4 | include Edge::Refunds 5 | 6 | register_attributes( 7 | raw: [:product, :quantity, :request_id, :country, :created_time, :payout_foreign_exchange_rate, :test], 8 | time: [:created_time, :updated_time], 9 | user: [:user], 10 | app: [:application], 11 | custom: [:actions, :items, :disputes] 12 | ) 13 | 14 | def initialize(id, attributes = {}) 15 | super 16 | # TODO: handle custom attributes. 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /lib/fb_graph2/photo.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Photo < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | include Edge::Tags 6 | 7 | register_attributes( 8 | raw: [ 9 | :backdated_time_granularity, :height, :icon, :link, :name, :page_story_id, :picture, :position, :source, :width, 10 | # NOTE: as cover photo 11 | :offset_y, :offset_x 12 | ], 13 | time: [:backdated_time, :created_time, :updated_time], 14 | place: [:place], 15 | profile: [:from], 16 | album: [:album], 17 | image_sources: [:images], 18 | custom: [:name_tags] 19 | ) 20 | end 21 | end -------------------------------------------------------------------------------- /lib/fb_graph2/place.rb: -------------------------------------------------------------------------------- 1 | require 'fb_graph2/page' 2 | 3 | module FbGraph2 4 | class Place < Page 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/fb_graph2/place_tag.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class PlaceTag < Node 3 | register_attributes( 4 | time: [:created_time], 5 | place: [:place] 6 | ) 7 | end 8 | end -------------------------------------------------------------------------------- /lib/fb_graph2/post.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Post < Node 3 | include Edge::Comments 4 | include Edge::Insights 5 | include Edge::Likes::LikeeContext 6 | include Edge::SharedPosts 7 | 8 | register_attributes( 9 | raw: [ 10 | :caption, :description, :icon, :is_hidden, :link, :message, :name, :object_id, :picture, 11 | :source, :status_type, :story, :type 12 | ], 13 | time: [:created_time, :updated_time], 14 | app: [:application], 15 | place: [:place], 16 | profile: [:from], 17 | profiles: [:to, :with_tags], 18 | actions: [:actions], 19 | custom: [ 20 | :message_tags, :privacy, :properties, :shares 21 | ] 22 | ) 23 | 24 | def initialize(id, attributes = {}) 25 | super 26 | if attributes.include? :message_tags 27 | self.message_tags = attributes[:message_tags].values.collect do |message_tags| 28 | message_tags.collect do |tag| 29 | TaggedProfile.new tag[:id], tag 30 | end 31 | end.flatten 32 | end 33 | if attributes.include? :privacy 34 | self.privacy = Struct::Privacy.new attributes[:privacy] 35 | end 36 | if attributes.include? :properties 37 | self.properties = attributes[:properties].collect do |property| 38 | Struct::Property.new property 39 | end 40 | end 41 | if attributes.include? :shares 42 | self.shares = Struct::Share.new attributes[:shares] 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/fb_graph2/request.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Request < Node 3 | register_attributes( 4 | raw: [:message], 5 | time: [:created_time], 6 | app: [:application], 7 | user: [:to, :from] 8 | ) 9 | end 10 | end -------------------------------------------------------------------------------- /lib/fb_graph2/request_filter/authenticator.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | module RequestFilter 3 | class Authenticator < Rack::OAuth2::AccessToken::Authenticator 4 | def initialize(access_token) 5 | _access_token_ = case access_token 6 | when Rack::OAuth2::AccessToken 7 | access_token 8 | else 9 | Rack::OAuth2::AccessToken::Bearer.new( 10 | access_token: access_token 11 | ) 12 | end 13 | super _access_token_ 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/request_filter/debugger.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | module RequestFilter 3 | class Debugger 4 | def filter_request(request) 5 | started = "======= [FbGraph2] API REQUEST STARTED =======" 6 | log started, request.dump 7 | end 8 | 9 | def filter_response(request, response) 10 | finished = "======= [FbGraph2] API REQUEST FINISHED =======" 11 | log '-' * 50, response.dump, finished 12 | end 13 | 14 | private 15 | 16 | def log(*outputs) 17 | outputs.each do |output| 18 | FbGraph2.logger.info output 19 | end 20 | end 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /lib/fb_graph2/review.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Review < Node 3 | register_attributes( 4 | raw: [:message, :rating], 5 | time: [:created_time], 6 | app: [:to], 7 | user: [:from] 8 | ) 9 | end 10 | end -------------------------------------------------------------------------------- /lib/fb_graph2/searchable.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | module Searchable 3 | def self.search(query, access_token, options = {}) 4 | klass = options.delete(:class) || Searchable 5 | collection = Collection.new( 6 | Node.new(:search).authenticate( 7 | access_token 8 | ).send(:get, options.merge(q: query)) 9 | ) 10 | yield collection if block_given? 11 | Searchable::Result.new(query, access_token, klass, options.merge(:collection => collection)) 12 | end 13 | 14 | def search(query, access_token, options = {}) 15 | type = self.to_s.split('::').last.underscore 16 | Searchable.search(query, access_token, options.merge(:type => type, :class => self)) do |collection| 17 | collection.map! do |obj| 18 | self.new(obj[:id], obj.merge( 19 | :access_token => options[:access_token] 20 | )) 21 | end 22 | end 23 | end 24 | end 25 | end 26 | 27 | require 'fb_graph2/searchable/result' 28 | -------------------------------------------------------------------------------- /lib/fb_graph2/searchable/result.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | module Searchable 3 | class Result < Collection 4 | attr_accessor :query, :access_token, :klass, :collection, :options 5 | 6 | def initialize(query, access_token, klass, options = {}) 7 | @klass = klass 8 | @access_token = access_token 9 | @query = query 10 | @options = options 11 | @collection = options.delete(:collection) || Collection.new 12 | replace @collection 13 | end 14 | 15 | def next(_options_ = {}) 16 | if collection.next.present? 17 | klass.search query, access_token, options.merge(_options_).merge(collection.next) 18 | else 19 | self.class.new query, access_token, klass 20 | end 21 | end 22 | 23 | def previous(_options_ = {}) 24 | if collection.previous.present? 25 | klass.search query, access_token, options.merge(_options_).merge(collection.previous) 26 | else 27 | self.class.new query, access_token, klass 28 | end 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | include AttributeAssigner 4 | 5 | def initialize(attributes = {}) 6 | assign attributes 7 | end 8 | end 9 | end 10 | 11 | Dir[File.join(__dir__, 'struct/*.rb')].each do |file| 12 | require file 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/action.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Action < Struct 4 | register_attributes( 5 | raw: [:name, :link] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/age_range.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class AgeRange < Struct 4 | register_attributes( 5 | raw: [:min, :max] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/app_event_type.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class AppEventType < Struct 4 | register_attributes( 5 | raw: [:event_name, :display_name, :description], 6 | custom: [:parameters] 7 | ) 8 | 9 | class Parameter < Struct 10 | register_attributes( 11 | raw: [:parameter_name, :display_name, :description] 12 | ) 13 | end 14 | 15 | def initialize(attributes = {}) 16 | super 17 | if attributes.include? :parameters 18 | self.parameters = Collection.new(attributes[:parameters]).collect! do |param| 19 | Parameter.new param 20 | end 21 | end 22 | end 23 | end 24 | end 25 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/app_insight.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class AppInsight < Struct 4 | register_attributes( 5 | raw: [:value], 6 | time: [:time] 7 | ) 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/fb_graph2/struct/app_link.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class AppLink < Struct 4 | register_attributes( 5 | raw: [:url] 6 | ) 7 | 8 | class Native < AppLink 9 | register_attributes( 10 | raw: [:app_name] 11 | ) 12 | 13 | class IOS < Native 14 | register_attributes( 15 | raw: [:app_store_id] 16 | ) 17 | end 18 | 19 | class Android < Native 20 | register_attributes( 21 | raw: [:package], 22 | custom: [:klass] 23 | ) 24 | 25 | def initialize(attributes = {}) 26 | super 27 | if attributes.include? :class 28 | self.klass = attributes[:class] 29 | end 30 | end 31 | end 32 | 33 | class WindowsPhone < Native 34 | register_attributes( 35 | raw: [:app_id] 36 | ) 37 | end 38 | end 39 | 40 | class Web < AppLink 41 | register_attributes( 42 | raw: [:should_fallback] 43 | ) 44 | end 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/context.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | module Context 4 | class UserContext < Struct 5 | register_attributes( 6 | users: [:mutual_friends], 7 | pages: [:mutual_likes] 8 | ) 9 | end 10 | 11 | class PageContext < Struct 12 | register_attributes( 13 | users: [:friends_who_like, :friends_tagged_at, :music_listen_friends, :video_watch_friends] 14 | ) 15 | end 16 | 17 | class AppContext < Struct 18 | register_attributes( 19 | users: [:friends_using_app] 20 | ) 21 | end 22 | end 23 | end 24 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/currency.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Currency < Struct 4 | register_attributes( 5 | raw: [:user_currency, :currency_exchange, :currency_exchange_inverse, :usd_exchange, :usd_exchange_inverse, :currency_offset] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/device.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Device < Struct 4 | register_attributes( 5 | raw: [:hardware, :os] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/education.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Education < Struct 4 | register_attributes( 5 | raw: [:type], 6 | page: [:school, :year, :degree], 7 | pages: [:classes, :concentration] 8 | ) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/fb_graph2/struct/friend.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Friend < Struct 4 | register_attributes( 5 | raw: [:id, :name], # NOTE: this 'id' isn't user_id, but a token for invitation/tagging. 6 | picture: [:picture] 7 | ) 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/group_file.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class GroupFile < Struct 4 | register_attributes( 5 | raw: [:id, :download_link], 6 | time: [:updated_time], 7 | user: [:from], 8 | group: [:group] 9 | ) 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/image_source.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class ImageSource < Struct 4 | register_attributes( 5 | raw: [:height, :source, :width] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/location.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Location < Struct 4 | register_attributes( 5 | raw: [:city, :country, :latitude, :located_in, :longitude, :name, :region, :state, :street, :zip] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/parking.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Parking < Struct 4 | register_attributes( 5 | int_flag: [:street, :lot, :valet] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/payment_options.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class PaymentOptions < Struct 4 | register_attributes( 5 | int_flag: [:amex, :cash_only, :discover, :mastercard, :visa] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/permission.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Permission < Struct 4 | register_attributes( 5 | raw: [:permission, :status] 6 | ) 7 | 8 | def as_identifier 9 | permission 10 | end 11 | 12 | def revokable? 13 | !['public_profile'].include? permission 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/picture.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Picture < Struct 4 | register_attributes( 5 | raw: [:url, :is_silhouette, :height, :width] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/poke.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Poke < Struct 4 | register_attributes( 5 | time: [:created_time], 6 | user: [:from, :to] 7 | ) 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/privacy.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Privacy < Struct 4 | register_attributes( 5 | raw: [:description, :value, :friends, :allow, :deny] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/property.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Property < Struct 4 | register_attributes( 5 | raw: [:name, :text, :href] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/rating.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Rating < Struct 4 | register_attributes( 5 | raw: [:has_rating, :has_review, :rating, :review_text], 6 | time: [:created_time], 7 | user: [:reviewer], 8 | custom: [:open_graph_story] 9 | ) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/fb_graph2/struct/restaurant_services.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class RestaurantServices < Struct 4 | register_attributes( 5 | int_flag: [:kids, :delivery, :walkins, :catering, :reserve, :groups, :waiter, :outdoor, :takeout] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/restaurant_specialties.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class RestaurantSpecialties < Struct 4 | register_attributes( 5 | int_flag: [:coffee, :drinks, :breakfast, :dinner, :lunch] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/role.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Role < Struct 4 | register_attributes( 5 | raw: [:app_id, :user, :role] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/score.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Score < Struct 4 | register_attributes( 5 | raw: [:score], 6 | user: [:user], 7 | app: [:application] 8 | ) 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/setting.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Setting < Struct 4 | register_attributes( 5 | raw: [:setting, :value] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/share.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Share < Struct 4 | register_attributes( 5 | raw: [:count] 6 | ) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/fb_graph2/struct/static_resource.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class StaticResource < Struct 4 | register_attributes( 5 | raw: [:usage_stats, :prefetched_resources], 6 | custom: [:https] 7 | ) 8 | 9 | def initialize(attributes = {}) 10 | super 11 | if attributes.include? :https 12 | self.https = self.class.new attributes[:https] 13 | end 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/subscription.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Subscription < Struct 4 | register_attributes( 5 | raw: [:object, :callback_url, :fields, :active] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/tag.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Tag < Struct 4 | register_attributes( 5 | raw: [:name] 6 | ) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/fb_graph2/struct/work.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Struct 3 | class Work < Struct 4 | register_attributes( 5 | page: [:employer, :location, :position], 6 | pages: [:projects], 7 | time: [:start_date, :end_date] 8 | ) 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/fb_graph2/tagged_profile.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class TaggedProfile < Node 3 | register_attributes( 4 | raw: [:name, :type, :offset, :length], 5 | custom: [:object] 6 | ) 7 | 8 | def initialize(id, attributes = {}) 9 | super 10 | self.object = klass.new self.id 11 | end 12 | 13 | def klass 14 | klass = case self.type 15 | when 'user' 16 | User 17 | when 'page' 18 | Page 19 | when 'group' 20 | Group 21 | when 'event' 22 | Event 23 | when 'application' 24 | App 25 | else 26 | Node 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/fb_graph2/test_user.rb: -------------------------------------------------------------------------------- 1 | require 'fb_graph2/user' 2 | 3 | module FbGraph2 4 | class TestUser < User 5 | register_attributes( 6 | raw: [:login_url, :password] 7 | ) 8 | 9 | def friend!(test_user) 10 | self.post({}, edge: :friends, edge_scope: test_user.id) 11 | test_user.post({}, edge: :friends, edge_scope: self.id) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/fb_graph2/thread.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Thread < Node 3 | include Edge::Messages 4 | alias_method :comments, :messages 5 | 6 | register_attributes( 7 | raw: [:unread, :unseen], 8 | time: [:updated_time], 9 | profiles: [:to], 10 | messages: [:comments] 11 | ) 12 | end 13 | end -------------------------------------------------------------------------------- /lib/fb_graph2/token_metadata.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class TokenMetadata < Node 3 | register_attributes( 4 | raw: [ 5 | :app_id, :application, :error, :is_valid, :metadata, :profile_id, :scopes, :user_id 6 | ], 7 | timestamp: [:expires_at, :issued_at], 8 | custom: [:app, :user, :page] 9 | ) 10 | 11 | def initialize(attributes = {}) 12 | super :debug_token, attributes 13 | if app_id 14 | self.app = App.new app_id 15 | end 16 | if user_id 17 | self.user = User.new user_id 18 | end 19 | if profile_id 20 | self.page = Page.new profile_id 21 | end 22 | end 23 | 24 | def fetch(params = {}, options = {}) 25 | attributes = get params, options 26 | self.class.new(attributes[:data]).authenticate access_token 27 | end 28 | 29 | def valid? 30 | !!is_valid 31 | end 32 | 33 | def app_token? 34 | app.present? && user.blank? && page.blank? 35 | end 36 | 37 | def user_token? 38 | app.present? && user.present? && page.blank? 39 | end 40 | 41 | def page_token? 42 | app.present? && user.present? && page.present? 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /lib/fb_graph2/translation.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Translation < Node 3 | register_attributes( 4 | raw: [:translation, :approval_status, :native_string, :description] 5 | ) 6 | end 7 | end -------------------------------------------------------------------------------- /lib/fb_graph2/util.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | module Util 3 | module_function 4 | 5 | def as_identifier(object) 6 | if object.respond_to? :id 7 | object.id 8 | elsif object.respond_to? :as_identifier 9 | object.as_identifier 10 | else 11 | object 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/fb_graph2/video.rb: -------------------------------------------------------------------------------- 1 | module FbGraph2 2 | class Video < Node 3 | include Edge::Comments 4 | include Edge::Likes::LikeeContext 5 | include Edge::SharedPosts 6 | 7 | register_attributes( 8 | raw: [:description, :embed_html, :icon, :length, :name, :picture, :source], 9 | time: [:created_time, :updated_time], 10 | profile: [:from], 11 | custom: [:format, :thumbnails] 12 | ) 13 | end 14 | end -------------------------------------------------------------------------------- /lib/patch/rack/oauth2/util.rb: -------------------------------------------------------------------------------- 1 | # NOTE: Authorization code given via FB JS SDK needs blank string as redirect_uri 2 | 3 | module Rack::OAuth2::Util 4 | class << self 5 | module ComcactHashWithBrankRedirect 6 | def compact_hash(hash) 7 | original_redirect_uri = hash[:redirect_uri] 8 | result = super 9 | if original_redirect_uri 10 | result[:redirect_uri] ||= original_redirect_uri 11 | end 12 | result 13 | end 14 | end 15 | prepend ComcactHashWithBrankRedirect 16 | end 17 | end -------------------------------------------------------------------------------- /spec/fb_graph2/app_link_host_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::AppLinkHost do 4 | let(:app_link_host) do 5 | FbGraph2::AppLinkHost.new( 6 | 'host_id', 7 | name: 'Sample', 8 | canonical_url: 'https://fb.me/804327549686491', 9 | ios: [{ 10 | app_name: 'Sample iOS', 11 | app_store_id: 'ios.sample.fb_graph2', 12 | url: 'fbgraph2://ios' 13 | }], 14 | iphone: [{ 15 | app_name: 'Sample iPhone', 16 | app_store_id: 'iphone.sample.fb_graph2', 17 | url: 'fbgraph2://iphone' 18 | }], 19 | android: [{ 20 | app_name: 'Sample Android', 21 | class: 'FbGraph2', 22 | package: 'android.sample.fb_graph2', 23 | url: 'fbgraph2://android' 24 | }], 25 | windows_phone: [{ 26 | app_name: 'Sample WindowsPhone', 27 | app_id: 'windows_phone.sample.fb_graph2', 28 | url: 'fbgraph2://windows_phone' 29 | }], 30 | web: { 31 | should_fallback: true, 32 | url: 'https://fbgraphsample.herokuapp.com/app_links/sample' 33 | } 34 | ) 35 | end 36 | subject { app_link_host } 37 | 38 | its(:id) { should == 'host_id' } 39 | its(:name) { should == 'Sample' } 40 | its(:canonical_url) { should == 'https://fb.me/804327549686491' } 41 | 42 | describe 'iOS' do 43 | subject { app_link_host.ios.first } 44 | its(:app_name) { should == 'Sample iOS' } 45 | its(:app_store_id) { should == 'ios.sample.fb_graph2' } 46 | its(:url) { should == 'fbgraph2://ios' } 47 | end 48 | 49 | describe 'iPhone' do 50 | subject { app_link_host.iphone.first } 51 | its(:app_name) { should == 'Sample iPhone' } 52 | its(:app_store_id) { should == 'iphone.sample.fb_graph2' } 53 | its(:url) { should == 'fbgraph2://iphone' } 54 | end 55 | 56 | describe 'Android' do 57 | subject { app_link_host.android.first } 58 | its(:app_name) { should == 'Sample Android' } 59 | its(:klass) { should == 'FbGraph2' } 60 | its(:package) { should == 'android.sample.fb_graph2' } 61 | its(:url) { should == 'fbgraph2://android' } 62 | end 63 | 64 | describe 'WindowsPhone' do 65 | subject { app_link_host.windows_phone.first } 66 | its(:app_name) { should == 'Sample WindowsPhone' } 67 | its(:app_id) { should == 'windows_phone.sample.fb_graph2' } 68 | its(:url) { should == 'fbgraph2://windows_phone' } 69 | end 70 | end -------------------------------------------------------------------------------- /spec/fb_graph2/app_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::App do 4 | describe '.app' do 5 | it 'should not call API' do 6 | expect do 7 | app = described_class.app 'token' 8 | app.should be_instance_of described_class 9 | end.not_to request_to 'app' 10 | end 11 | 12 | context 'when fetched' do 13 | it 'should call API' do 14 | app = mock_graph :get, 'app', 'app/app' do 15 | described_class.app('token').fetch 16 | end 17 | app.should be_instance_of described_class 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /spec/fb_graph2/collection_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Collection do 4 | context 'when non-collection object given' do 5 | it do 6 | expect do 7 | FbGraph2::Collection.new 'scalar' 8 | end.to raise_error ArgumentError 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/accounts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Accounts do 4 | context 'included in User' do 5 | describe '#accounts' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page with page token' do 8 | accounts = mock_graph :get, 'me/accounts', 'user/accounts', access_token: 'token' do 9 | me.accounts 10 | end 11 | accounts.should be_instance_of FbGraph2::Edge 12 | accounts.should_not be_blank 13 | accounts.each do |account| 14 | account.should be_instance_of FbGraph2::Page 15 | account.access_token.should == 'page_token' 16 | end 17 | accounts.first.name.should == 'Identity Conference #idcon' 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/achievements_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Achievements do 4 | context 'included in User' do 5 | describe '#achievements' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Achievement' do 8 | achievements = mock_graph :get, 'me/achievements', 'user/achievements', access_token: 'token' do 9 | me.achievements 10 | end 11 | achievements.should be_instance_of FbGraph2::Edge 12 | achievements.should_not be_blank 13 | achievements.each do |achievement| 14 | achievement.should be_instance_of FbGraph2::Achievement 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/activities_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Activities do 4 | context 'included in User' do 5 | describe '#activities' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/activities', 'user/activities', access_token: 'token' do 9 | me.activities 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/admins_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Admins do 4 | context 'included in Page' do 5 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 6 | 7 | describe '#admins' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'page_id/admins', 'page/admins', access_token: 'page_token' do 10 | page.admins 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | 20 | describe '#admin?' do 21 | let(:user_id) { 'user_id' } 22 | let(:user) { FbGraph2::Page.new(user_id) } 23 | 24 | context 'when String given' do 25 | it do 26 | mock_graph :get, "page_id/admins/#{user_id}", 'page/admins', access_token: 'page_token' do 27 | page.admin? user_id 28 | end.should be true 29 | end 30 | end 31 | 32 | context 'when FbGraph2::User given' do 33 | it do 34 | mock_graph :get, "page_id/admins/#{user_id}", 'page/admins', access_token: 'page_token' do 35 | page.admin? user 36 | end.should be true 37 | end 38 | end 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/albums_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Albums do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | 7 | describe '#albums' do 8 | it 'should return an Array of FbGraph2::Video' do 9 | albums = mock_graph :get, 'me/albums', 'user/albums', access_token: 'token' do 10 | me.albums 11 | end 12 | albums.should be_instance_of FbGraph2::Edge 13 | albums.should_not be_blank 14 | albums.each do |album| 15 | album.should be_instance_of FbGraph2::Album 16 | end 17 | end 18 | end 19 | 20 | describe '#album!' do 21 | it do 22 | album = mock_graph :post, 'me/albums', 'success_with_id', access_token: 'token', params: { 23 | name: 'test' 24 | } do 25 | me.album! name: 'test' 26 | end 27 | album.should be_instance_of FbGraph2::Album 28 | end 29 | end 30 | end 31 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/app_insights_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::AppInsights do 4 | let(:app) { FbGraph2::App.app('app_token') } 5 | 6 | describe '#app_link_hosts' do 7 | it 'should return an Array of FbGraph2::AppInsight' do 8 | mock_graph :get, 'app/app_insights/metric', 'app/app_insights', access_token: 'app_token' do 9 | insights = app.app_insights('metric') 10 | insights.should be_instance_of FbGraph2::Edge 11 | insights.should_not be_blank 12 | insights.each do |host| 13 | host.should be_instance_of FbGraph2::Struct::AppInsight 14 | end 15 | end 16 | end 17 | end 18 | 19 | end 20 | -------------------------------------------------------------------------------- /spec/fb_graph2/edge/app_link_hosts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::AppLinkHosts do 4 | let(:app) { FbGraph2::App.app('app_token') } 5 | 6 | describe '#app_link_hosts' do 7 | it 'should return an Array of FbGraph2::AppLinkHost' do 8 | mock_graph :get, 'app/app_link_hosts', 'app/app_link_hosts', access_token: 'app_token' do 9 | hosts = app.app_link_hosts 10 | hosts.should be_instance_of FbGraph2::Edge 11 | hosts.should_not be_blank 12 | hosts.each do |host| 13 | host.should be_instance_of FbGraph2::AppLinkHost 14 | end 15 | end 16 | end 17 | end 18 | 19 | describe '#app_link_host!' do 20 | it 'should return an FbGraph2::AppLinkHost' do 21 | mock_graph :post, 'app/app_link_hosts', 'success_with_id', access_token: 'app_token', params: { 22 | name: 'Sample', 23 | web: { 24 | should_fallback: true, 25 | url: 'https://fbgraphsample.herokuapp.com/app_links/sample' 26 | }.to_json, 27 | windows_phone: [{ 28 | url: 'test://activate' 29 | }].to_json 30 | } do 31 | host = app.app_link_host!( 32 | name: 'Sample', 33 | web: { 34 | should_fallback: true, 35 | url: 'https://fbgraphsample.herokuapp.com/app_links/sample' 36 | }, 37 | windows_phone: [{ 38 | url: 'test://activate' 39 | }] 40 | ) 41 | host.should be_instance_of FbGraph2::AppLinkHost 42 | host.id.should == 'created_object_id' 43 | host.name.should == 'Sample' 44 | host.web.should be_instance_of FbGraph2::Struct::AppLink::Web 45 | host.web.should_fallback.should == true 46 | host.web.url.should == 'https://fbgraphsample.herokuapp.com/app_links/sample' 47 | host.windows_phone.should be_instance_of FbGraph2::Collection 48 | host.windows_phone.each do |link| 49 | link.should be_instance_of FbGraph2::Struct::AppLink::Native::WindowsPhone 50 | end 51 | host.windows_phone.first.url.should == 'test://activate' 52 | end 53 | end 54 | end 55 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/attending_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Attending do 4 | context 'included in Event' do 5 | let(:event) { FbGraph2::Event.new('event_id').authenticate('token') } 6 | 7 | describe '#attending' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'event_id/attending', 'event/attending', access_token: 'token' do 10 | event.attending 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/banned_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Banned do 4 | context 'included in App' do 5 | let(:app) { FbGraph2::App.app('app_token') } 6 | let(:user_id) { 'user_id' } 7 | let(:user) { FbGraph2::User.new(user_id) } 8 | 9 | describe '#banned' do 10 | it 'should return an Array of FbGraph2::User' do 11 | users = mock_graph :get, 'app/banned', 'app/banned', access_token: 'app_token' do 12 | app.banned 13 | end 14 | users.should be_instance_of FbGraph2::Edge 15 | users.should_not be_blank 16 | users.each do |user| 17 | user.should be_instance_of FbGraph2::User 18 | end 19 | end 20 | end 21 | 22 | describe '#banned?' do 23 | context 'when String given' do 24 | it do 25 | mock_graph :get, "app/banned/#{user_id}", 'app/banned', access_token: 'app_token' do 26 | app.banned? user_id 27 | end.should be true 28 | end 29 | end 30 | 31 | context 'when FbGraph2::User given' do 32 | it do 33 | mock_graph :get, "app/banned/#{user_id}", 'app/banned', access_token: 'app_token' do 34 | app.banned? user 35 | end.should be true 36 | end 37 | end 38 | end 39 | 40 | describe '#ban!' do 41 | it do 42 | mock_graph :post, 'app/banned', 'true', access_token: 'app_token', params: { 43 | uid: user_id 44 | } do 45 | app.ban! user 46 | end.should be true 47 | end 48 | end 49 | 50 | describe '#unban!' do 51 | it do 52 | mock_graph :delete, 'app/banned', 'true', access_token: 'app_token', params: { 53 | uid: user_id 54 | } do 55 | app.unban! user 56 | end.should be true 57 | end 58 | end 59 | end 60 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/blocked_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Blocked do 4 | context 'included in Page' do 5 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 6 | let(:user_id) { 'user_id' } 7 | let(:user) { FbGraph2::User.new(user_id) } 8 | 9 | describe '#blocked' do 10 | it 'should return an Array of FbGraph2::User' do 11 | users = mock_graph :get, 'page_id/blocked', 'page/blocked', access_token: 'page_token' do 12 | page.blocked 13 | end 14 | users.should be_instance_of FbGraph2::Edge 15 | users.should_not be_blank 16 | users.each do |user| 17 | user.should be_instance_of FbGraph2::User 18 | end 19 | end 20 | end 21 | 22 | describe '#blocked?' do 23 | context 'when String given' do 24 | it do 25 | mock_graph :get, "page_id/blocked/#{user_id}", 'page/blocked', access_token: 'page_token' do 26 | page.blocked? user_id 27 | end.should be true 28 | end 29 | end 30 | 31 | context 'when FbGraph2::User given' do 32 | it do 33 | mock_graph :get, "page_id/blocked/#{user_id}", 'page/blocked', access_token: 'page_token' do 34 | page.blocked? user 35 | end.should be true 36 | end 37 | end 38 | end 39 | 40 | describe '#block!' do 41 | it do 42 | result = mock_graph :post, 'page_id/blocked', 'page/block_succeeded', access_token: 'page_token', params: { 43 | user: user_id 44 | } do 45 | page.block! user 46 | end 47 | result.should == {'user_id' => true} 48 | end 49 | end 50 | 51 | describe '#unblock!' do 52 | it do 53 | mock_graph :delete, 'page_id/blocked', 'true', access_token: 'page_token', params: { 54 | user: user_id 55 | } do 56 | page.unblock! user 57 | end.should be true 58 | end 59 | end 60 | end 61 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/books_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Books do 4 | context 'included in User' do 5 | describe '#books' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/books', 'user/books', access_token: 'token' do 9 | me.books 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/comments_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Comments do 4 | context 'included in Post' do 5 | let(:post) { FbGraph2::Post.new('post_id').authenticate('token') } 6 | 7 | describe '#comments' do 8 | context 'when cached' do 9 | let(:fetched) do 10 | mock_graph :get, 'post_id', 'post/liked_and_commented', access_token: 'token' do 11 | post.fetch 12 | end 13 | end 14 | 15 | context 'without params' do 16 | it 'should not call API' do 17 | expect do 18 | fetched.comments 19 | end.not_to request_to "#{fetched.id}/comments" 20 | end 21 | end 22 | 23 | context 'with params' do 24 | it 'should call API' do 25 | expect do 26 | fetched.comments no_cache: true 27 | end.to request_to "#{fetched.id}/comments" 28 | end 29 | end 30 | end 31 | 32 | context 'otherwise' do 33 | it 'should return an Array of FbGraph2::Post' do 34 | comments = mock_graph :get, 'post_id/comments', 'post/comments', access_token: 'token' do 35 | post.comments 36 | end 37 | comments.should be_instance_of FbGraph2::Edge 38 | comments.should_not be_blank 39 | comments.each do |comment| 40 | comment.should be_instance_of FbGraph2::Comment 41 | end 42 | end 43 | end 44 | 45 | context 'when summary requested' do 46 | it 'should be summarized' do 47 | comments = mock_graph :get, 'post_id/comments', 'post/comments_with_summary', access_token: 'token', params: { 48 | summary: true 49 | } do 50 | post.comments(summary: true) 51 | end 52 | comments.summary.should include order: 'chronological', total_count: 4 53 | comments.total_count.should == 4 54 | end 55 | end 56 | end 57 | 58 | describe '#comment!' do 59 | it 'should return FbGraph2::Post with posted params' do 60 | comment = mock_graph :post, 'post_id/comments', 'success_with_id', access_token: 'token' do 61 | post.comment! message: 'hello' 62 | end 63 | comment.should be_instance_of FbGraph2::Comment 64 | comment.id.should == 'created_object_id' 65 | comment.message.should == 'hello' 66 | end 67 | end 68 | end 69 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/conversations_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Conversations do 4 | context 'Conversations' do 5 | let(:page) { FbGraph2::Page.new("page_id").authenticate('token') } 6 | 7 | describe '#conversations' do 8 | it 'should return an Array of authenticated FbGraph2::Conversation objects' do 9 | 10 | conversations = mock_graph :get, 'page_id/conversations', 'page/conversations', access_token: 'token' do 11 | page.conversations 12 | end 13 | 14 | conversations.each { |conversation| expect(conversation.access_token).to eq('token') } 15 | 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/fb_graph2/edge/declined_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Declined do 4 | context 'included in Event' do 5 | let(:event) { FbGraph2::Event.new('event_id').authenticate('token') } 6 | 7 | describe '#declined' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'event_id/declined', 'event/declined', access_token: 'token' do 10 | event.declined 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/events_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Events do 4 | context 'included in User' do 5 | describe '#events' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Event' do 8 | events = mock_graph :get, 'me/events', 'user/events', access_token: 'token' do 9 | me.events 10 | end 11 | events.should be_instance_of FbGraph2::Edge 12 | events.should_not be_blank 13 | events.each do |event| 14 | event.should be_instance_of FbGraph2::Event 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/feed_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Feed do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | 7 | describe '#feed' do 8 | it 'should return an Array of FbGraph2::Post' do 9 | posts = mock_graph :get, 'me/feed', 'user/feed', access_token: 'token' do 10 | me.feed 11 | end 12 | posts.should be_instance_of FbGraph2::Edge 13 | posts.should_not be_blank 14 | posts.each do |post| 15 | post.should be_instance_of FbGraph2::Post 16 | end 17 | end 18 | end 19 | 20 | describe '#feed!' do 21 | it 'should return FbGraph2::Post with posted params' do 22 | post = mock_graph :post, 'me/feed', 'success_with_id', access_token: 'token' do 23 | me.feed! message: 'hello' 24 | end 25 | post.should be_instance_of FbGraph2::Post 26 | post.id.should == 'created_object_id' 27 | post.message.should == 'hello' 28 | end 29 | 30 | context 'with location' do 31 | it 'should convert place_id to Place object' do 32 | post = mock_graph :post, 'me/feed', 'success_with_id', access_token: 'token' do 33 | me.feed! place: 'place_id' 34 | end 35 | post.place.should be_instance_of FbGraph2::Place 36 | post.place.id.should == 'place_id' 37 | end 38 | end 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/friend_lists_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::FriendLists do 4 | context 'included in User' do 5 | describe '#friend_lists' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::FriendList' do 8 | friend_lists = mock_graph :get, 'me/friendlists', 'user/friend_lists', access_token: 'token' do 9 | me.friend_lists 10 | end 11 | friend_lists.should be_instance_of FbGraph2::Edge 12 | friend_lists.should_not be_blank 13 | friend_lists.each do |friend_list| 14 | friend_list.should be_instance_of FbGraph2::FriendList 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/friends_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Friends do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | 7 | describe '#friends' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'me/friends', 'user/friends', access_token: 'token' do 10 | me.friends 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | 20 | describe '#friend?' do 21 | context 'when is friend' do 22 | it do 23 | mock_graph :get, 'me/friends/user_id', 'user/friends', access_token: 'token' do 24 | me.friend? 'user_id' 25 | end.should be true 26 | end 27 | end 28 | 29 | context 'otherwise' do 30 | it do 31 | mock_graph :get, 'me/friends/user_id', 'blank_collection', access_token: 'token' do 32 | me.friend? 'user_id' 33 | end.should be false 34 | end 35 | end 36 | end 37 | end 38 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/groups_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Groups do 4 | context 'included in User' do 5 | describe '#groups' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | groups = mock_graph :get, 'me/groups', 'user/groups', access_token: 'token' do 9 | me.groups 10 | end 11 | groups.should be_instance_of FbGraph2::Edge 12 | groups.should_not be_blank 13 | groups.each do |group| 14 | group.should be_instance_of FbGraph2::Group 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/interests_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Interests do 4 | context 'included in User' do 5 | describe '#interests' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/interests', 'user/interests', access_token: 'token' do 9 | me.interests 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/invitable_friends_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::InvitableFriends do 4 | context 'included in User' do 5 | describe '#invitable_friends' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Struct::Friend' do 8 | users = mock_graph :get, 'me/invitable_friends', 'user/invitable_friends', access_token: 'token' do 9 | me.invitable_friends 10 | end 11 | users.should be_instance_of FbGraph2::Edge 12 | users.should_not be_blank 13 | users.each do |user| 14 | user.should be_instance_of FbGraph2::Struct::Friend 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/maybe_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Maybe do 4 | context 'included in Event' do 5 | let(:event) { FbGraph2::Event.new('event_id').authenticate('token') } 6 | 7 | describe '#maybe' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'event_id/maybe', 'event/maybe', access_token: 'token' do 10 | event.maybe 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/members_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Members do 4 | context 'included in Group' do 5 | let(:group) { FbGraph2::Group.new('group_id').authenticate('token') } 6 | 7 | describe '#members' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'group_id/members', 'group/members', access_token: 'token' do 10 | group.members 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | users.last.administrator.should be true 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/messages_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Messages do 4 | context 'Messages' do 5 | let(:conversation) { FbGraph2::Conversation.new("conversation_id").authenticate('token') } 6 | 7 | describe '#messages' do 8 | it 'should return an Array of authenticated FbGraph2::Message objects' do 9 | 10 | messages = mock_graph :get, 'conversation_id/messages', 'conversation/messages', access_token: 'token' do 11 | conversation.messages 12 | end 13 | 14 | expect(messages.first.access_token).to eq('token') 15 | 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/fb_graph2/edge/milestones_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Milestones do 4 | context 'included in Page' do 5 | describe '#milestones' do 6 | let(:page) { FbGraph2::Page.new('page_id').authenticate('token') } 7 | it 'should return an Array of FbGraph2::Milestone' do 8 | milestones = mock_graph :get, 'page_id/milestones', 'page/milestones', access_token: 'token' do 9 | page.milestones 10 | end 11 | milestones.should be_instance_of FbGraph2::Edge 12 | milestones.should_not be_blank 13 | milestones.each do |milestone| 14 | milestone.should be_instance_of FbGraph2::Milestone 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/movies_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Movies do 4 | context 'included in User' do 5 | describe '#movies' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/movies', 'user/movies', access_token: 'token' do 9 | me.movies 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/music_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Music do 4 | context 'included in User' do 5 | describe '#music' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/music', 'user/music', access_token: 'token' do 9 | me.music 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/noreply_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Noreply do 4 | context 'included in Event' do 5 | let(:event) { FbGraph2::Event.new('event_id').authenticate('token') } 6 | 7 | describe '#noreply' do 8 | it 'should return an Array of FbGraph2::User' do 9 | users = mock_graph :get, 'event_id/noreply', 'event/noreply', access_token: 'token' do 10 | event.noreply 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::User 16 | end 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/offers_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Offers do 4 | context 'included in Page' do 5 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 6 | 7 | describe '#offers' do 8 | it 'should return an Array of FbGraph2::Offer' do 9 | offers = mock_graph :get, 'page_id/offers', 'page/offers', access_token: 'page_token' do 10 | page.offers 11 | end 12 | offers.should be_instance_of FbGraph2::Edge 13 | offers.should_not be_blank 14 | offers.each do |offer| 15 | offer.should be_instance_of FbGraph2::Offer 16 | end 17 | end 18 | end 19 | 20 | describe '#offer!' do 21 | it 'should return FbGraph2::Offer' do 22 | offer = mock_graph :post, 'page_id/offers', 'success_with_id', access_token: 'page_token', params: { 23 | title: 'Foobar', 24 | expiration_time: 10.days.from_now.to_s 25 | } do 26 | page.offer!( 27 | title: 'Foobar', 28 | expiration_time: 10.days.from_now 29 | ) 30 | end 31 | offer.should be_instance_of FbGraph2::Offer 32 | end 33 | end 34 | end 35 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/permissions_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Permissions do 4 | context 'included in User' do 5 | describe '#permissions' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Struct::Permission' do 8 | permissions = mock_graph :get, 'me/permissions', 'user/permissions', access_token: 'token' do 9 | me.permissions 10 | end 11 | permissions.should be_instance_of FbGraph2::Edge 12 | permissions.should_not be_blank 13 | permissions.each do |permission| 14 | permission.should be_instance_of FbGraph2::Struct::Permission 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/photos_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Photos do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | 7 | describe '#photos' do 8 | it 'should return an Array of FbGraph2::Photo' do 9 | photos = mock_graph :get, 'me/photos', 'user/photos', access_token: 'token' do 10 | me.photos 11 | end 12 | photos.should be_instance_of FbGraph2::Edge 13 | photos.should_not be_blank 14 | photos.each do |photo| 15 | photo.should be_instance_of FbGraph2::Photo 16 | end 17 | end 18 | end 19 | 20 | describe 'photo!' do 21 | it 'should return FbGraph2::Post' do 22 | photo = mock_graph :post, 'me/photos', 'success_with_id', access_token: 'token' do 23 | me.photo! url: 'http://example.com/me.png' 24 | end 25 | photo.should be_instance_of FbGraph2::Photo 26 | photo.id.should == 'created_object_id' 27 | end 28 | end 29 | end 30 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/picture_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Picture do 4 | context 'included in User' do 5 | describe '#picture' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | 8 | it do 9 | mock_graph :get, 'me/picture', 'user/picture', access_token: 'token', params: { 10 | redirect: false 11 | } do 12 | me.picture 13 | end.should be_instance_of FbGraph2::Struct::Picture 14 | end 15 | 16 | context 'when cached' do 17 | let(:me_with_picture) do 18 | mock_graph :get, 'me', 'user/with_picture', access_token: 'token', params: { 19 | fields: 'picture' 20 | } do 21 | me.fetch fields: 'picture' 22 | end 23 | end 24 | 25 | context 'with option params' do 26 | it 'should not use cache' do 27 | mock_graph :get, '579612276/picture', 'user/picture', access_token: 'token', params: { 28 | redirect: false, 29 | type: 'square' 30 | } do 31 | me_with_picture.picture :square 32 | end 33 | end 34 | end 35 | 36 | context 'without option params' do 37 | it 'should use cache' do 38 | expect do 39 | me_with_picture.picture 40 | end.not_to request_to '579612276/picture' 41 | end 42 | end 43 | end 44 | end 45 | end 46 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/pokes_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Pokes do 4 | context 'included in User' do 5 | describe '#pokes' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Struct::Poke' do 8 | pokes = mock_graph :get, 'me/pokes', 'user/pokes', access_token: 'token' do 9 | me.pokes 10 | end 11 | pokes.should be_instance_of FbGraph2::Edge 12 | pokes.should_not be_blank 13 | pokes.each do |poke| 14 | poke.should be_instance_of FbGraph2::Struct::Poke 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/posts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Posts do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | describe '#posts' do 7 | it 'should return an Array of FbGraph2::Post' do 8 | posts = mock_graph :get, 'me/posts', 'user/posts', access_token: 'token' do 9 | me.posts 10 | end 11 | posts.should be_instance_of FbGraph2::Edge 12 | posts.should_not be_blank 13 | posts.each do |post| 14 | post.should be_instance_of FbGraph2::Post 15 | post.message_tags.count.should == 2 16 | end 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/promotable_posts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::PromotablePosts do 4 | context 'included in Page' do 5 | describe '#promotable_posts' do 6 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 7 | it 'should return an Array of FbGraph2::Post' do 8 | posts = mock_graph :get, 'page_id/promotable_posts', 'page/promotable_posts', access_token: 'page_token' do 9 | page.promotable_posts 10 | end 11 | posts.should be_instance_of FbGraph2::Edge 12 | posts.should_not be_blank 13 | posts.each do |post| 14 | post.should be_instance_of FbGraph2::Post 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/ratings_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Ratings do 4 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 5 | 6 | describe '#ratings' do 7 | it 'should return an Array of FbGraph2::Struct::Rating' do 8 | ratings = mock_graph :get, 'page_id/ratings', 'page/ratings', access_token: 'page_token' do 9 | page.ratings 10 | end 11 | ratings.should be_instance_of FbGraph2::Edge 12 | ratings.should_not be_blank 13 | ratings.each do |rating| 14 | rating.should be_instance_of FbGraph2::Struct::Rating 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/fb_graph2/edge/roles_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Roles do 4 | context 'included in App' do 5 | let(:app) { FbGraph2::App.app('app_token') } 6 | 7 | describe '#roles' do 8 | it 'should return an Array of FbGraph2::Struct::Role' do 9 | roles = mock_graph :get, 'app/roles', 'app/roles', access_token: 'app_token' do 10 | app.roles 11 | end 12 | roles.should be_instance_of FbGraph2::Edge 13 | roles.should_not be_blank 14 | roles.each do |role| 15 | role.should be_instance_of FbGraph2::Struct::Role 16 | end 17 | end 18 | end 19 | end 20 | 21 | context 'included in Page' do 22 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 23 | 24 | describe '#roles' do 25 | it 'should return an Array of FbGraph2::User' do 26 | roles = mock_graph :get, 'page_id/roles', 'page/roles', access_token: 'page_token' do 27 | page.roles 28 | end 29 | roles.should be_instance_of FbGraph2::Edge 30 | roles.should_not be_blank 31 | roles.each do |role| 32 | role.should be_instance_of FbGraph2::User 33 | end 34 | end 35 | 36 | context 'when blank' do 37 | it 'should return a blank Array' do 38 | roles = mock_graph :get, 'page_id/roles', 'blank_collection', access_token: 'page_token' do 39 | page.roles 40 | end 41 | roles.should be_instance_of FbGraph2::Edge 42 | roles.should be_blank 43 | end 44 | end 45 | 46 | context 'when user context specified' do 47 | let(:user) { FbGraph2::User.new('user_id') } 48 | 49 | it 'should return a FbGraph2::User' do 50 | role = mock_graph :get, 'page_id/roles/user_id', 'page/roles_single', access_token: 'page_token' do 51 | page.roles user 52 | end 53 | role.should be_instance_of FbGraph2::User 54 | end 55 | 56 | context 'when blank' do 57 | it 'should return nil' do 58 | role = mock_graph :get, 'page_id/roles/user_id', 'blank_collection', access_token: 'page_token' do 59 | page.roles user 60 | end 61 | role.should be_nil 62 | end 63 | end 64 | end 65 | end 66 | end 67 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/scores_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Scores do 4 | context 'included in User' do 5 | describe '#scores' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Struct::Score' do 8 | scores = mock_graph :get, 'me/scores', 'user/scores', access_token: 'token' do 9 | me.scores 10 | end 11 | scores.should be_instance_of FbGraph2::Edge 12 | scores.should_not be_blank 13 | scores.each do |score| 14 | score.should be_instance_of FbGraph2::Struct::Score 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/settings_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Settings do 4 | context 'included in Page' do 5 | describe '#settings' do 6 | let(:page) { FbGraph2::Page.new('page_id').authenticate('page_token') } 7 | it 'should return an Array of FbGraph2::Struct::Permission' do 8 | settings = mock_graph :get, 'page_id/settings', 'page/settings', access_token: 'page_token' do 9 | page.settings 10 | end 11 | settings.should be_instance_of FbGraph2::Edge 12 | settings.should_not be_blank 13 | settings.each do |setting| 14 | setting.should be_instance_of FbGraph2::Struct::Setting 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/shared_posts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::SharedPosts do 4 | context 'included in Post' do 5 | describe '#shared_posts' do 6 | let(:post) { FbGraph2::Post.new('post_id').authenticate('token') } 7 | it 'should return an Array of FbGraph2::Post' do 8 | posts = mock_graph :get, 'post_id/sharedposts', 'post/shared_posts', access_token: 'token' do 9 | post.shared_posts 10 | end 11 | posts.should be_instance_of FbGraph2::Edge 12 | posts.should_not be_blank 13 | posts.each do |post| 14 | post.should be_instance_of FbGraph2::Post 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/subscriptions_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Subscriptions do 4 | context 'included in App' do 5 | describe '#subscriptions' do 6 | let(:app) { FbGraph2::App.app('app_token') } 7 | it 'should return an Array of FbGraph2::Struct::Subscription' do 8 | subscriptions = mock_graph :get, 'app/subscriptions', 'app/subscriptions', access_token: 'app_token' do 9 | app.subscriptions 10 | end 11 | subscriptions.should be_instance_of FbGraph2::Edge 12 | subscriptions.should_not be_blank 13 | subscriptions.each do |subscription| 14 | subscription.should be_instance_of FbGraph2::Struct::Subscription 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/taggable_friends_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::TaggableFriends do 4 | context 'included in User' do 5 | describe '#taggable_friends' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Struct::Friend' do 8 | users = mock_graph :get, 'me/taggable_friends', 'user/taggable_friends', access_token: 'token' do 9 | me.taggable_friends 10 | end 11 | users.should be_instance_of FbGraph2::Edge 12 | users.should_not be_blank 13 | users.each do |user| 14 | user.should be_instance_of FbGraph2::Struct::Friend 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/tagged_places_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::TaggedPlaces do 4 | context 'included in User' do 5 | describe '#tagged_places' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::PlaceTag' do 8 | tags = mock_graph :get, 'me/tagged_places', 'user/tagged_places', access_token: 'token' do 9 | me.tagged_places 10 | end 11 | tags.should be_instance_of FbGraph2::Edge 12 | tags.should_not be_blank 13 | tags.each do |tag| 14 | tag.should be_instance_of FbGraph2::PlaceTag 15 | tag.place.should be_instance_of FbGraph2::Place 16 | tag.place.location.should be_instance_of FbGraph2::Struct::Location 17 | end 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/television_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Television do 4 | context 'included in User' do 5 | describe '#television' do 6 | let(:me) { FbGraph2::User.me('token') } 7 | it 'should return an Array of FbGraph2::Page' do 8 | pages = mock_graph :get, 'me/television', 'user/television', access_token: 'token' do 9 | me.television 10 | end 11 | pages.should be_instance_of FbGraph2::Edge 12 | pages.should_not be_blank 13 | pages.each do |page| 14 | page.should be_instance_of FbGraph2::Page 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /spec/fb_graph2/edge/test_users_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::TestUsers do 4 | context 'included in App' do 5 | let(:app) { FbGraph2::App.app('app_token') } 6 | 7 | describe '#test_users' do 8 | it 'should return an Array of FbGraph2::TestUser with test_user token' do 9 | users = mock_graph :get, 'app/accounts/test-users', 'app/test_users', access_token: 'app_token' do 10 | app.test_users 11 | end 12 | users.should be_instance_of FbGraph2::Edge 13 | users.should_not be_blank 14 | users.each do |user| 15 | user.should be_instance_of FbGraph2::TestUser 16 | user.access_token.should == 'test_user_token' 17 | end 18 | end 19 | end 20 | 21 | describe '#test_user!' do 22 | it 'should create an Object of FbGraph2::TestUser with test_user token' do 23 | permissions = %w[public_profile,email,user_friends].join(',') 24 | user = mock_graph :post, 'app/accounts/test-users', 'post/test_users', access_token: 'app_token', permissions: permissions do 25 | app.test_user! 26 | end 27 | user.should be_instance_of FbGraph2::TestUser 28 | user.access_token.should == 'test_user_token' 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/fb_graph2/edge/videos_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Edge::Videos do 4 | context 'included in User' do 5 | let(:me) { FbGraph2::User.me('token') } 6 | 7 | describe '#videos' do 8 | it 'should return an Array of FbGraph2::Video' do 9 | videos = mock_graph :get, 'me/videos', 'user/videos', access_token: 'token' do 10 | me.videos 11 | end 12 | videos.should be_instance_of FbGraph2::Edge 13 | videos.should_not be_blank 14 | videos.each do |video| 15 | video.should be_instance_of FbGraph2::Video 16 | end 17 | end 18 | end 19 | 20 | describe '#video!' do 21 | it 'skip until webmock support multipart' 22 | # it do 23 | # video = mock_graph :post, 'me/videos', 'success_with_id', access_token: 'token' do 24 | # me.video! source: File.new(__FILE__), message: 'hello' 25 | # end 26 | # video.should be_instance_of FbGraph2::Video 27 | # end 28 | end 29 | end 30 | end -------------------------------------------------------------------------------- /spec/fb_graph2/exception_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Exception do 4 | it 'should properly set its message for inspect' do 5 | err = FbGraph2::Exception.new(400, 'This is the error message') 6 | err.inspect.should == '#' 7 | end 8 | 9 | context 'when response body is given' do 10 | it 'should setup type, error code, and subcode from error' do 11 | err = FbGraph2::Exception.new(400, 'This is the original message', 12 | { 13 | :type => 'SomeError', 14 | :message => 'This is the error message', 15 | :code => 190, 16 | :error_subcode => 460 17 | } 18 | ) 19 | err.status.should == 400 20 | err.type.should == 'SomeError' 21 | err.error_code.should == 190 22 | err.error_subcode.should == 460 23 | end 24 | end 25 | 26 | describe ".detect" do 27 | it 'should detect the appropriate class from the error status' do 28 | [400,401,404,500].each do |error_code| 29 | err = FbGraph2::Exception.detect(error_code, error: { message: "Error #{error_code}"}) 30 | err.class.should == FbGraph2::Exception.detect_from_status(error_code) 31 | end 32 | end 33 | 34 | it 'should detect the appropriate class from headers' do 35 | %w{not_found invalid_token, invalid_request}.each do |error| 36 | header = {"WWW-Authenticate" => "OAuth 'Facebook Platform' '#{error}' Error!"} 37 | err = FbGraph2::Exception.detect('a code', {error: {message: "an error occurred"}}, header) 38 | err.class.should == FbGraph2::Exception.detect_from_header(header, nil) 39 | end 40 | end 41 | 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/fb_graph2/node_subclass_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module FbGraph2 4 | class NodeSubClass < Node 5 | end 6 | end 7 | 8 | describe FbGraph2::NodeSubClass do 9 | it 'should be included in FbGraph2.object_classes' do 10 | FbGraph2.object_classes.should include described_class 11 | end 12 | end -------------------------------------------------------------------------------- /spec/fb_graph2/page_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Page do 4 | context 'with optional fields' do 5 | subject { page } 6 | let(:page) do 7 | attributes = mock_json 'page/with_optional_fields' 8 | FbGraph2::Page.new attributes[:id], attributes 9 | end 10 | 11 | describe '#context' do 12 | subject { page.context } 13 | it { should be_instance_of FbGraph2::Struct::Context::PageContext } 14 | 15 | describe 'friends_who_like' do 16 | subject { page.context.friends_who_like } 17 | it { should be_instance_of FbGraph2::Collection } 18 | it { should be_blank } 19 | its(:total_count) { should == 14 } 20 | its(:summary) { should include :social_sentence } 21 | end 22 | end 23 | 24 | describe '#parking' do 25 | subject { page.parking } 26 | [:street, :lot, :valet].each do |key| 27 | its(key) { should be false } 28 | end 29 | end 30 | 31 | describe '#restaurant_services' do 32 | subject { page.restaurant_services } 33 | [:kids, :delivery, :catering, :waiter, :outdoor, :takeout].each do |key| 34 | its(key) { should be false } 35 | end 36 | [:groups, :reserve, :walkins].each do |key| 37 | its(key) { should be true } 38 | end 39 | end 40 | 41 | describe '#restaurant_specialties' do 42 | subject { page.restaurant_specialties } 43 | [:coffee, :drinks, :breakfast, :lunch].each do |key| 44 | its(key) { should be false } 45 | end 46 | [:dinner].each do |key| 47 | its(key) { should be true } 48 | end 49 | end 50 | 51 | describe '#payment_options' do 52 | subject { page.payment_options } 53 | [:cash_only, :discover].each do |key| 54 | its(key) { should be false } 55 | end 56 | [:amex, :mastercard, :visa].each do |key| 57 | its(key) { should be true } 58 | end 59 | end 60 | end 61 | end -------------------------------------------------------------------------------- /spec/fb_graph2/place_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Place do 4 | subject { described_class } 5 | its(:registered_attributes) { should == FbGraph2::Page.registered_attributes } 6 | end -------------------------------------------------------------------------------- /spec/fb_graph2/request_filter/authenticator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::RequestFilter::Authenticator do 4 | let(:endpoint) { 'https://graph.facebook.com/matake' } 5 | let(:request) { HTTP::Message.new_request(:get, URI.parse(endpoint)) } 6 | let(:request_filter) { described_class.new token } 7 | 8 | context 'when String given' do 9 | let(:token) { 'token' } 10 | it do 11 | request_filter.filter_request(request) 12 | request.header["Authorization"].should == ["Bearer #{token}"] 13 | end 14 | end 15 | 16 | context 'when Rack::OAuth2::AccessToken::Bearer given' do 17 | let(:token) { Rack::OAuth2::AccessToken::Bearer.new access_token: 'token' } 18 | it do 19 | request_filter.filter_request(request) 20 | request.header["Authorization"].should == ["Bearer #{token.access_token}"] 21 | end 22 | end 23 | 24 | context 'when Rack::OAuth2::AccessToken::Legacy given' do 25 | let(:token) { Rack::OAuth2::AccessToken::Legacy.new access_token: 'token' } 26 | it do 27 | request_filter.filter_request(request) 28 | request.header["Authorization"].should == ["OAuth #{token.access_token}"] 29 | end 30 | end 31 | end -------------------------------------------------------------------------------- /spec/fb_graph2/request_filter/debugger_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::RequestFilter::Debugger do 4 | let(:endpoint) { 'https://graph.facebook.com/matake' } 5 | let(:request) { HTTP::Message.new_request(:get, URI.parse(endpoint)) } 6 | let(:response) { HTTP::Message.new_response({:hello => 'world'}.to_json) } 7 | let(:request_filter) { FbGraph2::RequestFilter::Debugger.new } 8 | 9 | describe '#filter_request' do 10 | it 'should log request' do 11 | [ 12 | "======= [FbGraph2] API REQUEST STARTED =======", 13 | request.dump 14 | ].each do |output| 15 | expect(FbGraph2.logger).to receive(:info).with output 16 | end 17 | request_filter.filter_request(request) 18 | end 19 | end 20 | 21 | describe '#filter_response' do 22 | it 'should log response' do 23 | [ 24 | "--------------------------------------------------", 25 | response.dump, 26 | "======= [FbGraph2] API REQUEST FINISHED =======" 27 | ].each do |output| 28 | expect(FbGraph2.logger).to receive(:info).with output 29 | end 30 | request_filter.filter_response(request, response) 31 | end 32 | end 33 | end -------------------------------------------------------------------------------- /spec/fb_graph2/searchable_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Searchable do 4 | describe 'search' do 5 | context 'User' do 6 | it 'should return users' do 7 | users = mock_graph :get, 'search', 'search/user', access_token: 'token', params: { 8 | q: 'nov.matake', 9 | type: 'user' 10 | } do 11 | FbGraph2::User.search 'nov.matake', 'token' 12 | end 13 | users.should be_instance_of FbGraph2::Searchable::Result 14 | users.should_not be_empty 15 | users.each do |user| 16 | user.should be_instance_of FbGraph2::User 17 | end 18 | end 19 | end 20 | end 21 | 22 | describe 'pagination' do 23 | context 'when first page' do 24 | let :page1 do 25 | mock_graph :get, 'search', 'search/user', access_token: 'token', params: { 26 | q: 'nov.matake', 27 | type: 'user' 28 | } do 29 | FbGraph2::User.search 'nov.matake', 'token' 30 | end 31 | end 32 | 33 | it 'should have next' do 34 | mock_graph :get, 'search', 'blank_collection', access_token: 'token', params: { 35 | q: 'nov.matake', 36 | type: 'user', 37 | __after_id: 'enc_AeyyBJc7uo9gY-nHN9-LM0yG_IKBN5nCmqdkG8b4Ql-COLTnpQ-2NUc-xSDK6VwPhsq2W9Ktnr0zf7dD25Bc9eKT', 38 | limit: 5000, 39 | offset: 5000 40 | } do 41 | page1.next 42 | end 43 | end 44 | 45 | it 'should have no previous' do 46 | page1.previous.should be_blank 47 | end 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /spec/fb_graph2/struct/app_insight_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Struct::AppInsight do 4 | let(:app_insight) do 5 | FbGraph2::Struct::AppInsight.new( 6 | time: '2015-07-13T08:00:00+0000', 7 | value: '3' 8 | ) 9 | end 10 | subject { app_insight } 11 | 12 | its(:time) { should == Time.parse('2015-07-13T08:00:00+0000') } 13 | its(:value) { should == '3' } 14 | end 15 | -------------------------------------------------------------------------------- /spec/fb_graph2/struct/app_link_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Struct::AppLink do 4 | subject { described_class } 5 | its(:registered_attributes) { should == {raw: [:url]} } 6 | 7 | describe FbGraph2::Struct::AppLink::Native do 8 | its(:registered_attributes) { should == {raw: [:url, :app_name]} } 9 | end 10 | 11 | describe FbGraph2::Struct::AppLink::Native::IOS do 12 | its(:registered_attributes) { should == {raw: [:url, :app_name, :app_store_id]} } 13 | end 14 | 15 | describe FbGraph2::Struct::AppLink::Native::Android do 16 | its(:registered_attributes) { should == {raw: [:url, :app_name, :package], custom: [:klass]} } 17 | end 18 | 19 | describe FbGraph2::Struct::AppLink::Native::WindowsPhone do 20 | its(:registered_attributes) { should == {raw: [:url, :app_name, :app_id]} } 21 | end 22 | 23 | describe FbGraph2::Struct::AppLink::Web do 24 | its(:registered_attributes) { should == {raw: [:url, :should_fallback]} } 25 | end 26 | end -------------------------------------------------------------------------------- /spec/fb_graph2/tagged_profile_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::TaggedProfile do 4 | describe '.initialize' do 5 | { 6 | user: FbGraph2::User, 7 | page: FbGraph2::Page, 8 | event: FbGraph2::Event, 9 | application: FbGraph2::App, 10 | unknown: FbGraph2::Node 11 | }.each do |type, klass| 12 | context "when type=#{type}" do 13 | it "should return instances of the #{klass}" do 14 | tag = FbGraph2::TaggedProfile.new(1, type: type.to_s) 15 | expect(tag.object).to be_a klass 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/fb_graph2/test_user_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::TestUser do 4 | let(:app) { FbGraph2::App.app('app_token') } 5 | 6 | let(:test_user) do 7 | permissions = %w[public_profile,email,user_friends].join(',') 8 | mock_graph :post, 'app/accounts/test-users', 'post/test_users', access_token: 'app_token', permissions: permissions do 9 | app.test_user! 10 | end 11 | end 12 | 13 | describe '#access_token' do 14 | it 'should provide the TestUser access token' do 15 | test_user.access_token.should == 'test_user_token' 16 | end 17 | end 18 | 19 | describe '#password' do 20 | it 'should provide the new test user password' do 21 | test_user.password.should == 'test_user_password' 22 | end 23 | end 24 | 25 | describe '#login_url' do 26 | it 'should provide the new test user login_url' do 27 | test_user.login_url.should == 'https://developers.facebook.com/checkpoint/test-user-login/106444709796298/' 28 | end 29 | end 30 | 31 | describe '#friend!' do 32 | let(:test_friend) { FbGraph2::TestUser.new('123456789') } 33 | 34 | it 'should request and confirm the friendship for the given test user' do 35 | mock_graph :post, "#{test_user.id}/friends/#{test_friend.id}", 'success_true', access_token: test_user.access_token 36 | mock_graph :post, "#{test_friend.id}/friends/#{test_user.id}", 'success_true', access_token: test_friend.access_token 37 | test_user.friend!(test_friend) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/fb_graph2/token_metadata_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::TokenMetadata do 4 | let(:app_token) do 5 | attributes = mock_json 'token_metadata/app_token' 6 | FbGraph2::TokenMetadata.new attributes[:data] 7 | end 8 | let(:user_token) do 9 | attributes = mock_json 'token_metadata/user_token' 10 | FbGraph2::TokenMetadata.new attributes[:data] 11 | end 12 | let(:page_token) do 13 | attributes = mock_json 'token_metadata/page_token' 14 | FbGraph2::TokenMetadata.new attributes[:data] 15 | end 16 | let(:invalid_token) do 17 | attributes = mock_json 'token_metadata/invalid_token' 18 | FbGraph2::TokenMetadata.new attributes[:data] 19 | end 20 | 21 | context 'when app_token' do 22 | subject { app_token } 23 | its(:app_token?) { should == true } 24 | its(:user_token?) { should == false } 25 | its(:page_token?) { should == false } 26 | end 27 | 28 | context 'when user_token' do 29 | subject { user_token } 30 | its(:app_token?) { should == false } 31 | its(:user_token?) { should == true } 32 | its(:page_token?) { should == false } 33 | end 34 | 35 | context 'when page_token' do 36 | subject { page_token } 37 | its(:app_token?) { should == false } 38 | its(:user_token?) { should == false } 39 | its(:page_token?) { should == true } 40 | end 41 | 42 | context 'when valid' do 43 | subject { user_token } 44 | its(:valid?) { should == true } 45 | end 46 | 47 | context 'when invalid' do 48 | subject { invalid_token } 49 | its(:valid?) { should == false } 50 | end 51 | end -------------------------------------------------------------------------------- /spec/fb_graph2/user_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::User do 4 | describe '.me' do 5 | it 'should not call API' do 6 | expect do 7 | me = described_class.me 'token' 8 | me.should be_instance_of described_class 9 | end.not_to request_to 'me' 10 | end 11 | 12 | context 'when fetched' do 13 | it 'should call API' do 14 | me = mock_graph :get, 'me', 'user/me' do 15 | described_class.me('token').fetch 16 | end 17 | me.should be_instance_of described_class 18 | end 19 | 20 | context 'when ext attrs included' do 21 | it 'should success to parse' do 22 | me = mock_graph :get, 'me', 'user/me_with_ext_attrs' do 23 | described_class.me('token').fetch 24 | end 25 | [ 26 | :age_range, :context, :currency, :devices 27 | ].each do |key| 28 | me.send(key).should be_present 29 | end 30 | end 31 | end 32 | end 33 | end 34 | end -------------------------------------------------------------------------------- /spec/fb_graph2/util_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2::Util do 4 | describe '.as_identifier' do 5 | context 'when FbGraph2::Node given' do 6 | it do 7 | FbGraph2::Util.as_identifier( 8 | FbGraph2::Node.new 'object_id' 9 | ).should == 'object_id' 10 | end 11 | end 12 | 13 | context 'when String given' do 14 | it do 15 | FbGraph2::Util.as_identifier('object_id').should == 'object_id' 16 | end 17 | end 18 | 19 | context 'when FbGraph2::Struct::Permission given' do 20 | it do 21 | FbGraph2::Util.as_identifier( 22 | FbGraph2::Struct::Permission.new(permission: 'permission_name', granted: true) 23 | ).should == 'permission_name' 24 | end 25 | end 26 | end 27 | end -------------------------------------------------------------------------------- /spec/fb_graph2_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe FbGraph2 do 4 | subject { FbGraph2 } 5 | after { FbGraph2.debugging = false } 6 | 7 | context 'as default' do 8 | its(:logger) { should be_a Logger } 9 | its(:api_version) { should == 'v7.0' } 10 | its(:root_url) { should == 'https://graph.facebook.com' } 11 | it { should_not be_debugging } 12 | end 13 | 14 | describe '.debug!' do 15 | before { FbGraph2.debug! } 16 | it { should be_debugging } 17 | end 18 | 19 | describe '.http_client' do 20 | context 'with http_config' do 21 | before do 22 | FbGraph2.http_config do |config| 23 | config.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE 24 | config.connect_timeout = 30 25 | config.send_timeout = 40 26 | config.receive_timeout = 60 27 | end 28 | end 29 | 30 | it 'should configure Rack::OAuth2 and FbGraph2 http_client' do 31 | [Rack::OAuth2, FbGraph2].each do |klass| 32 | klass.http_client.ssl_config.verify_mode.should == OpenSSL::SSL::VERIFY_NONE 33 | klass.http_client.connect_timeout.should == 30 34 | klass.http_client.send_timeout.should == 40 35 | klass.http_client.receive_timeout.should == 60 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/mock_json/app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "category": "Business", 3 | "daily_active_users": "10000", 4 | "daily_active_users_rank": 1215, 5 | "description": "A tool to help browse objects within the Facebook Graph API, manage permissions, obtain access tokens and learn how it all works.", 6 | "icon_url": "https://fbcdn-photos-a-a.akamaihd.net/hphotos-ak-xpa1/t39.2081-0/851576_646264348772288_612357246_n.png", 7 | "link": "https://www.facebook.com/apps/application.php?id=145634995501895", 8 | "logo_url": "https://fbcdn-photos-a-a.akamaihd.net/hphotos-ak-xpa1/t39.2081-0/p75x75/851563_646263475439042_787584105_n.png", 9 | "monthly_active_users": "500000", 10 | "monthly_active_users_rank": 432, 11 | "name": "Graph API Explorer", 12 | "subcategory": "General", 13 | "weekly_active_users": "100000", 14 | "id": "145634995501895" 15 | } -------------------------------------------------------------------------------- /spec/mock_json/app/app_link_hosts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": "804327549686491", 5 | "canonical_url": "https://fb.me/804327549686491" 6 | } 7 | ], 8 | "paging": { 9 | "cursors": { 10 | "before": "ODA0MzI3NTQ5Njg2NDkx", 11 | "after": "ODA0MzI3NTQ5Njg2NDkx" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /spec/mock_json/app/banned.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "100003934202581", 4 | "name": "Open Graph Test User" 5 | }], 6 | "paging": { 7 | "cursors": { 8 | "before": "MTAwMDAzOTM0MjAyNTgx", 9 | "after": "MTAwMDAzOTM0MjAyNTgx" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /spec/mock_json/app/roles.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "app_id": "210798282372757", 4 | "user": "579612276", 5 | "role": "administrators" 6 | }], 7 | "paging": { 8 | "next": "https://graph.facebook.com/v2.1/210798282372757/roles?limit=5000&offset=5000&__after_id=enc_AezKeljwOb-ajJmD2AAQnxKG4ppLUt__oG9ScW9Um9PcjIxWf1zs1-LbrM8skz4rDAVCAQxs3SO_-GeS6OnwPJNA" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/mock_json/app/subscriptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "object": "user", 4 | "callback_url": "http://fbgraphsample.heroku.com/subscriptions/7", 5 | "fields": ["email"], 6 | "active": true 7 | }] 8 | } 9 | -------------------------------------------------------------------------------- /spec/mock_json/app/test_users.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "100003934202581", 4 | "login_url": "https://developers.facebook.com/checkpoint/test-user-login/100003934202581/", 5 | "access_token": "test_user_token" 6 | }, { 7 | "id": "100003888272508", 8 | "login_url": "https://developers.facebook.com/checkpoint/test-user-login/100003888272508/", 9 | "access_token": "test_user_token" 10 | }], 11 | "paging": { 12 | "cursors": { 13 | "before": "MTAwMDAzOTM0MjAyNTgx", 14 | "after": "MTAwMDAzODg4MjcyNTA4" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/blank_collection.json: -------------------------------------------------------------------------------- 1 | {"data":[]} -------------------------------------------------------------------------------- /spec/mock_json/conversation/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": "m_mid.1427484003966:6a7d41f350be02b202", 5 | "created_time": "2015-03-27T19:20:04+0000", 6 | "tags": { 7 | "data": [ 8 | {"name": "inbox"}, 9 | {"name": "source:web"} 10 | ] 11 | }, 12 | "from": { 13 | "name": "Bryan Brunetti", 14 | "email": "123456\u0040facebook.com", 15 | "id": "643757367" 16 | }, 17 | "to": { 18 | "data": [ 19 | { 20 | "name": "Desk Three", 21 | "email": "775794712516982\u0040facebook.com", 22 | "id": "775794712516982" 23 | } 24 | ] 25 | }, 26 | "message": "testing a message" 27 | } 28 | ], 29 | "paging": { 30 | "previous": "https:\/\/graph.facebook.com\/v2.0\/t_mid.1426199405718:7ed3d5c7813b41e484\/messages?limit=25&since=1427484004&__paging_token=enc_AdBRZAAMNJk6afsV9fngFvUvCruCFRtYbsQjQDUFCYEd4CHjwrXUD33IkK80S68qMg8IO8YWa5cZB5n8KbZBLbMQXZCPFOyYoobd2Ij11bvI6PywwAZDZD&__previous=1", 31 | "next": "https:\/\/graph.facebook.com\/v2.0\/t_mid.1426199405718:7ed3d5c7813b41e484\/messages?limit=25&until=1426199405&__paging_token=enc_AdD0AeYOoGBAn90kScirgzHTxGTnZCBaHYH5fDk2ESd90FesTLZAas06iG6NqMjTecoIAzs20zsfL4fmREIkC1HD0nSZA6E9TqF1aju7UYRDh7GgAZDZD" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /spec/mock_json/error/400/191.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "Missing redirect_uri parameter.", 4 | "type": "OAuthException", 5 | "code": 191 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /spec/mock_json/error/400/2500.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "An active access token must be used to query information about the current user.", 4 | "type": "OAuthException", 5 | "code": 2500 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /spec/mock_json/error/invalid_format.json: -------------------------------------------------------------------------------- 1 | NOT FOUND -------------------------------------------------------------------------------- /spec/mock_json/event/attending.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Akira Otaishi", 4 | "rsvp_status": "attending", 5 | "id": "553375548107883" 6 | }, { 7 | "name": "Shin-ichiro Kagaya", 8 | "rsvp_status": "attending", 9 | "id": "241546062702044" 10 | }], 11 | "paging": { 12 | "cursors": { 13 | "after": "TVRBd01EQXdNRFl6TWpjME1qSTBPakUwTVRBMU1UQTJNREE2TVRZMU1EZzBPRGsyT0RRNE5UZ3g=", 14 | "before": "TVRBd01EQXpNRFl6TWpjM01qTXhPakUwTVRBMU1UQTJNREE2TVRjMk9UQTRNVE0xTmpnM09UWXg=" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/event/declined.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Akira Otaishi", 4 | "rsvp_status": "attending", 5 | "id": "553375548107883" 6 | }, { 7 | "name": "Shin-ichiro Kagaya", 8 | "rsvp_status": "attending", 9 | "id": "241546062702044" 10 | }], 11 | "paging": { 12 | "cursors": { 13 | "after": "TVRBd01EQXdNRFl6TWpjME1qSTBPakUwTVRBMU1UQTJNREE2TVRZMU1EZzBPRGsyT0RRNE5UZ3g=", 14 | "before": "TVRBd01EQXpNRFl6TWpjM01qTXhPakUwTVRBMU1UQTJNREE2TVRjMk9UQTRNVE0xTmpnM09UWXg=" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/event/maybe.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Akira Otaishi", 4 | "rsvp_status": "attending", 5 | "id": "553375548107883" 6 | }, { 7 | "name": "Shin-ichiro Kagaya", 8 | "rsvp_status": "attending", 9 | "id": "241546062702044" 10 | }], 11 | "paging": { 12 | "cursors": { 13 | "after": "TVRBd01EQXdNRFl6TWpjME1qSTBPakUwTVRBMU1UQTJNREE2TVRZMU1EZzBPRGsyT0RRNE5UZ3g=", 14 | "before": "TVRBd01EQXpNRFl6TWpjM01qTXhPakUwTVRBMU1UQTJNREE2TVRjMk9UQTRNVE0xTmpnM09UWXg=" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/event/noreply.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Akira Otaishi", 4 | "rsvp_status": "attending", 5 | "id": "553375548107883" 6 | }, { 7 | "name": "Shin-ichiro Kagaya", 8 | "rsvp_status": "attending", 9 | "id": "241546062702044" 10 | }], 11 | "paging": { 12 | "cursors": { 13 | "after": "TVRBd01EQXdNRFl6TWpjME1qSTBPakUwTVRBMU1UQTJNREE2TVRZMU1EZzBPRGsyT0RRNE5UZ3g=", 14 | "before": "TVRBd01EQXpNRFl6TWpjM01qTXhPakUwTVRBMU1UQTJNREE2TVRjMk9UQTRNVE0xTmpnM09UWXg=" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/group/members.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "name": "Hayashi Tatsuya", 5 | "administrator": false, 6 | "id": "10152167763779825" 7 | }, 8 | { 9 | "name": "Ryo Ito", 10 | "administrator": false, 11 | "id": "10203204372262716" 12 | }, 13 | { 14 | "name": "Nov Matake", 15 | "administrator": true, 16 | "id": "579612276" 17 | } 18 | ], 19 | "paging": { 20 | "next": "https://graph.facebook.com/v2.1/343659285716553/members?limit=5000&offset=5000&__after_id=***" 21 | } 22 | } -------------------------------------------------------------------------------- /spec/mock_json/page/admins.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Nov Matake", 4 | "role": "MANAGER", 5 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"], 6 | "id": "10152411392127277" 7 | }], 8 | "paging": { 9 | "next": "https://graph.facebook.com/v2.0/140478125968442/admins?limit=5000&offset=5000&__after_id=enc_AewHp5mZW0v4ZorlBTo4lsBccesXKfIJsKvOM-Qb268XDhHwKtZnhOhNwXWSun5KdHE" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/mock_json/page/block_succeeded.json: -------------------------------------------------------------------------------- 1 | { 2 | "user_id": true 3 | } -------------------------------------------------------------------------------- /spec/mock_json/page/blocked.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Jr Nov", 4 | "id": "1575327134" 5 | }], 6 | "paging": { 7 | "next": "https://graph.facebook.com/v2.0/117513961602338/blocked?limit=5000&offset=5000&__after_id=enc_AewU3hSo5zqbS5KA0i0lJYmPrLn57SMSo645aYB7BTPg1PSawPvlM9mRI_3Y_dcpeDI" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /spec/mock_json/page/milestones.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "546071975451512", 4 | "created_time": "2013-07-05T02:04:43+0000", 5 | "description": "Big Guest from MIT-KIT", 6 | "end_time": "2013-06-26T19:00:00+0000", 7 | "from": { 8 | "category": "Community", 9 | "name": "Identity Conference #idcon", 10 | "id": "367989543259757" 11 | }, 12 | "start_time": "2013-06-26T19:00:00+0000", 13 | "title": "idcon satellite", 14 | "updated_time": "2013-07-05T02:04:43+0000" 15 | }], 16 | "paging": { 17 | "next": "https://graph.facebook.com/v2.0/367989543259757/milestones?limit=5000&offset=5000&__after_id=enc_Aex6DrtZcpP_AZjou_LFSynIQJzuO-LR4zoj2GU-WQO3StnFciL5I6GVJ2Nlj5-6C50JJSpZnn5O-zkuPXcU4DAC" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spec/mock_json/page/offers.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "797106500309744", 4 | "from": { 5 | "category": "Software", 6 | "name": "FbGraph", 7 | "id": "117513961602338" 8 | }, 9 | "title": "Foobar", 10 | "created_time": "2014-09-02T09:56:14+0000", 11 | "expiration_time": "2014-09-12T14:59:59+0000", 12 | "image_url": "https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-xap1\/v\/t1.0-1\/p200x200\/12758_485082394845491_483124061_n.png?oh=ffdf2fc204852be4167eebaeb7f1b2ec&oe=54733980&__gda__=1415926027_bbf6edaad90b94e23268131e6d8f258b", 13 | "claim_limit": 1000000000, 14 | "coupon_type": "in_store_only" 15 | }], 16 | "paging": { 17 | "next": "https:\/\/graph.facebook.com\/v2.0\/117513961602338\/offers?limit=50&offset=50&__after_id=enc_Aey48t-R5OQbq6nWOeyBEJKEHiddR7mdWX_5Pg0nBoVbmDoe_Lr4d_5XIg4vhahIQ7oFJzHsY8P91oMo_GD_ZrNy" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spec/mock_json/page/promotable_posts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "140478125968442_881790788503835", 4 | "from": { 5 | "category": "Community organization", 6 | "name": "OAuth.jp", 7 | "id": "140478125968442" 8 | }, 9 | "story": "OAuth.jp shared a link.", 10 | "story_tags": [{ 11 | "id": "140478125968442", 12 | "name": "OAuth.jp", 13 | "offset": 0, 14 | "length": 8, 15 | "type": "page" 16 | }], 17 | "link": "http://oauth.jp/blog/2014/05/09/what-happens-when-oauth2-code-leaked/", 18 | "name": "OAuth 2.0 の code は漏れても大丈夫ってホント!? - OAuth.jp", 19 | "caption": "oauth.jp", 20 | "description": "昨日のCovert Redirect で Query 漏れるケースもある!?やOAuth 2.0 の脆弱性 (!?) “Covert Redirect” とはにあるように、OAuth 2.0 の code が漏れちゃうことも、ありえます。 漏れないためにやるべきことは、 …", 21 | "icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif", 22 | "actions": [{ 23 | "name": "Comment", 24 | "link": "https://www.facebook.com/140478125968442/posts/881790788503835" 25 | }, { 26 | "name": "Like", 27 | "link": "https://www.facebook.com/140478125968442/posts/881790788503835" 28 | }], 29 | "privacy": { 30 | "description": "Public", 31 | "value": "EVERYONE", 32 | "friends": "", 33 | "networks": "", 34 | "allow": "", 35 | "deny": "" 36 | }, 37 | "type": "link", 38 | "status_type": "shared_story", 39 | "created_time": "2014-05-09T02:18:54+0000", 40 | "updated_time": "2014-05-09T02:18:54+0000", 41 | "is_published": true, 42 | "likes": { 43 | "data": [{ 44 | "id": "799980330042786", 45 | "name": "Nobuyuki Tetsuka" 46 | }, { 47 | "id": "671955032839764", 48 | "name": "Naohiro Fujie" 49 | }, { 50 | "id": "514441882016076", 51 | "name": "Shouji Ohara" 52 | }], 53 | "paging": { 54 | "cursors": { 55 | "after": "NTE0NDQxODgyMDE2MDc2", 56 | "before": "Nzk5OTgwMzMwMDQyNzg2" 57 | } 58 | } 59 | } 60 | }], 61 | "paging": { 62 | "previous": "https://graph.facebook.com/v2.0/140478125968442/promotable_posts?limit=25&since=1399601934", 63 | "next": "https://graph.facebook.com/v2.0/140478125968442/promotable_posts?limit=25&until=1340970652" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /spec/mock_json/page/ratings.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "created_time": "2014-10-13T02:04:49+0000", 5 | "reviewer": { 6 | "id": "10206374744997522", 7 | "name": "Shigeru Takagaki" 8 | }, 9 | "rating": 5 10 | }, 11 | { 12 | "created_time": "2014-07-09T13:39:31+0000", 13 | "reviewer": { 14 | "id": "585838138182211", 15 | "name": "Teruko Kaneshiro" 16 | }, 17 | "rating": 5 18 | }, 19 | { 20 | "created_time": "2013-11-10T08:21:29+0000", 21 | "reviewer": { 22 | "id": "10152917500568292", 23 | "name": "Lyn Yeoh" 24 | }, 25 | "rating": 5 26 | }, 27 | { 28 | "created_time": "2013-07-08T11:28:20+0000", 29 | "reviewer": { 30 | "id": "10152167763779825", 31 | "name": "Hayashi Tatsuya" 32 | }, 33 | "rating": 5 34 | } 35 | ], 36 | "paging": { 37 | "cursors": { 38 | "before": "MTUzNDY1MDA1NzoxMzkyOTYxMDYwOTU4Mjk=", 39 | "after": "NzcyNjg5ODI0OjEzOTI5NjEwNjA5NTgyOQ==" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /spec/mock_json/page/roles.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10101078259835569", 4 | "name": "Micah Wedemeyer", 5 | "role": "Admin", 6 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"] 7 | }, { 8 | "id": "579612276", 9 | "name": "Nov Matake", 10 | "role": "Admin", 11 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"] 12 | }], 13 | "paging": { 14 | "cursors": { 15 | "before": "MTAxMDEwNzgyNTk4MzU1Njk=", 16 | "after": "NTc5NjEyMjc2" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spec/mock_json/page/roles_single.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "579612276", 4 | "name": "Nov Matake", 5 | "role": "Admin", 6 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"] 7 | }], 8 | "paging": { 9 | "cursors": { 10 | "before": "MTAxMDEwNzgyNTk4MzU1Njk=", 11 | "after": "NTc5NjEyMjc2" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/mock_json/page/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "setting": "USERS_CAN_POST", 5 | "value": true 6 | }, 7 | { 8 | "setting": "USERS_CAN_MESSAGE", 9 | "value": true 10 | }, 11 | { 12 | "setting": "USERS_CAN_POST_PHOTOS", 13 | "value": true 14 | }, 15 | { 16 | "setting": "USERS_CAN_TAG_PHOTOS", 17 | "value": false 18 | }, 19 | { 20 | "setting": "WALL_COMBINED_POSTS", 21 | "value": true 22 | }, 23 | { 24 | "setting": "PLATFORM_OPTOUTS_CAN_POST", 25 | "value": true 26 | }, 27 | { 28 | "setting": "SHOW_RECENT_POSTS_BY_OTHERS", 29 | "value": true 30 | }, 31 | { 32 | "setting": "APPEARS_IN_RELATED_PAGES", 33 | "value": true 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /spec/mock_json/page/with_optional_fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "friends_who_like": { 4 | "data": [], 5 | "summary": { 6 | "social_sentence": "14 of your friends like this.", 7 | "total_count": 14 8 | } 9 | } 10 | }, 11 | "parking": { 12 | "lot": 0, 13 | "street": 0, 14 | "valet": 0 15 | }, 16 | "restaurant_services": { 17 | "delivery": 0, 18 | "catering": 0, 19 | "groups": 1, 20 | "kids": 0, 21 | "outdoor": 0, 22 | "reserve": 1, 23 | "takeout": 0, 24 | "waiter": 0, 25 | "walkins": 1 26 | }, 27 | "restaurant_specialties": { 28 | "breakfast": 0, 29 | "coffee": 0, 30 | "dinner": 1, 31 | "drinks": 0, 32 | "lunch": 0 33 | }, 34 | "payment_options": { 35 | "amex": 1, 36 | "cash_only": 0, 37 | "discover": 0, 38 | "mastercard": 1, 39 | "visa": 1 40 | }, 41 | "id": "139296106095829" 42 | } 43 | -------------------------------------------------------------------------------- /spec/mock_json/post/comments.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10152461220962277_10152461646087277", 4 | "from": { 5 | "id": "789665437731725", 6 | "name": "Toyoaki Ohgochi" 7 | }, 8 | "message": "....ポイントも付きますよ....", 9 | "can_remove": true, 10 | "created_time": "2014-05-24T15:05:57+0000", 11 | "like_count": 0, 12 | "user_likes": false 13 | }], 14 | "paging": { 15 | "cursors": { 16 | "after": "MQ==", 17 | "before": "MQ==" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /spec/mock_json/post/comments_with_summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10152662663892277_10152662666892277", 4 | "from": { 5 | "id": "579612276", 6 | "name": "Nov Matake" 7 | }, 8 | "message": "hummm, it's not \"post\"...", 9 | "can_remove": true, 10 | "created_time": "2014-08-20T05:34:21+0000", 11 | "like_count": 0, 12 | "user_likes": false 13 | }, { 14 | "id": "10152662663892277_10152662686952277", 15 | "from": { 16 | "id": "579612276", 17 | "name": "Nov Matake" 18 | }, 19 | "message": "579612276_10152662663892277 = post\n10152662663892277 = status", 20 | "can_remove": true, 21 | "created_time": "2014-08-20T05:57:11+0000", 22 | "like_count": 0, 23 | "user_likes": false 24 | }, { 25 | "id": "10152662663892277_10152662687272277", 26 | "from": { 27 | "id": "579612276", 28 | "name": "Nov Matake" 29 | }, 30 | "message": "でも多分v2.1完成してない。 http://stackoverflow.com/questions/25270649/facebook-graph-api-v2-1-all-post-photos", 31 | "can_remove": true, 32 | "created_time": "2014-08-20T05:57:31+0000", 33 | "like_count": 0, 34 | "user_likes": false 35 | }, { 36 | "id": "10152662663892277_10152662687387277", 37 | "from": { 38 | "id": "579612276", 39 | "name": "Nov Matake" 40 | }, 41 | "message": "完成さしてからだせや!!", 42 | "can_remove": true, 43 | "created_time": "2014-08-20T05:57:48+0000", 44 | "like_count": 0, 45 | "user_likes": false 46 | }], 47 | "paging": { 48 | "cursors": { 49 | "after": "NA==", 50 | "before": "MQ==" 51 | } 52 | }, 53 | "summary": { 54 | "order": "chronological", 55 | "total_count": 4 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /spec/mock_json/post/liked_and_commented.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "579612276_10152473646047277", 3 | "from": { 4 | "id": "579612276", 5 | "name": "Nov Matake" 6 | }, 7 | "message": "test", 8 | "actions": [{ 9 | "name": "Comment", 10 | "link": "https://www.facebook.com/579612276/posts/10152473646047277" 11 | }, { 12 | "name": "Like", 13 | "link": "https://www.facebook.com/579612276/posts/10152473646047277" 14 | }], 15 | "privacy": { 16 | "description": "Your friends", 17 | "value": "ALL_FRIENDS", 18 | "friends": "", 19 | "networks": "", 20 | "allow": "", 21 | "deny": "" 22 | }, 23 | "type": "status", 24 | "status_type": "mobile_status_update", 25 | "created_time": "2014-05-30T06:13:26+0000", 26 | "updated_time": "2014-05-30T06:13:30+0000", 27 | "likes": { 28 | "data": [{ 29 | "id": "579612276", 30 | "name": "Nov Matake" 31 | }], 32 | "paging": { 33 | "cursors": { 34 | "after": "NTc5NjEyMjc2", 35 | "before": "NTc5NjEyMjc2" 36 | } 37 | } 38 | }, 39 | "comments": { 40 | "data": [{ 41 | "id": "10152473646047277_10152473646112277", 42 | "from": { 43 | "id": "579612276", 44 | "name": "Nov Matake" 45 | }, 46 | "message": "test", 47 | "can_remove": true, 48 | "created_time": "2014-05-30T06:13:30+0000", 49 | "like_count": 0, 50 | "user_likes": false 51 | }], 52 | "paging": { 53 | "cursors": { 54 | "after": "MQ==", 55 | "before": "MQ==" 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /spec/mock_json/post/likes.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "689134294485152", 4 | "name": "Shunya Iriki" 5 | }, { 6 | "id": "1486426304903512", 7 | "name": "Masato Nagai" 8 | }], 9 | "paging": { 10 | "cursors": { 11 | "after": "MTQ4NjQyNjMwNDkwMzUxMg==", 12 | "before": "Njg5MTM0Mjk0NDg1MTUy" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spec/mock_json/post/shared_posts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "689134294485152_695439827187932", 4 | "from": { 5 | "id": "689134294485152", 6 | "name": "Shunya Iriki" 7 | }, 8 | "story": "Shunya Iriki shared a link.", 9 | "story_tags": [{ 10 | "id": "689134294485152", 11 | "name": "Shunya Iriki", 12 | "offset": 0, 13 | "length": 12, 14 | "type": "user" 15 | }], 16 | "picture": "https://fbexternal-a.akamaihd.net/safe_image.php?d=AQCtEdPdezKIoUxo&w=154&h=154&url=http%3A%2F%2Fi.yimg.jp%2Fi%2Fdocs%2Frelease%2Ffbicon.jpg", 17 | "link": "http://docs.yahoo.co.jp/docs/info/terms/chapter1.html#cf2nd", 18 | "name": "ヤフー株式会社 - サービス利用規約 第1編 基本ガイドライン", 19 | "caption": "docs.yahoo.co.jp", 20 | "description": "Yahoo! JAPANのサービス利用規約、第1編 基本ガイドラインは当社のサービスをご利用になるすべての方に共通して適用されます。", 21 | "icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif", 22 | "actions": [{ 23 | "name": "Comment", 24 | "link": "https://www.facebook.com/100001657627507/posts/695439827187932" 25 | }, { 26 | "name": "Like", 27 | "link": "https://www.facebook.com/100001657627507/posts/695439827187932" 28 | }], 29 | "privacy": { 30 | "value": "" 31 | }, 32 | "type": "link", 33 | "status_type": "shared_story", 34 | "application": { 35 | "name": "Facebook for iPhone", 36 | "namespace": "fbiphone", 37 | "id": "6628568379" 38 | }, 39 | "created_time": "2014-06-02T12:46:26+0000", 40 | "updated_time": "2014-06-02T12:46:26+0000" 41 | }], 42 | "paging": { 43 | "cursors": { 44 | "after": "Njk1NDM5ODI3MTg3OTMy", 45 | "before": "Njk1NDM5ODI3MTg3OTMy" 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /spec/mock_json/post/test_users.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "106444709796298", 3 | "login_url": "https://developers.facebook.com/checkpoint/test-user-login/106444709796298/", 4 | "email": "hhndcqu_bowerssky_1469002228@tfbnw.net", 5 | "password": "test_user_password", 6 | "access_token": "test_user_token" 7 | } 8 | -------------------------------------------------------------------------------- /spec/mock_json/search/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Nov Matake", 4 | "id": "426118390869327" 5 | }], 6 | "paging": { 7 | "next": "https:\/\/graph.facebook.com\/v2.0\/search?type=user&q=nov.matake&limit=5000&offset=5000&__after_id=enc_AeyyBJc7uo9gY-nHN9-LM0yG_IKBN5nCmqdkG8b4Ql-COLTnpQ-2NUc-xSDK6VwPhsq2W9Ktnr0zf7dD25Bc9eKT" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /spec/mock_json/success_true.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true 3 | } -------------------------------------------------------------------------------- /spec/mock_json/success_with_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "created_object_id" 3 | } 4 | -------------------------------------------------------------------------------- /spec/mock_json/token_metadata/app_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "app_id": "210798282372757", 4 | "is_valid": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /spec/mock_json/token_metadata/invalid_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "error": { 4 | "message": "Error validating access token: This may be because the user logged out or may be due to a system error.", 5 | "code": 190, 6 | "subcode": 467 7 | }, 8 | "app_id": "210798282372757", 9 | "is_valid": false, 10 | "application": "gem sample", 11 | "user_id": "579612276", 12 | "expires_at": 1409655600, 13 | "scopes": ["public_profile", "basic_info", "read_stream", "read_mailbox", "read_page_mailboxes", "rsvp_event", "email", "ads_management", "ads_read", "read_insights", "manage_notifications", "read_friendlists", "manage_pages", "publish_actions", "user_birthday", "user_religion_politics", "user_relationships", "user_relationship_details", "user_hometown", "user_location", "user_likes", "user_activities", "user_interests", "user_education_history", "user_work_history", "user_website", "user_groups", "user_events", "user_photos", "user_videos", "user_friends", "user_about_me", "user_status", "user_games_activity", "user_tagged_places", "user_actions.books", "user_actions.music", "user_actions.video", "user_actions.news"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spec/mock_json/token_metadata/page_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "app_id": "210798282372757", 4 | "is_valid": true, 5 | "profile_id": "367989543259757", 6 | "application": "gem sample", 7 | "user_id": "579612276", 8 | "expires_at": 1416996000, 9 | "scopes": ["public_profile", "basic_info", "read_stream"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/mock_json/token_metadata/user_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "app_id": "210798282372757", 4 | "is_valid": true, 5 | "application": "gem sample", 6 | "user_id": "579612276", 7 | "expires_at": 1416992400, 8 | "scopes": ["public_profile", "basic_info", "read_stream"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/mock_json/token_response.json: -------------------------------------------------------------------------------- 1 | access_token=access_token&expires=5183975 -------------------------------------------------------------------------------- /spec/mock_json/true.json: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /spec/mock_json/user/accounts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Community", 4 | "name": "Identity Conference #idcon", 5 | "access_token": "page_token", 6 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"], 7 | "id": "367989543259757" 8 | }, { 9 | "category": "Community organization", 10 | "name": "OAuth.jp", 11 | "access_token": "page_token", 12 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"], 13 | "id": "140478125968442" 14 | }, { 15 | "category": "Non-profit organization", 16 | "name": "OpenID Foundation Japan", 17 | "access_token": "page_token", 18 | "perms": ["ADMINISTER", "EDIT_PROFILE", "CREATE_CONTENT", "MODERATE_CONTENT", "CREATE_ADS", "BASIC_ADMIN"], 19 | "id": "157574337644417" 20 | }], 21 | "paging": { 22 | "next": "https:\/\/graph.facebook.com\/v2.0\/579612276\/accounts?limit=5000&offset=5000&__after_id=enc_AeyErLVKPOCVAXiRThtd3kSkz__A4QR6eZWAQTTTWw-QCDtft_TmuaKhPOxK_I993BKoO1VIgoyXIAd72ZZNYvrw" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spec/mock_json/user/achievements.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10150407675002277", 4 | "from": { 5 | "id": "579612276", 6 | "name": "Nov Matake" 7 | }, 8 | "start_time": "2011-11-09T08:04:58+0000", 9 | "end_time": "2011-11-09T08:04:58+0000", 10 | "publish_time": "2011-11-09T08:04:58+0000", 11 | "application": { 12 | "name": "gem sample", 13 | "namespace": "fbgraphsample", 14 | "id": "134145643294322" 15 | }, 16 | "data": { 17 | "achievement": { 18 | "id": "10150310611431721", 19 | "url": "http://fbgraphsample.heroku.com/achievements/1", 20 | "type": "game.achievement", 21 | "title": "1st Achievement" 22 | } 23 | }, 24 | "type": "games.achieves", 25 | "no_feed_story": false, 26 | "likes": { 27 | "count": 0, 28 | "can_like": true, 29 | "user_likes": false 30 | }, 31 | "comments": { 32 | "count": 0, 33 | "can_comment": true, 34 | "comment_order": "chronological" 35 | } 36 | }], 37 | "paging": { 38 | "next": "https://graph.facebook.com/v2.0/579612276/achievements?limit=25&offset=25&__after_id=enc_AeyhCSdwSdwIMz2Kbpibnp2MZgYC1gasXThstsCJgxJdxwL9V_ss1OPBDnrxUgpTqAe1QOHjq-un-45-IJXJFrLv" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /spec/mock_json/user/activities.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Interest", 4 | "name": "Mobile Hack Tokyo", 5 | "created_time": "2012-03-01T00:30:09+0000", 6 | "id": "253431701402959" 7 | }, { 8 | "category": "Software", 9 | "name": "Rack::OAuth2", 10 | "created_time": "2011-06-23T10:32:47+0000", 11 | "id": "141477809244105" 12 | }, { 13 | "category": "Non-profit organization", 14 | "name": "OpenID Foundation Japan", 15 | "created_time": "2011-06-23T04:53:40+0000", 16 | "id": "157574337644417" 17 | }, { 18 | "category": "Internet/software", 19 | "name": "SocialWeb Japan", 20 | "created_time": "2011-04-26T04:54:13+0000", 21 | "id": "150730961633" 22 | }, { 23 | "category": "Community organization", 24 | "name": "OAuth.jp", 25 | "created_time": "2011-01-05T00:27:02+0000", 26 | "id": "140478125968442" 27 | }, { 28 | "category": "Software", 29 | "name": "FbGraph", 30 | "created_time": "2010-04-30T06:48:21+0000", 31 | "id": "117513961602338" 32 | }], 33 | "paging": { 34 | "next": "https://graph.facebook.com/v2.0/579612276/activities?limit=25&offset=25&__after_id=enc_AewISXs8Uhe2pwegtVsWC8GFmzAWEKKFzGcJoZ-UJa4MA_wFfCIRKFaQMJkS6U5WTdiSKw3G3EvlyDir1upNCBop" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spec/mock_json/user/albums.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "532912916729105", 4 | "from": { 5 | "category": "Software", 6 | "name": "FbGraph", 7 | "id": "117513961602338" 8 | }, 9 | "name": "Timeline Photos", 10 | "link": "https://www.facebook.com/album.php?fbid=532912916729105&id=117513961602338&aid=116544", 11 | "privacy": "everyone", 12 | "type": "wall", 13 | "created_time": "2013-02-16T13:23:10+0000", 14 | "updated_time": "2013-02-16T13:23:10+0000", 15 | "can_upload": false 16 | }], 17 | "paging": { 18 | "cursors": { 19 | "after": "MjEwNDcxNDkyMzA2NTg0", 20 | "before": "NTMyOTEyOTE2NzI5MTA1" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spec/mock_json/user/books.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Book", 4 | "name": "Predictably Irrational", 5 | "created_time": "2011-07-27T15:49:06+0000", 6 | "id": "113167718696752" 7 | }], 8 | "paging": { 9 | "next": "https://graph.facebook.com/v2.0/579612276/books?limit=25&offset=25&__after_id=enc_AewjHX22qV_-BoIxoRMWHPno7BxZHunbqYgaxlHlJnH0x_Gza1bYpFD6V7Vve1HL-21x7kD5E_3QMLzdjM9pmK_f" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/mock_json/user/events.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "name": "Test Event", 5 | "start_time": "2014-06-13T19:00:00+0900", 6 | "timezone": "Asia/Tokyo", 7 | "location": "六本木", 8 | "rsvp_status": "attending", 9 | "id": "246996708819160" 10 | } 11 | ], 12 | "paging": { 13 | "previous": "https://graph.facebook.com/v2.0/579612276/events?limit=25&since=1402653600&__paging_token=***", 14 | "next": "https://graph.facebook.com/v2.0/579612276/events?limit=25&until=1402653600&__paging_token=***" 15 | } 16 | } -------------------------------------------------------------------------------- /spec/mock_json/user/friend_lists.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10152338362087277", 4 | "name": "CyberAgent America", 5 | "list_type": "work" 6 | }, { 7 | "id": "10152338362072277", 8 | "name": "Cerego Japan", 9 | "list_type": "work" 10 | }, { 11 | "id": "10152142419302277", 12 | "name": "Capy Inc.", 13 | "list_type": "work" 14 | }, { 15 | "id": "10151887848997277", 16 | "name": "Cerego Japan", 17 | "list_type": "work" 18 | }, { 19 | "id": "10151870113532277", 20 | "name": "Kyoto CtoG.org", 21 | "list_type": "work" 22 | }, { 23 | "id": "10150348660692277", 24 | "name": "同志社大学", 25 | "list_type": "education" 26 | }, { 27 | "id": "10150346113542277", 28 | "name": "Kawasaki-shi, Kanagawa, Japan Area", 29 | "list_type": "current_city" 30 | }, { 31 | "id": "10150346085662277", 32 | "name": "OpenID Foundation", 33 | "list_type": "work" 34 | }, { 35 | "id": "10150346074892277", 36 | "name": "OpenID Foundation Japan", 37 | "list_type": "work" 38 | }, { 39 | "id": "10150341935447277", 40 | "name": "株式会社ドリコム", 41 | "list_type": "work" 42 | }, { 43 | "id": "10150336745462277", 44 | "name": "Kyoto CtoG.org", 45 | "list_type": "work" 46 | }, { 47 | "id": "10150336745457277", 48 | "name": "Acquaintances", 49 | "list_type": "acquaintances" 50 | }, { 51 | "id": "10150336744357277", 52 | "name": "ドリコム", 53 | "list_type": "work" 54 | }, { 55 | "id": "10150336526382277", 56 | "name": "Doshisha University", 57 | "list_type": "education" 58 | }, { 59 | "id": "10150336526227277", 60 | "name": "Doshisha High School", 61 | "list_type": "education" 62 | }, { 63 | "id": "10150336526222277", 64 | "name": "Cerego Japan", 65 | "list_type": "work" 66 | }, { 67 | "id": "10150336526217277", 68 | "name": "Family", 69 | "list_type": "family" 70 | }, { 71 | "id": "10150336526212277", 72 | "name": "Close Friends", 73 | "list_type": "close_friends" 74 | }, { 75 | "id": "10150287189437277", 76 | "name": "Family", 77 | "list_type": "user_created" 78 | }, { 79 | "id": "494503307276", 80 | "name": "OpenStack", 81 | "list_type": "user_created" 82 | }, { 83 | "id": "41968037276", 84 | "name": "Doshisha", 85 | "list_type": "user_created" 86 | }, { 87 | "id": "41967672276", 88 | "name": "iKnow!", 89 | "list_type": "user_created" 90 | }, { 91 | "id": "41967622276", 92 | "name": "Drecom", 93 | "list_type": "user_created" 94 | }], 95 | "paging": { 96 | "next": "https://graph.facebook.com/v2.0/579612276/friendlists?limit=5000&offset=5000&__after_id=enc_AeyvnVCKex4_AhqGX7_QdptE11EjyFPx0CGxMGyRHvxS2SbnqjP7fJD8tL2VFjeodZA" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /spec/mock_json/user/friends.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "Nat Sakimura", 4 | "id": "1048138174" 5 | }, { 6 | "name": "Yusuke Kondo", 7 | "id": "1229826130" 8 | }, { 9 | "name": "Yuya Ito", 10 | "id": "1326792131" 11 | }, { 12 | "name": "Tatsuya Katsuhara", 13 | "id": "1784765822" 14 | }], 15 | "paging": { 16 | "next": "https://graph.facebook.com/v2.0/579612276/friends?limit=5000&offset=5000&__after_id=enc_AexFQ6mn3PA35psWD5WjFNzW7ovDp35_gkApd8tXqRmc5ygEBBAEs56d3YIetOc9NNk" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /spec/mock_json/user/groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "name": "OpenID Connect Hackathon", 4 | "administrator": true, 5 | "bookmark_order": 14, 6 | "id": "562322927125681" 7 | }, { 8 | "name": "OAuth.jp", 9 | "administrator": true, 10 | "bookmark_order": 12, 11 | "id": "343659285716553" 12 | }], 13 | "paging": { 14 | "next": "https://graph.facebook.com/v2.0/579612276/groups?icon_size=16&limit=5000&offset=5000&__after_id=enc_AeynOYwetNSbegZQTbjirpNPayS9oqujy9wnu0CnNjC7YMl4zxLq-JP--CRz3FX3KWg" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spec/mock_json/user/interests.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Interest", 4 | "name": "#idcon 14th ~ BYOResume or DEAD! ~", 5 | "created_time": "2012-09-03T17:18:16+0000", 6 | "id": "309562105809363" 7 | }, { 8 | "category": "Interest", 9 | "name": "Heroku Meetup #6 Japan Heroku Lab", 10 | "created_time": "2012-09-03T03:07:14+0000", 11 | "id": "102424793243222" 12 | }, { 13 | "category": "Interest", 14 | "name": "Activity Streams", 15 | "created_time": "2011-06-30T22:57:47+0000", 16 | "id": "114998808528822" 17 | }, { 18 | "category": "Company", 19 | "name": "Social Web", 20 | "created_time": "2011-06-18T02:52:35+0000", 21 | "id": "105645299472577" 22 | }, { 23 | "category": "Interest", 24 | "name": "Open ID", 25 | "created_time": "2011-01-05T00:21:56+0000", 26 | "id": "106260522746492" 27 | }, { 28 | "category": "Interest", 29 | "name": "Open Social", 30 | "created_time": "2011-01-05T00:21:52+0000", 31 | "id": "107119605991729" 32 | }, { 33 | "category": "Interest", 34 | "name": "OAuth", 35 | "created_time": "2010-07-04T06:17:52+0000", 36 | "id": "104064209632570" 37 | }], 38 | "paging": { 39 | "next": "https://graph.facebook.com/v2.0/579612276/interests?limit=25&offset=25&__after_id=enc_AezLYldJHiKEyShbuOdR82cv0TtL4DwoXvFHvxocLB9dyJjlw96DIz3jwBNiERXgDjzAH_sT_ZhHU9QGJNxiOe3P" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /spec/mock_json/user/invitable_friends.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "AVm6afobc20T0wATmCYRk_CNymo_44MQW8yMBwpgDFAQ18iF9feZpDEDmwfmcjSBSSuYkFfD5fx77g_uJRF0fmQ7AR2kObX8biP4wzN7UMpbYQ", 4 | "name": "Shingo Yamanaka", 5 | "picture": { 6 | "data": { 7 | "is_silhouette": false, 8 | "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpf1/t1.0-1/c0.15.85.85/s50x50/1468668_10152037195781416_2050550170_s.jpg" 9 | } 10 | } 11 | }, { 12 | "id": "AVnJiIlmAtrWJ106ErRPlLZNy8_Hd4mfmuQBrbGm4tuFS_ENvyYdVxTwgesXE5Wp2ICtxcPHzkA4Y4BJAWwJqyUie2ZDKQeKn9mnjPCVAUr8Lg", 13 | "name": "Hayashi Tatsuya", 14 | "picture": { 15 | "data": { 16 | "is_silhouette": false, 17 | "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xaf1/t1.0-1/c79.38.479.479/s50x50/388771_10150501378984825_523522119_n.jpg" 18 | } 19 | } 20 | }], 21 | "paging": { 22 | "cursors": { 23 | "before": "QVZra09GaExkNndsM1J5eVpuQ2dWS1hLV3FBb0dqRTh3dC1PVXJIZE8ya0JzbV9kUDZXcWZEdUtUZFNHejcxeGlWZ3JjZjZjdkIwMWdtSWtHZGpGVE8wTWZ5cUdNUm5NWWw3c2hSTEtPZ19ySmc=", 24 | "after": "QVZrdlNsUHItNExPY1JIUVdlZ3BDZlFCTHFFMUl6YVhnVG5fRVlBLVV0QThUMFBmRnZNQkVQWVg2VkRBQWhRa3RyemVQUFhscWxBVERYZU15SExZbG50Z0RTQUtfVno5VjRjT3VUb2J5NGg1VFE=" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spec/mock_json/user/likes.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Business/economy website", 4 | "name": "デザイナーズSOHOオフィスなら【SOHO東京】", 5 | "created_time": "2014-04-27T07:42:29+0000", 6 | "id": "140108926038346" 7 | }, { 8 | "category": "Real estate", 9 | "category_list": [{ 10 | "id": "198327773511962", 11 | "name": "Real Estate" 12 | }], 13 | "name": "ジョイライフスタイル", 14 | "created_time": "2014-04-05T15:26:28+0000", 15 | "id": "117500321741291" 16 | }, { 17 | "category": "Internet/software", 18 | "category_list": [{ 19 | "id": "2256", 20 | "name": "Internet/Software" 21 | }], 22 | "name": "Engineerrise", 23 | "created_time": "2014-03-28T14:32:31+0000", 24 | "id": "565244630160593" 25 | }], 26 | "paging": { 27 | "cursors": { 28 | "after": "MzY3OTg5NTQzMjU5NzU3", 29 | "before": "MTQwMTA4OTI2MDM4MzQ2" 30 | }, 31 | "next": "https://graph.facebook.com/v2.0/579612276/likes?limit=25&after=MzY3OTg5NTQzMjU5NzU3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /spec/mock_json/user/me_with_ext_attrs.json: -------------------------------------------------------------------------------- 1 | { 2 | "age_range": { 3 | "min": 21 4 | }, 5 | "context": { 6 | "mutual_friends": { 7 | "data": [], 8 | "summary": { 9 | "total_count": 245 10 | } 11 | }, 12 | "mutual_likes": { 13 | "data": [{ 14 | "category": "Product/service", 15 | "name": "GSMA Mobile World Congress", 16 | "id": "177607143648" 17 | }, { 18 | "category": "Business/economy website", 19 | "name": "デザイナーズSOHOオフィスなら【SOHO東京】", 20 | "id": "140108926038346" 21 | }, { 22 | "category": "Real estate", 23 | "category_list": [{ 24 | "id": "198327773511962", 25 | "name": "Real Estate" 26 | }], 27 | "name": "ジョイライフスタイル", 28 | "id": "117500321741291" 29 | }, { 30 | "category": "Internet/software", 31 | "category_list": [{ 32 | "id": "10101472279007861", 33 | "name": "Internet/Software" 34 | }], 35 | "name": "Engineerrise", 36 | "id": "565244630160593" 37 | }, { 38 | "category": "Electronics", 39 | "name": "Rapiro", 40 | "id": "124199987785627" 41 | }], 42 | "paging": { 43 | "next": "https://graph.facebook.com/v2.0/579612276?pretty=1&fields=context.fields(mutual_likes.limit(5).after(MTI0MTk5OTg3Nzg1NjI3))", 44 | "cursors": { 45 | "before": "MTc3NjA3MTQzNjQ4", 46 | "after": "MTI0MTk5OTg3Nzg1NjI3" 47 | } 48 | }, 49 | "summary": { 50 | "total_count": 89 51 | } 52 | } 53 | }, 54 | "currency": { 55 | "currency_offset": 1, 56 | "usd_exchange": 0.0097614, 57 | "usd_exchange_inverse": 102.4443215113, 58 | "user_currency": "JPY" 59 | }, 60 | "devices": [{ 61 | "hardware": "iPhone", 62 | "os": "iOS" 63 | }], 64 | "id": "579612276" 65 | } 66 | -------------------------------------------------------------------------------- /spec/mock_json/user/movies.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Movie", 4 | "name": "The Social Network", 5 | "created_time": "2011-01-05T00:17:17+0000", 6 | "id": "105460422821089" 7 | }], 8 | "paging": { 9 | "next": "https://graph.facebook.com/v2.0/579612276/movies?limit=25&offset=25&__after_id=enc_AewDz_Z8KNKb51zhWhUMYOJjref9qTPZpk1jT2P9sAXIzWmNSJSUU56XyMbJASE2c8qPbE1-WoFS8o6eCgs6K4Ui" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/mock_json/user/music.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Music", 4 | "name": "斉藤和義", 5 | "created_time": "2011-07-31T05:30:44+0000", 6 | "id": "108827045813193" 7 | }, { 8 | "category": "Musician/band", 9 | "name": "L'arc~en~Ciel", 10 | "created_time": "2011-07-31T05:28:30+0000", 11 | "id": "12039028077" 12 | }, { 13 | "category": "Musician/band", 14 | "name": "Utada Hikaru", 15 | "created_time": "2010-05-10T06:57:25+0000", 16 | "id": "105806242793688" 17 | }, { 18 | "category": "Musician/band", 19 | "category_list": [{ 20 | "id": "180164648685982", 21 | "name": "Bands & Musicians" 22 | }], 23 | "name": "Avril Lavigne", 24 | "created_time": "2009-01-22T18:03:07+0000", 25 | "id": "5413509299" 26 | }, { 27 | "category": "Musician/band", 28 | "name": "Bank Band", 29 | "created_time": "2009-01-22T17:47:26+0000", 30 | "id": "28534671472" 31 | }, { 32 | "category": "Musician/band", 33 | "name": "The Yellow Monkey", 34 | "created_time": "2009-01-22T17:36:46+0000", 35 | "id": "32548904409" 36 | }, { 37 | "category": "Musician/band", 38 | "name": "Mr. Children", 39 | "created_time": "2009-01-22T17:36:26+0000", 40 | "id": "27868140174" 41 | }], 42 | "paging": { 43 | "next": "https://graph.facebook.com/v2.0/579612276/music?limit=25&offset=25&__after_id=enc_AeyVKBfCEuM8ZXcswQ4tW_IGxEZSp9qkwAdtOM37T5EWpk1I8POJ2Kn5tSqM2lWyx0Q" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spec/mock_json/user/picture.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfp1/t1.0-1/p50x50/1621886_836472406369007_1319645706_t.jpg", 4 | "is_silhouette": false 5 | } 6 | } -------------------------------------------------------------------------------- /spec/mock_json/user/pokes.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "to": { 4 | "id": "579612276", 5 | "name": "Nov Matake" 6 | }, 7 | "from": { 8 | "id": "10203783534727236", 9 | "name": "Taizo Matsuoka" 10 | }, 11 | "created_time": "2014-06-03T09:01:25+0000" 12 | }], 13 | "paging": { 14 | "previous": "https://graph.facebook.com/v2.0/579612276/pokes?limit=25&since=1401786085", 15 | "next": "https://graph.facebook.com/v2.0/579612276/pokes?limit=25&until=1401786085" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/mock_json/user/posts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "579612276_10152483324277277", 4 | "from": { 5 | "id": "579612276", 6 | "name": "Nov Matake" 7 | }, 8 | "to": { 9 | "data": [{ 10 | "id": "579612276", 11 | "name": "Nov Matake" 12 | }] 13 | }, 14 | "message": "Nov Matake test", 15 | "message_tags": { 16 | "0": [ 17 | { 18 | "id": "579612276", 19 | "name": "Nov Matake", 20 | "type": "user", 21 | "offset": 0, 22 | "length": 10 23 | } 24 | ], 25 | "11": [ 26 | { 27 | "id": "10153177366617368", 28 | "name": "Bryan Brunetti", 29 | "type": "user", 30 | "offset": 11, 31 | "length": 14 32 | } 33 | ] 34 | }, 35 | "actions": [{ 36 | "name": "Comment", 37 | "link": "https://www.facebook.com/579612276/posts/10152483324277277" 38 | }, { 39 | "name": "Like", 40 | "link": "https://www.facebook.com/579612276/posts/10152483324277277" 41 | }], 42 | "privacy": { 43 | "description": "Your friends", 44 | "value": "ALL_FRIENDS", 45 | "friends": "", 46 | "networks": "", 47 | "allow": "", 48 | "deny": "" 49 | }, 50 | "type": "status", 51 | "status_type": "mobile_status_update", 52 | "created_time": "2014-06-03T06:27:21+0000", 53 | "updated_time": "2014-06-03T06:27:21+0000" 54 | }], 55 | "paging": { 56 | "previous": "https://graph.facebook.com/v2.0/579612276/posts?limit=1&since=1401776841", 57 | "next": "https://graph.facebook.com/v2.0/579612276/posts?limit=1&until=1401776840" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /spec/mock_json/user/scores.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "user": { 4 | "id": "10152411392127277", 5 | "name": "Nov Matake" 6 | }, 7 | "score": 10, 8 | "application": { 9 | "name": "gem sample", 10 | "namespace": "fbgraphsample", 11 | "id": "134145643294322" 12 | } 13 | }] 14 | } 15 | -------------------------------------------------------------------------------- /spec/mock_json/user/taggable_friends.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "AVm6afobc20T0wATmCYRk_CNymo_44MQW8yMBwpgDFAQ18iF9feZpDEDmwfmcjSBSSuYkFfD5fx77g_uJRF0fmQ7AR2kObX8biP4wzN7UMpbYQ", 4 | "name": "Shingo Yamanaka", 5 | "picture": { 6 | "data": { 7 | "is_silhouette": false, 8 | "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpf1/t1.0-1/c0.15.85.85/s50x50/1468668_10152037195781416_2050550170_s.jpg" 9 | } 10 | } 11 | }, { 12 | "id": "AVnJiIlmAtrWJ106ErRPlLZNy8_Hd4mfmuQBrbGm4tuFS_ENvyYdVxTwgesXE5Wp2ICtxcPHzkA4Y4BJAWwJqyUie2ZDKQeKn9mnjPCVAUr8Lg", 13 | "name": "Hayashi Tatsuya", 14 | "picture": { 15 | "data": { 16 | "is_silhouette": false, 17 | "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xaf1/t1.0-1/c79.38.479.479/s50x50/388771_10150501378984825_523522119_n.jpg" 18 | } 19 | } 20 | }], 21 | "paging": { 22 | "cursors": { 23 | "before": "QVZra09GaExkNndsM1J5eVpuQ2dWS1hLV3FBb0dqRTh3dC1PVXJIZE8ya0JzbV9kUDZXcWZEdUtUZFNHejcxeGlWZ3JjZjZjdkIwMWdtSWtHZGpGVE8wTWZ5cUdNUm5NWWw3c2hSTEtPZ19ySmc=", 24 | "after": "QVZrdlNsUHItNExPY1JIUVdlZ3BDZlFCTHFFMUl6YVhnVG5fRVlBLVV0QThUMFBmRnZNQkVQWVg2VkRBQWhRa3RyemVQUFhscWxBVERYZU15SExZbG50Z0RTQUtfVno5VjRjT3VUb2J5NGg1VFE=" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /spec/mock_json/user/television.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "category": "Tv show", 4 | "name": "Mobile Suit Zeta Gundam", 5 | "created_time": "2014-06-03T06:08:35+0000", 6 | "id": "105508046150348" 7 | }], 8 | "paging": { 9 | "next": "https://graph.facebook.com/v2.0/579612276/television?limit=25&offset=25&__after_id=enc_AewK-s0422fW15xZjOu3LxDtrkej8NQumXBW2ugVt3EuK52YArNQIKzoyq72k0V_vQ3_DGUsIp7COPzF82p_h4BK" 10 | } 11 | } -------------------------------------------------------------------------------- /spec/mock_json/user/videos.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "id": "10150407695537277", 4 | "from": { 5 | "category": "Software", 6 | "name": "FbGraph", 7 | "id": "117513961602338" 8 | }, 9 | "name": "Testing Video Upload!", 10 | "description": "Testing Video Upload!!!!", 11 | "picture": "https://fbcdn-vthumb-a.akamaihd.net/hvthumb-ak-xap1/t15.0-10/51203_10150407695802277_10150407695537277_13346_258_t.jpg", 12 | "embed_html": "", 13 | "icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/DggDhA4z4tO.gif", 14 | "source": "https://fbcdn-video-a.akamaihd.net/hvideo-ak-xap1/v/t43.1792-2/1205675_10151804645367277_61538_n.mp4?oh=d78d7d5854d1614376ca0358b15b9f54&oe=538F750B&__gda__=1401907382_f5c3b44cfea781601e4caed9eca55002", 15 | "created_time": "2011-11-09T08:31:28+0000", 16 | "updated_time": "2011-11-09T08:31:28+0000", 17 | "format": [{ 18 | "embed_html": "", 19 | "width": 130, 20 | "height": 98, 21 | "filter": "130x130", 22 | "picture": "https://fbcdn-vthumb-a.akamaihd.net/hvthumb-ak-xap1/t15.0-10/s130x130/51203_10150407695802277_10150407695537277_13346_258_t.jpg" 23 | }, { 24 | "embed_html": "", 25 | "width": 480, 26 | "height": 360, 27 | "filter": "480x480", 28 | "picture": "https://fbcdn-vthumb-a.akamaihd.net/hvthumb-ak-xap1/t15.0-10/s480x480/51203_10150407695802277_10150407695537277_13346_258_b.jpg" 29 | }, { 30 | "embed_html": "", 31 | "width": 640, 32 | "height": 480, 33 | "filter": "native", 34 | "picture": "https://fbcdn-vthumb-a.akamaihd.net/hvthumb-ak-xap1/t15.0-10/51203_10150407695802277_10150407695537277_13346_258_b.jpg" 35 | }] 36 | }], 37 | "paging": { 38 | "previous": "https://graph.facebook.com/v2.0/117513961602338/videos?limit=25&since=1320827488", 39 | "next": "https://graph.facebook.com/v2.0/117513961602338/videos?limit=25&until=1308369661" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /spec/mock_json/user/with_picture.json: -------------------------------------------------------------------------------- 1 | { 2 | "picture": { 3 | "data": { 4 | "is_silhouette": false, 5 | "url": "https://scontent.xx.fbcdn.net/hprofile-xaf1/v/l/t1.0-1/c47.47.587.587/s50x50/480315_10151515065267277_840234863_n.jpg?oh=6935fc39f4807b6f30c741d721ce766e&oe=56639F81" 6 | } 7 | }, 8 | "id": "579612276" 9 | } -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | 3 | SimpleCov.start do 4 | add_filter 'spec' 5 | end 6 | 7 | require 'rspec' 8 | require 'rspec/its' 9 | require 'fb_graph2' 10 | 11 | RSpec.configure do |config| 12 | config.expect_with :rspec do |c| 13 | c.syntax = [:should, :expect] 14 | end 15 | end 16 | 17 | Dir[File.join(__dir__, 'spec_helper/*.rb')].each do |file| 18 | require file 19 | end -------------------------------------------------------------------------------- /spec/spec_helper/mock_graph.rb: -------------------------------------------------------------------------------- 1 | require 'webmock/rspec' 2 | 3 | module MockGraph 4 | def mock_graph(method, path, response_path, options = {}) 5 | stub_request( 6 | method, 7 | endpoint_for(path, options) 8 | ).with( 9 | request_for(method, options) 10 | ).to_return( 11 | response_for(response_path, options) 12 | ) 13 | if block_given? 14 | response = yield 15 | a_request( 16 | method, 17 | endpoint_for(path, options) 18 | ).with( 19 | request_for(method, options) 20 | ).should have_been_made.once 21 | response 22 | end 23 | end 24 | 25 | def mock_json(response_path) 26 | content = response_for(response_path)[:body].read 27 | MultiJson.load(content).with_indifferent_access 28 | rescue MultiJson::DecodeError 29 | content 30 | end 31 | 32 | def request_to(path, method = :get, options = {}) 33 | raise_error { |e| 34 | e.should be_instance_of WebMock::NetConnectNotAllowedError 35 | e.message.should include("Unregistered request: #{method.to_s.upcase}") 36 | e.message.should include(endpoint_for path, options) 37 | } 38 | end 39 | 40 | private 41 | 42 | def endpoint_for(path, options = {}) 43 | api_version = unless options[:disable_api_versioning] 44 | options[:api_version] || FbGraph2.api_version 45 | end 46 | File.join FbGraph2.root_url, api_version.to_s, path 47 | end 48 | 49 | def request_for(method, options = {}) 50 | request = {} 51 | if options[:access_token] 52 | request[:headers] ||= {} 53 | request[:headers] = { 54 | authorization: "Bearer #{options[:access_token]}" 55 | } 56 | end 57 | params = options.try(:[], :params) || {} 58 | case method 59 | when :post, :put, :delete 60 | request[:body] = params 61 | else 62 | request[:query] = params 63 | end 64 | request 65 | end 66 | 67 | def response_for(response_path, options = {}) 68 | response = {} 69 | response[:body] = response_file_for response_path 70 | if options[:status] 71 | response[:status] = options[:status] 72 | end 73 | response 74 | end 75 | 76 | def response_file_for(response_path) 77 | _response_file_path_ = if File.exist? response_path 78 | response_path 79 | else 80 | File.join( 81 | File.dirname(__FILE__), '../mock_json', "#{response_path}.json" 82 | ) 83 | end 84 | unless File.exist? _response_file_path_ 85 | response_file_required! _response_file_path_ 86 | end 87 | File.new _response_file_path_, 'r', encoding: 'utf-8' 88 | end 89 | 90 | def response_file_required!(response_path) 91 | warn 'No response file found.' 92 | end 93 | end 94 | 95 | include MockGraph 96 | WebMock.disable_net_connect! --------------------------------------------------------------------------------