share_checker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/Gemfile +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +41 -0
  4. data/Rakefile +25 -0
  5. data/lib/share_checker.rb +40 -0
  6. data/lib/share_checker/config.rb +38 -0
  7. data/lib/share_checker/provider.rb +48 -0
  8. data/lib/share_checker/providers/facebook.rb +32 -0
  9. data/lib/share_checker/providers/odnoklassniki.rb +18 -0
  10. data/lib/share_checker/providers/tweetracker.rb +35 -0
  11. data/lib/share_checker/providers/twitter.rb +23 -0
  12. data/lib/share_checker/providers/vkontakte.rb +21 -0
  13. data/lib/share_checker/version.rb +3 -0
  14. data/spec/dummy/Rakefile +7 -0
  15. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  16. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  17. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  18. data/spec/dummy/config.ru +4 -0
  19. data/spec/dummy/config/application.rb +45 -0
  20. data/spec/dummy/config/boot.rb +10 -0
  21. data/spec/dummy/config/database.yml +22 -0
  22. data/spec/dummy/config/environment.rb +5 -0
  23. data/spec/dummy/config/environments/development.rb +26 -0
  24. data/spec/dummy/config/environments/production.rb +49 -0
  25. data/spec/dummy/config/environments/test.rb +35 -0
  26. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  27. data/spec/dummy/config/initializers/inflections.rb +10 -0
  28. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  29. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  30. data/spec/dummy/config/initializers/session_store.rb +8 -0
  31. data/spec/dummy/config/locales/en.yml +5 -0
  32. data/spec/dummy/config/routes.rb +58 -0
  33. data/spec/dummy/db/test.sqlite3 +0 -0
  34. data/spec/dummy/log/development.log +0 -0
  35. data/spec/dummy/log/production.log +0 -0
  36. data/spec/dummy/log/server.log +0 -0
  37. data/spec/dummy/log/test.log +91 -0
  38. data/spec/dummy/public/404.html +26 -0
  39. data/spec/dummy/public/422.html +26 -0
  40. data/spec/dummy/public/500.html +26 -0
  41. data/spec/dummy/public/favicon.ico +0 -0
  42. data/spec/dummy/public/javascripts/application.js +2 -0
  43. data/spec/dummy/public/javascripts/controls.js +965 -0
  44. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  45. data/spec/dummy/public/javascripts/effects.js +1123 -0
  46. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  47. data/spec/dummy/public/javascripts/rails.js +191 -0
  48. data/spec/dummy/script/rails +6 -0
  49. data/spec/integration/navigation_spec.rb +9 -0
  50. data/spec/providers/facebook_spec.rb +25 -0
  51. data/spec/providers/odnoklassniki_spec.rb +12 -0
  52. data/spec/providers/tweetracker_spec.rb +12 -0
  53. data/spec/providers/twitter_spec.rb +12 -0
  54. data/spec/providers/vkontakte_spec.rb +12 -0
  55. data/spec/share_checker_spec.rb +42 -0
  56. data/spec/spec_helper.rb +33 -0
  57. metadata +220 -0
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "3.0.10"
4
+ gem "capybara", ">= 0.4.0"
5
+ gem "sqlite3"
6
+
7
+ gem "nokogiri"
8
+ gem "json"
9
+ gem "curb"
10
+
11
+ gem "rspec-rails", "~> 2.6.1"
12
+
13
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
14
+ # gem 'ruby-debug'
15
+ # gem 'ruby-debug19'
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Aimbulance
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ = ShareChecker
2
+
3
+ The easiest way to check how many times a URL has been shared on Twitter, Facebook, Vkontakte and Odnoklassniki.
4
+
5
+ == Install
6
+
7
+ gem 'share_checker'
8
+
9
+ == Configure
10
+
11
+ ShareChecker.setup do |config|
12
+ config.vkontakte = { :app_id => 00000 }
13
+ end
14
+
15
+ == Usage
16
+
17
+ Supported providers: twitter, facebook, vkontakte and odnoklassniki:
18
+
19
+ ShareChecker.check("facebook", "SHARED_URL")
20
+
21
+ ShareChecker::Providers::Twitter.new("SHARED_URL").check
22
+
23
+ Overwride default options:
24
+
25
+ ShareChecker.check("vkontakte", "SHARED_URL", { :app_id => 00001 })
26
+
27
+ == Dependences
28
+
29
+ * {curb}[https://github.com/taf2/curb]
30
+
31
+ sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev
32
+
33
+ * {nokogiri}[http://nokogiri.org/]
34
+ * {json}[http://flori.github.com/json/]
35
+ * {active_support}[https://rubygems.org/gems/active_support]
36
+
37
+ == Test
38
+
39
+ rake spec
40
+
41
+ Copyright (c) 2011 Aimbulance, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rdoc/task'
11
+
12
+ require 'rspec/core'
13
+ require 'rspec/core/rake_task'
14
+
15
+ RSpec::Core::RakeTask.new(:spec)
16
+
17
+ task :default => :spec
18
+
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'ShareChecker'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README.rdoc')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
@@ -0,0 +1,40 @@
1
+ require "active_support"
2
+
3
+ module ShareChecker
4
+ autoload :Provider, 'share_checker/provider'
5
+ autoload :Config, 'share_checker/config'
6
+
7
+ module Providers
8
+ autoload :Facebook, 'share_checker/providers/facebook'
9
+ autoload :Twitter, 'share_checker/providers/twitter'
10
+ autoload :Vkontakte, 'share_checker/providers/vkontakte'
11
+ autoload :Odnoklassniki, 'share_checker/providers/odnoklassniki'
12
+ autoload :Tweetracker, 'share_checker/providers/tweetracker'
13
+
14
+ def self.get(provider)
15
+ "ShareChecker::Providers::#{provider.to_s.classify}".constantize
16
+ end
17
+
18
+ def self.avariable
19
+ constants.select {|c| Class === const_get(c)}.sort.map(&:downcase).map(&:to_sym)
20
+ end
21
+ end
22
+
23
+ mattr_accessor :config
24
+ @@config = Config.new
25
+
26
+ # Class methods
27
+
28
+ def self.setup(&block)
29
+ yield config
30
+ end
31
+
32
+ def self.check(*args)
33
+ provider(*args).check
34
+ end
35
+
36
+ def self.provider(provider, url, options = {})
37
+ options = (config.send(provider) || {}).merge(options)
38
+ Providers.get(provider).new(url, provider, options)
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module ShareChecker
3
+ class Config < Hash
4
+ # Creates an accessor that simply sets and reads a key in the hash:
5
+ #
6
+ # class Config < Hash
7
+ # hash_accessor :routes, :secret_key, :service_number, :project_name
8
+ # end
9
+ #
10
+ # config = Config.new
11
+ # config.routes = '/posts/message'
12
+ # config[:routes] #=> '/posts/message'
13
+ #
14
+ def self.hash_accessor(*names) #:nodoc:
15
+ names.each do |name|
16
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
17
+ def #{name}
18
+ self[:#{name}]
19
+ end
20
+
21
+ def #{name}=(value)
22
+ self[:#{name}] = value
23
+ end
24
+ METHOD
25
+ end
26
+ end
27
+
28
+ hash_accessor *Providers.avariable
29
+
30
+ def initialize(other = {})
31
+ merge!(other)
32
+
33
+ Providers.avariable.each do |provider|
34
+ self[provider] ||= {}
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ require 'curb'
2
+
3
+ module ShareChecker
4
+ class Provider
5
+ attr_reader :name
6
+
7
+ def initialize(link, name = "noname", options = {})
8
+ @link = link
9
+ @name = name
10
+ @options = options.symbolize_keys
11
+ end
12
+
13
+ def check
14
+ response = self.class.get([url, @link].join)
15
+ return nil unless response
16
+
17
+ parse(response)
18
+ end
19
+
20
+ def parse(response)
21
+ raise NotImplementedError, "Must be overwritten in subclasses"
22
+ end
23
+
24
+ def url
25
+ raise NotImplementedError, "Must be overwritten in subclasses"
26
+ end
27
+
28
+ def method_missing(method_name, *args, &block)
29
+ if @options.key?(method_name.to_sym)
30
+ @options[method_name.to_sym]
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ class << self
37
+ def get(url)
38
+ c = Curl::Easy.new(url) do |curl|
39
+ curl.headers["User-Agent"] = "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/6.0.0"
40
+ curl.verbose = false
41
+ end
42
+
43
+ c.perform
44
+ c.body_str
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,32 @@
1
+ require 'nokogiri'
2
+
3
+ module ShareChecker
4
+ module Providers
5
+ class Facebook < Provider
6
+ # Response sample
7
+ #
8
+ # <links_getStats_response list="true">
9
+ # <link_stat>
10
+ # <url>http://www.mcdonaldseurokids2012.com.ua/challenges/1/works/98</url>
11
+ # <normalized_url>http://www.mcdonaldseurokids2012.com.ua/challenges/1/works/98</normalized_url>
12
+ # <share_count>36</share_count>
13
+ # <like_count>406</like_count>
14
+ # <comment_count>0</comment_count>
15
+ # <total_count>442</total_count>
16
+ # <click_count>0</click_count>
17
+ # <comments_fbid>10150218116270823</comments_fbid>
18
+ # <commentsbox_count>0</commentsbox_count>
19
+ # </link_stat>
20
+ # </links_getStats_response>
21
+ #
22
+ def parse(response)
23
+ doc = Nokogiri::XML(response)
24
+ doc.at("like_count").content.to_i
25
+ end
26
+
27
+ def url
28
+ "http://api.facebook.com/restserver.php?method=links.getStats&urls="
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ module ShareChecker
2
+ module Providers
3
+ class Odnoklassniki < Provider
4
+
5
+ # Response sample
6
+ #
7
+ # ODKL.updateCount('odklcnt0','147');
8
+ #
9
+ def parse(response)
10
+ response =~ /\'(\d+)\'\)\;$/ ? $1.to_i : 0
11
+ end
12
+
13
+ def url
14
+ "http://www.odnoklassniki.ru/dk?st.cmd=extLike&uid=odklcnt0&ref="
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+
3
+ module ShareChecker
4
+ module Providers
5
+ class Tweetracker < Provider
6
+
7
+ # Response sample
8
+ #
9
+ # {
10
+ # "tweets":30,
11
+ # "id":"4e281dcec546612414000004",
12
+ # "users":26,
13
+ # "query":"http://www.mcdonaldseurokids2012.com.ua/challenges/1/works/140"
14
+ # }
15
+ #
16
+ def parse(response)
17
+ count = 0
18
+
19
+ begin
20
+ obj = JSON.parse(response)
21
+ count = (obj["users"] ? obj["users"].to_i : 0)
22
+ rescue Exception => e
23
+ puts "Error parse json: #{response}, #{e.message}"
24
+ count = 0
25
+ end
26
+
27
+ return count
28
+ end
29
+
30
+ def url
31
+ "http://tracktweets.aimbulance.com/api/v1/groups/#{group_id}/urls/count.json?query="
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ require 'json'
2
+
3
+ module ShareChecker
4
+ module Providers
5
+ class Twitter < Provider
6
+
7
+ # Response sample
8
+ #
9
+ # twttr.receiveCount({"count":38,"url":"http://www.mcdonaldseurokids2012.com.ua/challenges/1/works/98/"})
10
+ #
11
+ def parse(response)
12
+ if response =~ /^twttr.receiveCount\((.+)\)$/i
13
+ obj = JSON.parse($1)
14
+ obj["count"].to_i
15
+ end
16
+ end
17
+
18
+ def url
19
+ "http://urls.api.twitter.com/1/urls/count.json?callback=twttr.receiveCount&url="
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'json'
2
+
3
+ module ShareChecker
4
+ module Providers
5
+ class Vkontakte < Provider
6
+
7
+ # Response sample
8
+ #
9
+ # {"response":{"count":1054,"users":[136685987,30523343,144263601,9428152,67880464,9770301,5702433,...]}}
10
+ #
11
+ def parse(response)
12
+ obj = JSON.parse(response)
13
+ obj["response"] ? obj["response"]["count"].to_i : 0
14
+ end
15
+
16
+ def url
17
+ "https://api.vkontakte.ru/method/likes.getList?type=sitepage&owner_id=#{app_id}&page_url="
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module ShareChecker
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "active_model/railtie"
4
+ require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_view/railtie"
7
+ require "action_mailer/railtie"
8
+
9
+ Bundler.require
10
+ require "share_checker"
11
+
12
+ module Dummy
13
+ class Application < Rails::Application
14
+ # Settings in config/environments/* take precedence over those specified here.
15
+ # Application configuration should go into files in config/initializers
16
+ # -- all .rb files in that directory are automatically loaded.
17
+
18
+ # Custom directories with classes and modules you want to be autoloadable.
19
+ # config.autoload_paths += %W(#{config.root}/extras)
20
+
21
+ # Only load the plugins named here, in the order given (default is alphabetical).
22
+ # :all can be used as a placeholder for all plugins not explicitly named.
23
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
+
25
+ # Activate observers that should always be running.
26
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
+
28
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30
+ # config.time_zone = 'Central Time (US & Canada)'
31
+
32
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34
+ # config.i18n.default_locale = :de
35
+
36
+ # JavaScript files you want as :defaults (application.js is always included).
37
+ # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
38
+
39
+ # Configure the default encoding used in templates for Ruby 1.9.
40
+ config.encoding = "utf-8"
41
+
42
+ # Configure sensitive parameters which will be filtered from the log file.
43
+ config.filter_parameters += [:password]
44
+ end
45
+ end