galerts 0.0.1
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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/README.md +41 -0
- data/Rakefile +1 -0
- data/galerts.gemspec +18 -0
- data/lib/galerts.rb +51 -0
- data/lib/galerts/alert.rb +36 -0
- data/lib/galerts/manager.rb +141 -0
- data/lib/galerts/version.rb +3 -0
- metadata +66 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2ade27844d1c41508bbacd7b030c2ed4654a45e4
|
|
4
|
+
data.tar.gz: 6e1f27c679e63c21e1d238158397e2442dea11c6
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f8b27acbde41ba7bd76d0d34b7404260989d3aced4d22a697057b5ba483646bd17368c46b9f17e7ad55e3545a79f514da39ca4b4f1719258119d7750e24455eb
|
|
7
|
+
data.tar.gz: 219056aebeb3d6e3834012f4fd98d7a521df6d7931579c7798fb1782077d81d6dc4631850ffc3c9db7afead1d65dca15cd58922e710e6532551338678d86867a
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Galerts
|
|
2
|
+
|
|
3
|
+
Simple Ruby library that uses Mechanize to scrape Google Alerts from the google
|
|
4
|
+
alerts webpage.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- List all alerts associated with account.
|
|
9
|
+
- Create new alerts for any google domain.
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
require 'google_alerts'
|
|
15
|
+
|
|
16
|
+
manager = Galerts::Manager.new('example@gmail.com', 'password')
|
|
17
|
+
|
|
18
|
+
# List alerts
|
|
19
|
+
alerts = manager.alerts
|
|
20
|
+
|
|
21
|
+
# Create a new alert for on Google News Turkey in real time delivering alerts
|
|
22
|
+
# via RSS
|
|
23
|
+
manager.create("my keywords", {
|
|
24
|
+
:frequency => Galerts::RT,
|
|
25
|
+
:domain => 'com.tr',
|
|
26
|
+
:language => "tr",
|
|
27
|
+
:sources => [Galerts::NEWS],
|
|
28
|
+
:how_many => Galerts::ALL_RESULTS,
|
|
29
|
+
:region => "TR",
|
|
30
|
+
:delivery => Galerts::RSS
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Contribute
|
|
36
|
+
|
|
37
|
+
I need your contributions to make that work better!
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
This project licensed under MIT.
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/galerts.gemspec
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require File.expand_path('../lib/galerts/version', __FILE__)
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = 'galerts'
|
|
5
|
+
s.version = Galerts::VERSION.dup
|
|
6
|
+
s.date = '2014-09-16'
|
|
7
|
+
s.summary = 'Ruby library to manage google alerts'
|
|
8
|
+
s.description = %q{Manage to Google Alerts}
|
|
9
|
+
s.authors = ["Emre Can Yılmaz"]
|
|
10
|
+
s.email = ['emrecan@ecylmz.com']
|
|
11
|
+
s.files = `git ls-files`.split("\n")
|
|
12
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
13
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
14
|
+
s.require_paths = ['lib']
|
|
15
|
+
s.homepage = 'https://github.com/pivotus/galerts'
|
|
16
|
+
s.license = 'MIT'
|
|
17
|
+
s.add_runtime_dependency('mechanize', '~> 2.7')
|
|
18
|
+
end
|
data/lib/galerts.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require File.expand_path('../galerts/alert', __FILE__)
|
|
2
|
+
require File.expand_path('../galerts/manager', __FILE__)
|
|
3
|
+
|
|
4
|
+
module Galerts
|
|
5
|
+
# URLs
|
|
6
|
+
CREATE_ALERT_URL = 'https://www.google.com/alerts/create?'
|
|
7
|
+
GOOGLE_LOGIN_URL = 'https://accounts.google.com/ServiceLogin?'
|
|
8
|
+
ALERTS_URL = 'https://www.google.com/alerts'
|
|
9
|
+
LOGIN_URL = "#{GOOGLE_LOGIN_URL}service=alerts&continue=#{ALERTS_URL}"
|
|
10
|
+
|
|
11
|
+
# Google Return HTML Definitions
|
|
12
|
+
ALERT_EXIST = "[null,11,null,\"\"]"
|
|
13
|
+
ALERT_SOMETHING_WENT_WRONG = "[null,7,null,\"\"]"
|
|
14
|
+
|
|
15
|
+
# Google Value
|
|
16
|
+
BEST_RESULTS = 'Only the best results'
|
|
17
|
+
ALL_RESULTS = 'All results'
|
|
18
|
+
|
|
19
|
+
HOW_MANY_TYPES = {
|
|
20
|
+
ALL_RESULTS => 2,
|
|
21
|
+
BEST_RESULTS => 3
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
RSS = 'rss'
|
|
25
|
+
EMAIL = 'email'
|
|
26
|
+
|
|
27
|
+
DELIVERY_TYPES = [RSS, EMAIL]
|
|
28
|
+
|
|
29
|
+
RT = 'As it happens'
|
|
30
|
+
DAILY = 'Once a day'
|
|
31
|
+
WEEKLY = 'Once a week'
|
|
32
|
+
|
|
33
|
+
FREQ_TYPES = [RT, DAILY, WEEKLY]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
BLOGS = 'Blogs'
|
|
37
|
+
NEWS = 'News'
|
|
38
|
+
WEB = 'Web'
|
|
39
|
+
VIDEOS = 'Videos'
|
|
40
|
+
BOOKS = 'Books'
|
|
41
|
+
DISCUSSIONS = 'Discussions'
|
|
42
|
+
|
|
43
|
+
SOURCES_TYPES = {
|
|
44
|
+
BLOGS => 1,
|
|
45
|
+
NEWS => 2,
|
|
46
|
+
WEB => 3,
|
|
47
|
+
VIDEOS => 5,
|
|
48
|
+
BOOKS => 6,
|
|
49
|
+
DISCUSSIONS => 7
|
|
50
|
+
}
|
|
51
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Galerts
|
|
2
|
+
class Alert
|
|
3
|
+
attr_accessor :search_query, :id, :data_id, :domain, :frequency, :sources, :language, :how_many, :region, :delivery, :feed_url
|
|
4
|
+
def initialize(search_query, options = {})
|
|
5
|
+
|
|
6
|
+
default_options = {
|
|
7
|
+
id: 0,
|
|
8
|
+
data_id: 0,
|
|
9
|
+
domain: 'com',
|
|
10
|
+
frequency: 'rt',
|
|
11
|
+
sources: '',
|
|
12
|
+
language: 'tr',
|
|
13
|
+
how_many: 'all_results',
|
|
14
|
+
region: 'TR',
|
|
15
|
+
delivery: 'rss',
|
|
16
|
+
feed_url: nil
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
default_options.each do |key, value|
|
|
20
|
+
options[key] ||= value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@search_query = search_query
|
|
24
|
+
@id = options[:id]
|
|
25
|
+
@data_id = options[:data_id]
|
|
26
|
+
@domain = options[:domain]
|
|
27
|
+
@frequency = options[:frequency]
|
|
28
|
+
@sources = options[:sources]
|
|
29
|
+
@language = options[:language]
|
|
30
|
+
@how_many = options[:how_many]
|
|
31
|
+
@region = options[:region]
|
|
32
|
+
@delivery = options[:delivery]
|
|
33
|
+
@feed_url = options[:feed_url]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require 'mechanize'
|
|
2
|
+
|
|
3
|
+
module Galerts
|
|
4
|
+
class Manager
|
|
5
|
+
def initialize(email, password)
|
|
6
|
+
@email = email
|
|
7
|
+
@password = password
|
|
8
|
+
init_agent
|
|
9
|
+
login
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def init_agent
|
|
13
|
+
@agent = Mechanize.new
|
|
14
|
+
@agent.user_agent_alias = 'Linux Mozilla'
|
|
15
|
+
@agent.keep_alive = true
|
|
16
|
+
@agent.redirect_ok = true
|
|
17
|
+
@agent.follow_meta_refresh = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def login
|
|
21
|
+
response = @agent.get(LOGIN_URL) # get login page
|
|
22
|
+
login_form = Nokogiri::HTML(response.body, nil, 'utf-8').css('form#gaia_loginform input') # get login form
|
|
23
|
+
params = get_login_form_params(login_form) # fetch form parameters and edit
|
|
24
|
+
response = @agent.post(LOGIN_URL, params) # do login
|
|
25
|
+
error = response.parser.css('span[id^=errormsg]')
|
|
26
|
+
unless error.empty?
|
|
27
|
+
raise error.text.delete("\n").strip
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def get_login_form_params(login_form)
|
|
32
|
+
params = {}
|
|
33
|
+
login_form.each do |input|
|
|
34
|
+
if input['name'] == 'Email'
|
|
35
|
+
params[input['name']] = @email
|
|
36
|
+
elsif input['name'] == 'Passwd'
|
|
37
|
+
params[input['name']] = @password
|
|
38
|
+
else
|
|
39
|
+
params[input['name']] = input['value']
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
return params
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def alerts_page
|
|
46
|
+
Nokogiri::HTML(@agent.get(ALERTS_URL).body, nil, 'utf-8')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def alerts
|
|
50
|
+
result = []
|
|
51
|
+
contents = alerts_page.css('div#gb-main div.main-page script').text
|
|
52
|
+
|
|
53
|
+
contents = contents.gsub('null', 'nil')
|
|
54
|
+
|
|
55
|
+
contents = eval(contents.gsub("window.STATE = ", ""))
|
|
56
|
+
|
|
57
|
+
# only 'id, search_query, feed_url, data_id' variables have true value,
|
|
58
|
+
# other variables have default Alert class values.
|
|
59
|
+
contents[1][1].each do |alert|
|
|
60
|
+
result << Alert.new(alert[2][3][1], {
|
|
61
|
+
id: alert[2].last.last.last,
|
|
62
|
+
search_query: alert[2][3][1],
|
|
63
|
+
feed_url: "/alerts/feeds/#{alert.last}/#{alert[2].last.last.last}",
|
|
64
|
+
data_id: alert[1],
|
|
65
|
+
domain: 'Unknown',
|
|
66
|
+
frequency: 'Unknown',
|
|
67
|
+
sources: 'Unknown',
|
|
68
|
+
language: 'Unknown',
|
|
69
|
+
how_many: 'Unknown',
|
|
70
|
+
region: 'Unknown',
|
|
71
|
+
delivery: 'Unknown'
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
result
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def build_create_params(search_query, options)
|
|
79
|
+
# check parameters
|
|
80
|
+
raise "Unknown alert how_many" unless HOW_MANY_TYPES.has_key?(options[:how_many])
|
|
81
|
+
raise "Unknown alert delivery type" unless DELIVERY_TYPES.include?(options[:delivery])
|
|
82
|
+
raise "Unknown alert frequency type" unless FREQ_TYPES.include?(options[:frequency])
|
|
83
|
+
|
|
84
|
+
# set delivery and frequency parameters
|
|
85
|
+
if options[:delivery] == EMAIL
|
|
86
|
+
if options[:frequency] == DAILY
|
|
87
|
+
delivery_and_frequency = @email + ',[null,null,11],2'
|
|
88
|
+
elsif options[:frequency] == WEEKLY
|
|
89
|
+
delivery_and_frequency = @email + ',[null,null,11,1],3'
|
|
90
|
+
elsif options[:frequency] == RT
|
|
91
|
+
delivery_and_frequency = "1,\"#{@email}\",[],1"
|
|
92
|
+
end
|
|
93
|
+
elsif options[:delivery] == RSS
|
|
94
|
+
delivery_and_frequency = "2,\"\",[],1"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# options[:sources] ? sources = options[:sources] : sources = ""
|
|
98
|
+
|
|
99
|
+
if options[:sources].nil?
|
|
100
|
+
sources_text = 'null'
|
|
101
|
+
else
|
|
102
|
+
sources_text = "["
|
|
103
|
+
options[:sources].collect do |source|
|
|
104
|
+
raise "Unknown alert source" unless SOURCES_TYPES.has_key?(source)
|
|
105
|
+
sources_text += SOURCES_TYPES[source].to_s + ','
|
|
106
|
+
end
|
|
107
|
+
sources_text = sources_text.chop + ']'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# TODO: need more readable
|
|
111
|
+
params = {
|
|
112
|
+
'params' => "[null,[null,null,null,[null,\"#{search_query}\",\"#{options[:domain]}\",[null,\"#{options[:language]}\",\"#{options[:region]}\"],null,null,null,#{options[:region] == "" ? 1 : 0},1],#{sources_text},#{HOW_MANY_TYPES[options[:how_many]]},[[null,#{delivery_and_frequency},\"#{options[:language] + '-' + options[:region].upcase}\",null,null,null,null,null,'0']]]]"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
params = URI.encode_www_form(params)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def create(search_query, options = {})
|
|
119
|
+
x = alerts_page.css('div#gb-main div.main-page script').text.split(',').last[1..-4]
|
|
120
|
+
response = @agent.post("#{CREATE_ALERT_URL}x=#{x}", build_create_params(search_query, options), {'Content-Type' => 'application/x-www-form-urlencoded'})
|
|
121
|
+
|
|
122
|
+
if response.body == ALERT_EXIST
|
|
123
|
+
raise "Alert exist!"
|
|
124
|
+
elsif response.body == ALERT_SOMETHING_WENT_WRONG
|
|
125
|
+
raise "Something went wrong!" # internal error, html changed maybe
|
|
126
|
+
else
|
|
127
|
+
response_body = response.body.gsub('null', 'nil')
|
|
128
|
+
created_alert = Nokogiri::HTML(eval(response_body)[4][0][2], nil, 'utf-8')
|
|
129
|
+
|
|
130
|
+
alert = Alert.new(search_query, options)
|
|
131
|
+
|
|
132
|
+
if options[:delivery] == RSS
|
|
133
|
+
alert.id = created_alert.css('a')[0]['href'].split('/').last if options[:delivery] == RSS
|
|
134
|
+
alert.feed_url = created_alert.css('a')[0]['href']
|
|
135
|
+
end
|
|
136
|
+
alert.data_id = created_alert.css('li')[0]['data-id']
|
|
137
|
+
alert
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: galerts
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Emre Can Yılmaz
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-09-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: mechanize
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.7'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.7'
|
|
27
|
+
description: Manage to Google Alerts
|
|
28
|
+
email:
|
|
29
|
+
- emrecan@ecylmz.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- Gemfile
|
|
35
|
+
- README.md
|
|
36
|
+
- Rakefile
|
|
37
|
+
- galerts.gemspec
|
|
38
|
+
- lib/galerts.rb
|
|
39
|
+
- lib/galerts/alert.rb
|
|
40
|
+
- lib/galerts/manager.rb
|
|
41
|
+
- lib/galerts/version.rb
|
|
42
|
+
homepage: https://github.com/pivotus/galerts
|
|
43
|
+
licenses:
|
|
44
|
+
- MIT
|
|
45
|
+
metadata: {}
|
|
46
|
+
post_install_message:
|
|
47
|
+
rdoc_options: []
|
|
48
|
+
require_paths:
|
|
49
|
+
- lib
|
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0'
|
|
60
|
+
requirements: []
|
|
61
|
+
rubyforge_project:
|
|
62
|
+
rubygems_version: 2.2.2
|
|
63
|
+
signing_key:
|
|
64
|
+
specification_version: 4
|
|
65
|
+
summary: Ruby library to manage google alerts
|
|
66
|
+
test_files: []
|