quora_notify 0.0.7
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 +4 -0
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +9 -0
- data/bin/quora_notify +34 -0
- data/lib/quora_notify/base.rb +63 -0
- data/lib/quora_notify/cookie_readers/chrome_cookie_reader.rb +56 -0
- data/lib/quora_notify/cookie_readers/cookie.rb +14 -0
- data/lib/quora_notify/cookie_readers/safari_cookie_reader.rb +107 -0
- data/lib/quora_notify/cookie_readers.rb +5 -0
- data/lib/quora_notify/install.rb +49 -0
- data/lib/quora_notify/notification.rb +51 -0
- data/lib/quora_notify/version.rb +3 -0
- data/lib/quora_notify.rb +5 -0
- data/test/test_quora_notify.rb +69 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a2e83b718291fe349330076b9e419979994700fc
|
4
|
+
data.tar.gz: ce758c4e070950ce22d476fe8528832b547eb685
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b07cbb3b8a2a6a80c15cd1c0d3489b3ecf574b95cdc66a2aac699f4ecf046c912015fbe8dfe1649bba73392eb895312beb6613f7bfd2e3a161254de640e04491
|
7
|
+
data.tar.gz: 9bff482d70fd30f821cfb0f0e3396bce26d09cfe8027eb630048469b93d913db9ad1afa281785b4d83bce31475d813f92c0a1d69fcc7be9b1e42fce326d38b2e
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
quora_notify (0.0.6)
|
5
|
+
htmlentities
|
6
|
+
sqlite3
|
7
|
+
terminal-notifier
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
htmlentities (4.3.1)
|
13
|
+
metaclass (0.0.1)
|
14
|
+
mocha (0.13.3)
|
15
|
+
metaclass (~> 0.0.1)
|
16
|
+
sqlite3 (1.3.7)
|
17
|
+
terminal-notifier (1.4.2)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
mocha
|
24
|
+
quora_notify!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Joey Carmello
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# QuoraNotify
|
2
|
+
|
3
|
+
Receive quora.com notifications in Notification Center on OSX Mountain Lion.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install a launchAgent to poll Quora for notifications
|
8
|
+
|
9
|
+
$ gem install quora_notify
|
10
|
+
|
11
|
+
$ quora_notify --install
|
12
|
+
|
13
|
+
|
14
|
+
Uninstall with:
|
15
|
+
|
16
|
+
$ quora_notify --uninstall
|
17
|
+
|
18
|
+
### Or use it as a library in your ruby project:
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
gem 'quora_notify'
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
$ gem install quora_notify
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
Fetch notifications and send them to Notification Center:
|
35
|
+
|
36
|
+
QuoraNotify.run!
|
37
|
+
|
38
|
+
|
39
|
+
List the current Quora notifications:
|
40
|
+
|
41
|
+
QuoraNotify::Notification.list
|
42
|
+
|
43
|
+
Clear the current Quora notifications:
|
44
|
+
|
45
|
+
QuoraNotify::Notification.clear!
|
46
|
+
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/quora_notify
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'quora_notify'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'quora_notify'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'optparse'
|
11
|
+
|
12
|
+
command = nil
|
13
|
+
|
14
|
+
op = OptionParser.new do |opts|
|
15
|
+
opts.program_name = __FILE__
|
16
|
+
opts.banner = "Use Quora API notifications in Notification Center."
|
17
|
+
opts.on("-h", "--help") { command = :help }
|
18
|
+
opts.on("-i", "--install", "Installs the LaunchAgent") { command = :install }
|
19
|
+
opts.on("-u", "--uninstall", "Uninstalls the LaunchAgent") { command = :uninstall }
|
20
|
+
opts.on("-r", "--run", "Run once") { command = :run }
|
21
|
+
end
|
22
|
+
|
23
|
+
op.parse!
|
24
|
+
|
25
|
+
case command
|
26
|
+
when :install
|
27
|
+
QuoraNotify::Install.run!
|
28
|
+
when :uninstall
|
29
|
+
QuoraNotify::Install.uninstall!
|
30
|
+
when :run
|
31
|
+
QuoraNotify.run!
|
32
|
+
when :help
|
33
|
+
puts op
|
34
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'json'
|
3
|
+
require 'terminal-notifier'
|
4
|
+
|
5
|
+
module QuoraNotify
|
6
|
+
|
7
|
+
API_NOTIFICATION_PATH = 'http://api.quora.com/api/logged_in_user?fields=notifs'
|
8
|
+
TMP_COOKIE_PATH = '/tmp/quora_notifier'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def quora_notifications
|
12
|
+
cookies = quora_cookies_for_browser(:default)
|
13
|
+
write_cookies_to_file(cookies, TMP_COOKIE_PATH)
|
14
|
+
|
15
|
+
notification_response = `curl #{API_NOTIFICATION_PATH} -b #{TMP_COOKIE_PATH}`.sub('while(1);', '')
|
16
|
+
JSON.parse(notification_response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def run!
|
20
|
+
notifications = begin
|
21
|
+
quora_notifications
|
22
|
+
rescue JSON::ParserError
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
process notifications
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def process(notifications)
|
31
|
+
return [] if notifications.empty? || notifications['notifs']['unseen_count'] == 0
|
32
|
+
|
33
|
+
existing_notifs = Notification.list.map{ |n| n[:group] }
|
34
|
+
quora_notifs = notifications['notifs']['unseen'].map{ |notif| Notification.new(notif) }
|
35
|
+
(quora_notifs - existing_notifs).each { |notification| notification.notify }
|
36
|
+
end
|
37
|
+
|
38
|
+
def write_cookies_to_file(cookies, file)
|
39
|
+
File.open(file, 'w') do |file|
|
40
|
+
cookies.each do |cookie|
|
41
|
+
# TODO: could be in to_s for cookie object
|
42
|
+
file.puts "#{cookie.domain}\tTRUE\t#{cookie.path}\tFALSE\t#{cookie.expires}\t#{cookie.name}\t#{cookie.value}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def quora_cookies_for_browser(browser)
|
48
|
+
readers = [
|
49
|
+
CookieReaders::ChromeCookieReader.new,
|
50
|
+
CookieReaders::SafariCookieReader.new
|
51
|
+
]
|
52
|
+
|
53
|
+
readers.collect do |reader|
|
54
|
+
begin
|
55
|
+
reader.read_cookies
|
56
|
+
rescue => e
|
57
|
+
[]
|
58
|
+
end
|
59
|
+
end.flatten.uniq.select { |cookie| cookie.domain == '.quora.com' }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
require 'quora_notify/cookie_readers/cookie'
|
3
|
+
|
4
|
+
class ChromeCookieReaderException < StandardError; end
|
5
|
+
|
6
|
+
class QuoraNotify::CookieReaders::ChromeCookieReader
|
7
|
+
|
8
|
+
DEFAULT_CHROME_COOKIE_PATH = "#{ENV['HOME']}/Library/Application Support/Google/Chrome/Default/Cookies"
|
9
|
+
|
10
|
+
# Accepts:
|
11
|
+
# cookie_file_path: Use default cookie file if nil (default)
|
12
|
+
def initialize(file_path = nil)
|
13
|
+
@cookie_file_path = file_path
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns an array of Cookie objects
|
17
|
+
# Raises: binarycookieReaderException
|
18
|
+
def read_cookies
|
19
|
+
raise ChromeCookieReaderException 'No cookie file found' unless File.exists?(cookie_file_path)
|
20
|
+
|
21
|
+
cookies = []
|
22
|
+
db = SQLite3::Database.new(cookie_file_path)
|
23
|
+
db.execute('SELECT name, value, host_key, path, secure, httponly, expires_utc, creation_utc FROM cookies') do |row|
|
24
|
+
cookies << cookie_for_row(row)
|
25
|
+
end
|
26
|
+
|
27
|
+
cookies
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def cookie_for_row(row)
|
33
|
+
# CREATE TABLE cookies (creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,host_key TEXT NOT NULL,name TEXT NOT NULL,value TEXT NOT NULL,path TEXT NOT NULL,expires_utc INTEGER N OT NULL,secure INTEGER NOT NULL,httponly INTEGER NOT NULL,last_access_utc INTEGER NOT NULL, has_expires INTEGER NOT NULL DEFAULT 1, persistent INTEGER NOT NULL DEFAULT 1);
|
34
|
+
name = row[0]
|
35
|
+
value = row[1]
|
36
|
+
domain = row[2]
|
37
|
+
path = row[3]
|
38
|
+
flag = flag(row[4], row[5])
|
39
|
+
expires = row[6]
|
40
|
+
created = row[7]
|
41
|
+
|
42
|
+
QuoraNotify::CookieReaders::Cookie.new(name: name, value: value, domain: domain, path: path, flag: flag, expires: expires, created: created)
|
43
|
+
end
|
44
|
+
|
45
|
+
def flag(secure, httponly)
|
46
|
+
return 'Secure: HttpOnly' if secure == 1 && httponly == 1
|
47
|
+
return 'Secure' if secure == 1
|
48
|
+
return 'HttpOnly' if httponly == 1
|
49
|
+
'Unknown'
|
50
|
+
end
|
51
|
+
|
52
|
+
# Defaults to the standard safari cookie system path
|
53
|
+
def cookie_file_path
|
54
|
+
@cookie_file_path || DEFAULT_CHROME_COOKIE_PATH
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
class QuoraNotify::CookieReaders::Cookie
|
3
|
+
attr_reader :name, :value, :domain, :path, :flag, :expires, :created
|
4
|
+
|
5
|
+
def initialize(opts = {})
|
6
|
+
@name = opts[:name]
|
7
|
+
@value = opts[:value]
|
8
|
+
@domain = opts[:domain]
|
9
|
+
@path = opts[:path]
|
10
|
+
@flag = opts[:flag]
|
11
|
+
@expires = opts[:expires]
|
12
|
+
@created = opts[:created]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
require 'stringio'
|
3
|
+
require 'quora_notify/cookie_readers/cookie'
|
4
|
+
|
5
|
+
class SfariCookieReaderException < StandardError; end
|
6
|
+
|
7
|
+
class QuoraNotify::CookieReaders::SafariCookieReader
|
8
|
+
|
9
|
+
class CookieIO < StringIO
|
10
|
+
def next
|
11
|
+
self.read(4)
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_as_int
|
15
|
+
self.next.unpack('l<')[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_as_flag
|
19
|
+
case self.next_as_int
|
20
|
+
when 0; ''
|
21
|
+
when 1; 'Secure'
|
22
|
+
when 4; 'HttpOnly'
|
23
|
+
when 5; 'Secure: HttpOnly'
|
24
|
+
else; 'Unknown'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_as_date
|
29
|
+
epoch = self.read(8).unpack('E')[0] + 978307200
|
30
|
+
Time.at(epoch).strftime('%a, %d %b %Y')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
DEFAULT_SAFARI_COOKIE_PATH = "#{ENV['HOME']}/Library/Cookies/Cookies.binarycookies"
|
35
|
+
|
36
|
+
# Accepts:
|
37
|
+
# cookie_file_path: Use default cookie file if nil (default)
|
38
|
+
def initialize(file_path = nil)
|
39
|
+
@cookie_file_path = file_path
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns an array of Cookie objects
|
43
|
+
# Raises: binarycookieReaderException
|
44
|
+
def read_cookies
|
45
|
+
raise SafariCookieReaderException 'No cookie file found' unless File.exists?(cookie_file_path)
|
46
|
+
|
47
|
+
File.open(cookie_file_path, 'rb') do |cookie_file|
|
48
|
+
process_file cookie_file
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_file(cookie_file)
|
53
|
+
header = cookie_file.read(4)
|
54
|
+
raise SafariCookieReaderException 'Not recognized as a binarycookie file' unless header == 'cook'
|
55
|
+
|
56
|
+
n_pages = cookie_file.read(4).unpack('l>')[0]
|
57
|
+
sizes = (0..n_pages - 1).collect { |page| cookie_file.read(4).unpack('l>')[0] }
|
58
|
+
pages = sizes.collect { |size| cookie_file.read(size) }
|
59
|
+
|
60
|
+
cookie_groups = pages.collect do |page|
|
61
|
+
page = CookieIO.new(page); page.next
|
62
|
+
|
63
|
+
n_items = page.next_as_int
|
64
|
+
cookie_offsets = (0..n_items - 1).collect { |item| page.next_as_int }
|
65
|
+
|
66
|
+
page.next
|
67
|
+
|
68
|
+
cookie_offsets.collect do |offset|
|
69
|
+
page.seek(offset) # Move to the start of the next page of cookies
|
70
|
+
cookie_for_data CookieIO.new(page.read(page.next_as_int)) # Pulls each cookie out of the page
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
cookie_groups.flatten
|
75
|
+
end
|
76
|
+
|
77
|
+
def cookie_for_data(cookie)
|
78
|
+
cookie.next; flag = cookie.read_as_flag; cookie.next
|
79
|
+
|
80
|
+
domain_off, name_off, path_off, value_off = 4.times.map { cookie.next_as_int }
|
81
|
+
|
82
|
+
cookie.next; cookie.next
|
83
|
+
|
84
|
+
expires, created = 2.times.map { cookie.read_as_date }
|
85
|
+
|
86
|
+
domain, name, path, value = [domain_off, name_off, path_off, value_off].collect do |offset|
|
87
|
+
cookie.seek(offset - 4)
|
88
|
+
|
89
|
+
data = ''
|
90
|
+
while char = cookie.read(1)
|
91
|
+
new_data = char.unpack('c')[0]
|
92
|
+
break if new_data == 0
|
93
|
+
data << new_data
|
94
|
+
end
|
95
|
+
|
96
|
+
data
|
97
|
+
end
|
98
|
+
|
99
|
+
QuoraNotify::CookieReaders::Cookie.new(name: name, value: value, domain: domain, path: path, flag: flag, expires: expires, created: created)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Defaults to the standard safari cookie system path
|
103
|
+
def cookie_file_path
|
104
|
+
@cookie_file_path || DEFAULT_SAFARI_COOKIE_PATH
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
class QuoraNotify::Install
|
5
|
+
|
6
|
+
INSTALL_PATH = File.join(ENV["HOME"], "Library", "LaunchAgents")
|
7
|
+
LAUNCHD_PROCESS_NAME = "com.joeycarmello.quora_notify"
|
8
|
+
LAUNCHD_FILE_NAME = "#{LAUNCHD_PROCESS_NAME}.plist"
|
9
|
+
LAUNCHD_FILE_PATH = File.join("lib", "quora_notify", "config", LAUNCHD_FILE_NAME)
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def run!
|
13
|
+
uninstall!
|
14
|
+
gem_path = ENV['GEM_HOME']
|
15
|
+
ruby_path = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
|
16
|
+
bin_path = `which quora_notify`.chomp
|
17
|
+
template = ERB.new File.read(erb_path)
|
18
|
+
File.write(install_file_path, template.result(binding))
|
19
|
+
start
|
20
|
+
end
|
21
|
+
|
22
|
+
def uninstall!
|
23
|
+
if File.exists?(install_file_path)
|
24
|
+
stop
|
25
|
+
File.delete install_file_path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def stop
|
32
|
+
system %Q[launchctl stop #{LAUNCHD_PROCESS_NAME}]
|
33
|
+
system %Q[launchctl unload #{install_file_path}]
|
34
|
+
end
|
35
|
+
|
36
|
+
def start
|
37
|
+
system %Q[launchctl load #{install_file_path}]
|
38
|
+
system %Q[launchctl start #{LAUNCHD_PROCESS_NAME}]
|
39
|
+
end
|
40
|
+
|
41
|
+
def erb_path
|
42
|
+
"#{LAUNCHD_FILE_PATH}.erb"
|
43
|
+
end
|
44
|
+
|
45
|
+
def install_file_path
|
46
|
+
File.join(INSTALL_PATH, LAUNCHD_FILE_NAME)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'htmlentities'
|
2
|
+
|
3
|
+
class QuoraNotify::Notification
|
4
|
+
|
5
|
+
NOTIFICATION_GROUP = 'com.joeycarmello.quora_notify'
|
6
|
+
NOTIFICATION_TITLE = 'New Notification'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def list
|
10
|
+
notifs = TerminalNotifier.list('ALL') || []
|
11
|
+
notifs.select { |n| n[:group] =~ /^#{NOTIFICATION_GROUP}/ }
|
12
|
+
end
|
13
|
+
|
14
|
+
def clear!
|
15
|
+
list.each { |notif| TerminalNotifier.remove(notif[:group]) }
|
16
|
+
list.size
|
17
|
+
end
|
18
|
+
|
19
|
+
def cleanse_text(text)
|
20
|
+
coder = HTMLEntities.new
|
21
|
+
coder.decode text.gsub(/<.*?>/, '')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :text, :links
|
26
|
+
|
27
|
+
def id
|
28
|
+
"#{NOTIFICATION_GROUP} - #{@text}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Allows for fun things like [a, b] - [a] = [b]
|
32
|
+
def hash
|
33
|
+
self.id.hash
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(notif)
|
37
|
+
@text = self.class.cleanse_text(notif)
|
38
|
+
@links = notif.scan(/href="(.*?)"/).flatten
|
39
|
+
end
|
40
|
+
|
41
|
+
def notify
|
42
|
+
TerminalNotifier.notify(@text, title: NOTIFICATION_TITLE, open: @links.last, group: self.id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def ==(other)
|
46
|
+
other.kind_of?(QuoraNotify::Notification) ? id == other.id : other == id
|
47
|
+
end
|
48
|
+
|
49
|
+
alias :eql? :==
|
50
|
+
end
|
51
|
+
|
data/lib/quora_notify.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'quora_notify'
|
4
|
+
|
5
|
+
class QuoraNotifyTest < Test::Unit::TestCase
|
6
|
+
def test_can_parse_quora_api_response
|
7
|
+
assert_nothing_raised do
|
8
|
+
notifications = QuoraNotify.quora_notifications
|
9
|
+
assert_not_nil notifications['notifs']['unseen_count'], 'Cannot access notifications from response'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_run_will_add_notifications_to_notification_center
|
14
|
+
QuoraNotify::Notification.clear! # start empty
|
15
|
+
fill_with_mocks
|
16
|
+
# list real local notifs
|
17
|
+
notifications = QuoraNotify::Notification.list
|
18
|
+
assert_equal mock_notifications['notifs']['unseen_count'], notifications.size
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_run_will_not_repeat_existing_notifications
|
22
|
+
QuoraNotify::Notification.clear! # start empty
|
23
|
+
existing_notifs = fill_with_mocks # add some notifications
|
24
|
+
new_notifs = fill_with_mocks # add the same ones again
|
25
|
+
assert_equal 0, new_notifs.size
|
26
|
+
assert_equal existing_notifs.size + new_notifs.size, QuoraNotify::Notification.list.size
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_clear_will_remove_all_notifications_from_notification_center
|
30
|
+
fill_with_mocks
|
31
|
+
QuoraNotify::Notification.clear!
|
32
|
+
assert_equal 0, QuoraNotify::Notification.list.size
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_run_will_process_if_notifications_are_present
|
36
|
+
QuoraNotify.expects(:process).once
|
37
|
+
fill_with_mocks
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def fill_with_mocks
|
43
|
+
# create some notifications
|
44
|
+
QuoraNotify.expects(:quora_notifications).returns(mock_notifications)
|
45
|
+
# go fetch for the fake ones, creating real local notifs
|
46
|
+
QuoraNotify.run!
|
47
|
+
end
|
48
|
+
|
49
|
+
def mock_notifications
|
50
|
+
{
|
51
|
+
'notifs' => {
|
52
|
+
'unseen_count' => 2,
|
53
|
+
'unseen' => [
|
54
|
+
'<a href="http://quora.com">Some text</a>',
|
55
|
+
'<a href="http://quora.com">Some text 2</a>'
|
56
|
+
]
|
57
|
+
}
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def mock_empty_notifications
|
62
|
+
{
|
63
|
+
'notifs' => {
|
64
|
+
'unseen_count' => 0,
|
65
|
+
'unseen' => []
|
66
|
+
}
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: quora_notify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joey Carmello
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: terminal-notifier
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: htmlentities
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
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: |2
|
70
|
+
QuoraNotify provides basic access to one of the few API's Quora.com has opened to the public.
|
71
|
+
It uses local quora cookies to access this API as a logged-in user.
|
72
|
+
|
73
|
+
See https://www.quora.com/Edmond-Lau/Edmond-Laus-Posts/Quora-Extension-API for more information about this Alpha API.
|
74
|
+
email: joeycarmello@me.com
|
75
|
+
executables:
|
76
|
+
- quora_notify
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- lib/quora_notify/base.rb
|
81
|
+
- lib/quora_notify/cookie_readers/chrome_cookie_reader.rb
|
82
|
+
- lib/quora_notify/cookie_readers/cookie.rb
|
83
|
+
- lib/quora_notify/cookie_readers/safari_cookie_reader.rb
|
84
|
+
- lib/quora_notify/cookie_readers.rb
|
85
|
+
- lib/quora_notify/install.rb
|
86
|
+
- lib/quora_notify/notification.rb
|
87
|
+
- lib/quora_notify/version.rb
|
88
|
+
- lib/quora_notify.rb
|
89
|
+
- bin/quora_notify
|
90
|
+
- test/test_quora_notify.rb
|
91
|
+
- Gemfile
|
92
|
+
- Gemfile.lock
|
93
|
+
- LICENSE.txt
|
94
|
+
- Rakefile
|
95
|
+
- README.md
|
96
|
+
homepage: http://github.com/joeycarmello/QuoraNotifier
|
97
|
+
licenses: []
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 2.0.3
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: Displays Quora notifications in OSX Mountain Lion's Notification Center
|
119
|
+
test_files: []
|