cinch-toolbox 1.0.3 → 1.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.
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # Cinch Toolbox
1
+ # Cinch::Toolbox
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/cinch-toolbox.png)](http://badge.fury.io/rb/cinch-dicebag)
4
- [![Dependency Status](https://gemnasium.com/bhaberer/cinch-toolbox.png)](https://gemnasium.com/bhaberer/cinch-dicebag)
5
- [![Build Status](https://travis-ci.org/bhaberer/cinch-toolbox.png?branch=master)](https://travis-ci.org/bhaberer/cinch-dicebag)
6
- [![Coverage Status](https://coveralls.io/repos/bhaberer/cinch-toolbox/badge.png?branch=master)](https://coveralls.io/r/bhaberer/cinch-dicebag?branch=master)
7
- [![Code Climate](https://codeclimate.com/github/bhaberer/cinch-toolbox.png)](https://codeclimate.com/github/bhaberer/cinch-dicebag)
3
+ [![Gem Version](https://badge.fury.io/rb/cinch-toolbox.png)](http://badge.fury.io/rb/cinch-toolbox)
4
+ [![Dependency Status](https://gemnasium.com/bhaberer/cinch-toolbox.png)](https://gemnasium.com/bhaberer/cinch-toolbox)
5
+ [![Build Status](https://travis-ci.org/bhaberer/cinch-toolbox.png?branch=master)](https://travis-ci.org/bhaberer/cinch-toolbox)
6
+ [![Coverage Status](https://coveralls.io/repos/bhaberer/cinch-toolbox/badge.png?branch=master)](https://coveralls.io/r/bhaberer/cinch-toolbox?branch=master)
7
+ [![Code Climate](https://codeclimate.com/github/bhaberer/cinch-toolbox.png)](https://codeclimate.com/github/bhaberer/cinch-toolbox)
8
8
 
9
9
  This is just a gem required fro many of my plugins, it facilitates a variety of mundane operations.
10
10
 
@@ -4,18 +4,19 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'cinch/toolbox/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = "cinch-toolbox"
7
+ gem.name = 'cinch-toolbox'
8
8
  gem.version = Cinch::Toolbox::VERSION
9
- gem.authors = ["Brian Haberer"]
10
- gem.email = ["bhaberer@gmail.com"]
9
+ gem.authors = ['Brian Haberer']
10
+ gem.email = ['bhaberer@gmail.com']
11
11
  gem.description = %q{A gem of various methods used in many of my plugins. If you need the namespace, let me know.}
12
12
  gem.summary = %q{Common methods used in Cinch Plugins.}
13
- gem.homepage = "https://github.com/bhaberer/cinch-toolbox"
13
+ gem.homepage = 'https://github.com/bhaberer/cinch-toolbox'
14
+ gem.license = 'MIT'
14
15
 
15
16
  gem.files = `git ls-files`.split($/)
16
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
+ gem.require_paths = ['lib']
19
20
 
20
21
  gem.add_development_dependency 'rake'
21
22
  gem.add_development_dependency 'rspec'
data/lib/cinch/toolbox.rb CHANGED
@@ -5,125 +5,162 @@ require 'patron'
5
5
  require 'nokogiri'
6
6
 
7
7
  module Cinch
8
+ # Module for conveniance methods used in multiple Cinch plugins.
8
9
  module Toolbox
9
-
10
10
  # Get an element of the supplied website
11
11
  # @param [String] url The url to access.
12
12
  # @param [String] selector The the selector to try an acquire on the page.
13
- # @param [String] mode (:css) Set this to the kind of selection you want to do.
14
- # @option [String] :mode :css Fetch just the text content at the css selector.
15
- # @option [String] :mode :css_full Fetch the markup and text content at the css selector.
16
- # @option [String] :mode :xpath Fetch just the text content at the xpath selector.
17
- # @option [String] :mode :xpath_full Fetch the markup and text at the xpath selector.
18
- # @return [String] The content ofg the Element or Nil if the element could not be found.
19
- def Toolbox.get_html_element(url, selector, mode = :css)
13
+ # @param [String] mode (:css) Set this to the kind of selection you want to
14
+ # do.
15
+ # @option [String] :mode :css Fetch just the text content at the css
16
+ # selector.
17
+ # @option [String] :mode :css_full Fetch the markup and text content at
18
+ # the css selector.
19
+ # @option [String] :mode :xpath Fetch just the text content at the
20
+ # xpath selector.
21
+ # @option [String] :mode :xpath_full Fetch the markup and text at the
22
+ # xpath selector.
23
+ # @return [String] The content ofg the Element or Nil if the element
24
+ # could not be found.
25
+ def self.get_html_element(url, selector, mode = :css)
20
26
  # Make sure the URL is legit
21
- url = URI::extract(url, ["http", "https"]).first
22
- url = Nokogiri::HTML(open(url))
23
-
24
- content = case mode
25
- when :css, :xpath
26
- page = url.send(mode.to_sym, selector)
27
- page.first.content unless page.first.nil?
28
- when :css_full, :xpath_full
29
- url.send("at_#{mode.to_s.gsub(/_full/, '')}", selector).to_html
30
- end
31
- return content
32
- rescue SocketError, RuntimeError
33
- # Rescue for any kind of network sillyness
34
- return nil
27
+ url = Nokogiri.HTML(open(extract_url(url)))
28
+
29
+ case mode
30
+ when :css, :xpath
31
+ page = url.send(mode.to_sym, selector)
32
+ page.first.content unless page.first.nil?
33
+ when :css_full, :xpath_full
34
+ url.send("at_#{mode.to_s.gsub(/_full/, '')}", selector).to_html
35
+ end
36
+ # Rescue for any kind of network sillyness
37
+ rescue SocketError, RuntimeError, HTTPError
38
+ nil
35
39
  end
36
40
 
37
41
  # Get the title of a given web page.
38
42
  # @param [String] url The url of the page you want the title from.
39
- # @return [String] Either contents of the title element or a notion for an image.
40
- def Toolbox.get_page_title(url)
43
+ # @return [String] Either contents of the title element or a notion
44
+ # for an image.
45
+ def self.get_page_title(url)
41
46
  # Make sure the URL is legit
42
- url = URI::extract(url, ["http", "https"]).first
43
-
44
- # If the link is to an image, extract the filename.
45
- if url.match(/\.jpg|jpeg|gif|png$/)
46
- # unless it's from reddit, then change the url to the gallery to get the image's caption.
47
- if imgur_id = url[/https?:\/\/i\.imgur\.com.*\/([A-Za-z0-9]+)\.(jpg|jpeg|png|gif)/, 1]
48
- url = "http://imgur.com/#{imgur_id}"
49
- else
50
- site = url.match(/([^\.]+\.[^\/]+)/)
51
- return site.nil? ? "Image [#{url}]!!!" : "Image from #{site[1]}"
52
- end
53
- end
47
+ url = extract_url(url)
54
48
 
55
- # Grab the element, return nothing if the site doesn't have a title.
56
- title = Toolbox.get_html_element(url, 'title')
57
- return title.strip.gsub(/\s+/, ' ') unless title.nil?
49
+ if url.match(/([^\s]+(\.(?i)(jpe?g|png|gif|bmp))$)/)
50
+ # If the link is to an image, extract the filename.
51
+ title = get_image_title(url)
52
+ else
53
+ # Grab the element, return nothing if the site doesn't have a title.
54
+ title = Toolbox.get_html_element(url, 'title')
55
+ end
56
+ title.strip.gsub(/\s+/, ' ') unless title.nil?
58
57
  end
59
58
 
60
59
  # Shorten a URL via the configured shortener
61
60
  # @param [String] url The url of the page you want to shorten.
62
61
  # @return [String] The shortened url.
63
- def Toolbox.shorten(url)
62
+ def self.shorten(url)
64
63
  return url if url.length < 45
65
- return shortener.get("create.php?format=simple&url=#{url}").body
64
+ uri = URI.parse("http://is.gd/create.php?format=simple&url=#{url}")
65
+ shortened = Net::HTTP.get(uri)
66
+ shortened if shortened.match(%r(https?://is.gd/))
66
67
  end
67
68
 
68
69
  # Expand a previously shortened URL via the configured shortener
69
70
  # @param [String] url A previously shortened url.
70
71
  # @return [String] The expanded url.
71
- def Toolbox.expand(url)
72
- shortener.get("forward.php?format=simple&shorturl=#{url}").body
72
+ def self.expand(url)
73
+ uri = URI.parse("http://is.gd/forward.php?format=simple&shorturl=#{url}")
74
+ unshortened = Net::HTTP.get(uri)
75
+ unshortened unless unshortened.match(%r(https?://is.gd/))
73
76
  end
74
77
 
75
- # Truncate a given block of text, used for making sure the bot doesn't flood.
78
+ # Truncate a given block of text, used for making sure the bot doesn't
79
+ # flood.
76
80
  # @param [String] text The block of text to check.
77
- # @param [Fixnum] length (250) length to which to constrain the block of text.
78
- def Toolbox.truncate(text, length = 250)
81
+ # @param [Fixnum] length (250) length to which to constrain the
82
+ # block of text.
83
+ def self.truncate(text, length = 250)
79
84
  text = text.gsub(/\n/, ' ')
80
- if text.length > length
81
- text = text[0, (length - 3)] + '...'
82
- end
83
- return text
85
+ text = text[0, (length - 3)] + '...' if text.length > length
86
+ text
84
87
  end
85
88
 
86
- # Simple check to make sure people are using a command via the main channel for plugins that
87
- # require a channel for context.
88
- def Toolbox.sent_via_private_message?(m, error = "You must use that command in the main channel.")
89
+ # Simple check to make sure people are using a command via the main channel
90
+ # for plugins that require a channel for context.
91
+ def self.sent_via_private_message?(m, error = nil)
89
92
  return false unless m.channel.nil?
93
+ error = 'You must use that command in the main channel.' if error.nil?
90
94
  m.user.msg error
91
- return true
95
+ true
92
96
  end
93
97
 
94
98
  # Used to render a period of time in a uniform string.
95
- # There is probably a much better way to do this, so FIXME
99
+ # There is probably a much better way to do this
96
100
  # @param [Fixnum] secs Number of seconds to render into a string.
97
- def Toolbox.time_format(secs, units = nil, format = :long)
98
- data = { :days => (secs / 86400).floor,
99
- :hours => ((secs % 86400) / 3600).floor,
100
- :mins => ((secs % 3600) / 60).floor,
101
- :seconds => (secs % 60).floor }
102
- string = []
103
- data.keys.map do |period|
104
- if period == :seconds || !(data[period].zero? && string.empty?)
105
- if units.nil? || units.include?(period)
106
- string << "#{data[period]}#{format == :long ? " #{period}" : period.slice(0)}"
107
- end
108
- end
109
- end
110
- return string.join(', ')
101
+ def self.time_format(secs, units = nil, format = :long)
102
+ time = build_time_hash(secs, units)
103
+ parse_time_hash(time, format)
104
+ end
105
+
106
+ # Extract the first url from a string
107
+ # @param [String] url String to parse URIs from.
108
+ # @return [URI] URI created from the url.
109
+ def self.extract_url(url)
110
+ extract_urls(url).first
111
+ end
112
+
113
+ # Extract the urls from a string
114
+ # @param [String] url String to parse URIs from.
115
+ # @return [Array] List of URIs created from the string.
116
+ def self.extract_urls(url)
117
+ URI.extract(url, %w(http https))
111
118
  end
112
119
 
113
120
  private
114
121
 
115
- def Toolbox.shortener
116
- short = Patron::Session.new
117
- short.base_url = 'http://is.gd/'
118
- return short
122
+ def self.get_image_title(url)
123
+ if url.match(/imgur/)
124
+ # Get the page title if it's imgur
125
+ imgur_image_title(url)
126
+ else
127
+ site = url[/([^\.]+\.[^\/]+)/, 1]
128
+ site.nil? ? "Image [#{url}]" : "Image from #{site}"
129
+ end
130
+ end
131
+
132
+ def self.imgur_image_title(url)
133
+ imgur_id = url[%r(https?://i\.imgur\.com.*/(\w+)\.(\D{3,4})), 1]
134
+ url = "http://imgur.com/#{imgur_id}"
135
+ Toolbox.get_html_element(url, 'title')
119
136
  end
120
137
 
138
+ def self.build_time_hash(secs, units)
139
+ { days: (secs / 86_400).floor,
140
+ hours: ((secs % 86_400) / 3600).floor,
141
+ mins: ((secs % 3_600) / 60).floor,
142
+ seconds: (secs % 60).floor }
143
+ .delete_if { |period, _time| units && !units.include?(period) }
144
+ end
145
+
146
+ def self.parse_time_hash(times, format)
147
+ string = []
148
+ times.each_pair do |period, time|
149
+ if period == :seconds || !(time.zero? && string.empty?)
150
+ string << [time, format == :long ? " #{period}" : period.slice(0)]
151
+ .join
152
+ end
153
+ end
154
+ string.join(', ')
155
+ end
121
156
  end
122
157
  end
123
158
 
159
+ # Patch OpenURI to allow for redirection from http => https
124
160
  module OpenURI
125
- def OpenURI.redirectable?(uri1, uri2) # :nodoc:
161
+ def self.redirectable?(uri1, uri2) # :nodoc:
126
162
  uri1.scheme.downcase == uri2.scheme.downcase ||
127
- (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp|https)\z/i =~ uri2.scheme)
163
+ /\A(?:http|ftp)\z/i =~ uri1.scheme &&
164
+ /\A(?:http|ftp|https)\z/i =~ uri2.scheme
128
165
  end
129
166
  end
@@ -1,5 +1,7 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  module Cinch
3
+ # Version Info
2
4
  module Toolbox
3
- VERSION = "1.0.3"
5
+ VERSION = '1.1.0'
4
6
  end
5
7
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  require 'coveralls'
2
- Coveralls.wear!
2
+ require 'simplecov'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
9
+
3
10
  require 'cinch/toolbox'
4
11
  require 'cinch/test'
5
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cinch-toolbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-09 00:00:00.000000000 Z
12
+ date: 2014-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -143,7 +143,8 @@ files:
143
143
  - spec/cinch-toolbox_spec.rb
144
144
  - spec/spec_helper.rb
145
145
  homepage: https://github.com/bhaberer/cinch-toolbox
146
- licenses: []
146
+ licenses:
147
+ - MIT
147
148
  post_install_message:
148
149
  rdoc_options: []
149
150
  require_paths:
@@ -169,3 +170,4 @@ summary: Common methods used in Cinch Plugins.
169
170
  test_files:
170
171
  - spec/cinch-toolbox_spec.rb
171
172
  - spec/spec_helper.rb
173
+ has_rdoc: