ogo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 07a11957eb9e8e7a755ef7508125319f86e14b65
4
+ data.tar.gz: 31e44eeb7a939ea3afbcdd9a5a309bbdf86e8f8a
5
+ SHA512:
6
+ metadata.gz: 4cbbc4c57a3f4fab3e09fafd6853d78f2674d9da677aa73977051c0610eac0f35e0339af37f7d3031d33590197f80800d6f740f68a00e86126f41b4702acd261
7
+ data.tar.gz: 3e3c2516b4fdaf125c1bb7d378630f4c3faa6762f8efc22613d3fceae9ebcfa89b39831ff4c4e13f8c87315ce3dca2bee52db34eed96dc87af681573476b5a1c
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ tmp/*
6
+ .rvmrc
7
+ *.idea
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ogo.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2016 gazay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Ogo gem — parse info from urls for different social network needs
2
+
3
+ ## Information
4
+
5
+ Implementation of first verion of this gem based mostly on @huyha85's opengraph_parser
6
+ https://github.com/huyha85/opengraph_parser and its forks.
7
+
8
+ I prefer to make my own repo for this gem as origin repo is seemingly-abandoned and
9
+ I need more functionality than just opengraph (ogp.me) tags parsing.
10
+
11
+ ## License
12
+
13
+ The MIT License
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc 'Run all tests by default'
5
+ task :default => :spec
6
+
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.rspec_opts = ["--color", '--format doc']
10
+ end
@@ -0,0 +1,139 @@
1
+ require 'nokogiri'
2
+ require 'utils/redirect_follower'
3
+ require "addressable/uri"
4
+ require 'uri'
5
+
6
+ module Ogo
7
+ class Opengraph
8
+
9
+ attr_accessor :src, :url, :type, :title, :description, :images, :metadata, :response, :original_images
10
+
11
+ def initialize(src, options = {})
12
+ @src = src
13
+ @body = nil
14
+ @images = []
15
+ @metadata = {}
16
+
17
+ @_fallback = options[:fallback] || true
18
+ @_options = options
19
+ end
20
+
21
+ def parse
22
+ parse_opengraph(@_options)
23
+ load_fallback if @_fallback
24
+ check_images_path
25
+ end
26
+
27
+ private
28
+
29
+ def parse_opengraph(options = {})
30
+ begin
31
+ if src.include? '</html>'
32
+ self.body = src
33
+ else
34
+ self.body = Ogo::Utils::RedirectFollower.new(src, options).resolve.body
35
+ end
36
+ rescue
37
+ self.title = self.url = src
38
+ return
39
+ end
40
+
41
+ if body
42
+ attrs_list = %w(title url type description)
43
+ doc = Nokogiri.parse(body)
44
+ doc.css('meta').each do |m|
45
+ if m.attribute('property') && m.attribute('property').to_s.match(/^og:(.+)$/i)
46
+ m_content = m.attribute('content').to_s.strip
47
+ metadata_name = m.attribute('property').to_s.gsub("og:", "")
48
+ self.metadata = add_metadata(metadata, metadata_name, m_content)
49
+ case metadata_name
50
+ when *attrs_list
51
+ self.instance_variable_set("@#{metadata_name}", m_content) unless m_content.empty?
52
+ when "image"
53
+ add_image(m_content)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def load_fallback
61
+ if body
62
+ doc = Nokogiri.parse(body)
63
+
64
+ if title.to_s.empty? && doc.xpath("//head//title").size > 0
65
+ self.title = doc.xpath("//head//title").first.text.to_s.strip
66
+ end
67
+
68
+ self.url = src if url.to_s.empty?
69
+
70
+ if description.to_s.empty? && description_meta = doc.xpath("//head//meta[@name='description']").first
71
+ self.description = description_meta.attribute("content").to_s.strip
72
+ end
73
+
74
+ if description.to_s.empty?
75
+ self.description = fetch_first_text(doc)
76
+ end
77
+
78
+ fetch_images(doc, "//head//link[@rel='image_src']", "href") if images.empty?
79
+ fetch_images(doc, "//img", "src") if images.empty?
80
+ end
81
+ end
82
+
83
+ def check_images_path
84
+ self.original_images = images.dup
85
+ uri = Addressable::URI.parse(src)
86
+ imgs = images.dup
87
+ self.images = []
88
+ imgs.each do |img|
89
+ if Addressable::URI.parse(img).host.nil?
90
+ full_path = uri.join(img).to_s
91
+ add_image(full_path)
92
+ else
93
+ add_image(img)
94
+ end
95
+ end
96
+ end
97
+
98
+ def add_image(image_url)
99
+ unless images.include?(image_url) || image_url.to_s.empty?
100
+ self.images << image_url
101
+ end
102
+ end
103
+
104
+ def fetch_images(doc, xpath_str, attr)
105
+ doc.xpath(xpath_str).each do |link|
106
+ add_image(link.attribute(attr).to_s.strip)
107
+ end
108
+ end
109
+
110
+ def fetch_first_text(doc)
111
+ doc.xpath('//p').each do |p|
112
+ s = p.text.to_s.strip
113
+ return s if s.length > 20
114
+ end
115
+ end
116
+
117
+ def add_metadata(metadata_container, path, content)
118
+ path_elements = path.split(':')
119
+ if path_elements.size > 1
120
+ current_element = path_elements.delete_at(0)
121
+ path = path_elements.join(':')
122
+ if metadata_container[current_element.to_sym]
123
+ path_pointer = metadata_container[current_element.to_sym].last
124
+ index_count = metadata_container[current_element.to_sym].size
125
+ metadata_container[current_element.to_sym][index_count - 1] = add_metadata(path_pointer, path, content)
126
+ metadata_container
127
+ else
128
+ metadata_container[current_element.to_sym] = []
129
+ metadata_container[current_element.to_sym] << add_metadata({}, path, content)
130
+ metadata_container
131
+ end
132
+ else
133
+ metadata_container[path.to_sym] ||= []
134
+ metadata_container[path.to_sym] << {'_value'.to_sym => content}
135
+ metadata_container
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,52 @@
1
+ require 'net/http'
2
+
3
+ module Ogo
4
+ module Utils
5
+ class RedirectFollower
6
+ REDIRECT_DEFAULT_LIMIT = 5
7
+
8
+ class TooManyRedirects < StandardError; end
9
+
10
+ attr_accessor :url, :body, :redirect_limit, :response, :headers
11
+
12
+ def initialize(url, options = {})
13
+ @limit = options[:limit] || REDIRECT_DEFAULT_LIMIT
14
+ @headers = options[:headers] || {}
15
+ @url = url
16
+ end
17
+
18
+ def resolve
19
+ raise TooManyRedirects if redirect_limit < 0
20
+
21
+ url = "http://#{url}" unless url.starts_with?('http')
22
+ uri = Addressable::URI.parse(URI.escape(url))
23
+
24
+ http = Net::HTTP.new(uri.host, uri.port)
25
+ if uri.scheme == 'https'
26
+ http.use_ssl = true
27
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
28
+ end
29
+
30
+ self.response = http.request_get(uri.request_uri, headers)
31
+
32
+ if response.kind_of?(Net::HTTPRedirection)
33
+ self.url = redirect_url
34
+ self.redirect_limit -= 1
35
+ resolve
36
+ end
37
+
38
+ self.body = response.body
39
+ self
40
+ end
41
+
42
+ def redirect_url
43
+ if response['location'].nil?
44
+ response.body.match(/<a href=\"([^>]+)\">/i)[1]
45
+ else
46
+ response['location']
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Ogo
2
+ VERSION = '0.0.1'
3
+ end
data/lib/ogo.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'addressable/uri'
2
+ require_relative 'ogo/opengraph'
3
+ require_relative 'ogo/utils/redirect_follower'
4
+
5
+ module Ogo
6
+
7
+ def self.parse_opengraph(url)
8
+ og = Ogo::Opengraph.new(url)
9
+ og.parse
10
+ og
11
+ end
12
+
13
+ end
data/ogo.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'ogo/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'ogo'
7
+ s.version = Ogo::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['gazay']
10
+ s.licenses = ['MIT']
11
+ s.email = ['alex.gaziev@gmail.com']
12
+ s.homepage = 'https://github.com/gazay/ogo'
13
+ s.summary = %q{Parse open graphs for social networks}
14
+ s.description = %q{Provides information from opengraph tags for different social networks}
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.require_paths = ['lib']
18
+ s.required_ruby_version = '> 2.0'
19
+ s.add_dependency 'nokogiri', '>= 1.6'
20
+ s.add_dependency 'addressable', '>= 2.4.0'
21
+ s.add_development_dependency 'rspec', '>= 3.0'
22
+ s.add_development_dependency 'rake'
23
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ogo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - gazay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: addressable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.4.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Provides information from opengraph tags for different social networks
70
+ email:
71
+ - alex.gaziev@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - lib/ogo.rb
82
+ - lib/ogo/opengraph.rb
83
+ - lib/ogo/utils/redirect_follower.rb
84
+ - lib/ogo/version.rb
85
+ - ogo.gemspec
86
+ homepage: https://github.com/gazay/ogo
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">"
97
+ - !ruby/object:Gem::Version
98
+ version: '2.0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.5.1
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Parse open graphs for social networks
110
+ test_files: []