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 +6 -6
- data/cinch-toolbox.gemspec +6 -5
- data/lib/cinch/toolbox.rb +112 -75
- data/lib/cinch/toolbox/version.rb +3 -1
- data/spec/spec_helper.rb +8 -2
- metadata +5 -3
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# Cinch
|
1
|
+
# Cinch::Toolbox
|
2
2
|
|
3
|
-
[](http://badge.fury.io/rb/cinch-
|
4
|
-
[](https://gemnasium.com/bhaberer/cinch-
|
5
|
-
[](https://travis-ci.org/bhaberer/cinch-
|
6
|
-
[](https://coveralls.io/r/bhaberer/cinch-
|
7
|
-
[](https://codeclimate.com/github/bhaberer/cinch-
|
3
|
+
[](http://badge.fury.io/rb/cinch-toolbox)
|
4
|
+
[](https://gemnasium.com/bhaberer/cinch-toolbox)
|
5
|
+
[](https://travis-ci.org/bhaberer/cinch-toolbox)
|
6
|
+
[](https://coveralls.io/r/bhaberer/cinch-toolbox?branch=master)
|
7
|
+
[](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
|
|
data/cinch-toolbox.gemspec
CHANGED
@@ -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 =
|
7
|
+
gem.name = 'cinch-toolbox'
|
8
8
|
gem.version = Cinch::Toolbox::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
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 =
|
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 = [
|
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
|
14
|
-
#
|
15
|
-
# @option [String] :mode :
|
16
|
-
#
|
17
|
-
# @option [String] :mode :
|
18
|
-
#
|
19
|
-
|
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 =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
40
|
-
|
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 =
|
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
|
-
|
56
|
-
|
57
|
-
|
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
|
62
|
+
def self.shorten(url)
|
64
63
|
return url if url.length < 45
|
65
|
-
|
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
|
72
|
-
|
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
|
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
|
78
|
-
|
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
|
-
|
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
|
87
|
-
# require a channel for context.
|
88
|
-
def
|
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
|
-
|
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
|
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
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
161
|
+
def self.redirectable?(uri1, uri2) # :nodoc:
|
126
162
|
uri1.scheme.downcase == uri2.scheme.downcase ||
|
127
|
-
|
163
|
+
/\A(?:http|ftp)\z/i =~ uri1.scheme &&
|
164
|
+
/\A(?:http|ftp|https)\z/i =~ uri2.scheme
|
128
165
|
end
|
129
166
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require 'coveralls'
|
2
|
-
|
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
|
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:
|
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:
|