quora_notify 0.0.7 → 0.0.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2e83b718291fe349330076b9e419979994700fc
4
- data.tar.gz: ce758c4e070950ce22d476fe8528832b547eb685
3
+ metadata.gz: 18a733e9ecd69603d65c8446b7b2ed93d8f37c69
4
+ data.tar.gz: ffc967ed622f81bc98351421ee28b03bc9d39952
5
5
  SHA512:
6
- metadata.gz: b07cbb3b8a2a6a80c15cd1c0d3489b3ecf574b95cdc66a2aac699f4ecf046c912015fbe8dfe1649bba73392eb895312beb6613f7bfd2e3a161254de640e04491
7
- data.tar.gz: 9bff482d70fd30f821cfb0f0e3396bce26d09cfe8027eb630048469b93d913db9ad1afa281785b4d83bce31475d813f92c0a1d69fcc7be9b1e42fce326d38b2e
6
+ metadata.gz: 630b7abc59ea8d58b0430aadc07250c8a9344e878602be73c00fc927edfa14bcd4b8fbc157ab6503f987d57e62b3c34a9c4288b06005cf6f0d7e038172a2f058
7
+ data.tar.gz: 76a5838745afafec15c41849a1e8b4e7db59c0d121b9805060ce43c2b747f56f8c3f0b2a043734629bc4ff80bff73406a2bcec403aefe27afebe629940be7ea8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quora_notify (0.0.6)
4
+ quora_notify (0.0.7)
5
5
  htmlentities
6
6
  sqlite3
7
7
  terminal-notifier
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Receive quora.com notifications in Notification Center on OSX Mountain Lion.
4
4
 
5
+ Due to the hackish way this currently works (using local cookies), only certain versions of Safari, Chrome, and Firefox are supported for now.
6
+
5
7
  ## Installation
6
8
 
7
9
  Install a launchAgent to poll Quora for notifications
data/Rakefile CHANGED
@@ -2,7 +2,10 @@ require 'rake/testtask'
2
2
  require "bundler/gem_tasks"
3
3
 
4
4
  Rake::TestTask.new do |t|
5
- t.libs << 'test'
5
+ t.libs << "test"
6
+ t.pattern = "test/**/test_*.rb"
7
+ t.warning = true
8
+ t.verbose = true
6
9
  end
7
10
 
8
11
  desc "Run all tests"
data/lib/quora_notify.rb CHANGED
@@ -1,5 +1,8 @@
1
+ require 'quora_notify/version'
2
+ require 'quora_notify/exceptions'
1
3
  require 'quora_notify/base'
2
4
  require 'quora_notify/install'
5
+ require 'quora_notify/cookie'
3
6
  require 'quora_notify/cookie_readers'
4
7
  require 'quora_notify/notification'
5
8
 
@@ -3,17 +3,14 @@ require 'json'
3
3
  require 'terminal-notifier'
4
4
 
5
5
  module QuoraNotify
6
-
7
6
  API_NOTIFICATION_PATH = 'http://api.quora.com/api/logged_in_user?fields=notifs'
8
7
  TMP_COOKIE_PATH = '/tmp/quora_notifier'
9
8
 
10
9
  class << self
11
10
  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)
11
+ fetch_notifications_with_cookies quora_cookies do |notifications|
12
+ JSON.parse(notifications)
13
+ end
17
14
  end
18
15
 
19
16
  def run!
@@ -27,6 +24,13 @@ module QuoraNotify
27
24
 
28
25
  private
29
26
 
27
+ def fetch_notifications_with_cookies(cookies)
28
+ write_cookies_to_file(cookies, TMP_COOKIE_PATH)
29
+ response = `curl #{API_NOTIFICATION_PATH} -b #{TMP_COOKIE_PATH}`.sub('while(1);', '')
30
+ File.delete TMP_COOKIE_PATH
31
+ yield response
32
+ end
33
+
30
34
  def process(notifications)
31
35
  return [] if notifications.empty? || notifications['notifs']['unseen_count'] == 0
32
36
 
@@ -36,17 +40,18 @@ module QuoraNotify
36
40
  end
37
41
 
38
42
  def write_cookies_to_file(cookies, file)
39
- File.open(file, 'w') do |file|
43
+ File.open(file, 'w') do |f|
40
44
  cookies.each do |cookie|
41
45
  # 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}"
46
+ f.puts "#{cookie.domain}\tTRUE\t#{cookie.path}\tFALSE\t#{cookie.expires}\t#{cookie.name}\t#{cookie.value}"
43
47
  end
44
48
  end
45
49
  end
46
50
 
47
- def quora_cookies_for_browser(browser)
51
+ def quora_cookies
48
52
  readers = [
49
53
  CookieReaders::ChromeCookieReader.new,
54
+ CookieReaders::FirefoxCookieReader.new,
50
55
  CookieReaders::SafariCookieReader.new
51
56
  ]
52
57
 
@@ -54,6 +59,8 @@ module QuoraNotify
54
59
  begin
55
60
  reader.read_cookies
56
61
  rescue => e
62
+ puts e.message
63
+ puts e.backtrace
57
64
  []
58
65
  end
59
66
  end.flatten.uniq.select { |cookie| cookie.domain == '.quora.com' }
@@ -0,0 +1,15 @@
1
+ module QuoraNotify
2
+ class 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
15
+ end
@@ -1,5 +1,33 @@
1
+ require 'stringio'
2
+
1
3
  module QuoraNotify::CookieReaders
4
+ class CookieIO < StringIO
5
+ def next
6
+ self.read(4)
7
+ end
8
+
9
+ def next_as_int
10
+ self.next.unpack('l<')[0]
11
+ end
12
+
13
+ def read_as_flag
14
+ case self.next_as_int
15
+ when 0; ''
16
+ when 1; 'Secure'
17
+ when 4; 'HttpOnly'
18
+ when 5; 'Secure: HttpOnly'
19
+ else; 'Unknown'
20
+ end
21
+ end
22
+
23
+ def read_as_date
24
+ epoch = self.read(8).unpack('E')[0] + 978307200
25
+ Time.at(epoch).strftime('%a, %d %b %Y')
26
+ end
27
+ end
2
28
  end
3
29
 
30
+ require 'quora_notify/cookie_readers/cookie_reader'
31
+ require 'quora_notify/cookie_readers/firefox_cookie_reader'
4
32
  require 'quora_notify/cookie_readers/safari_cookie_reader'
5
33
  require 'quora_notify/cookie_readers/chrome_cookie_reader'
@@ -1,56 +1,35 @@
1
1
  require 'sqlite3'
2
- require 'quora_notify/cookie_readers/cookie'
3
2
 
4
- class ChromeCookieReaderException < StandardError; end
3
+ module QuoraNotify::CookieReaders
4
+ class ChromeCookieReader < CookieReader
5
+ DEFAULT_COOKIE_PATH = "#{ENV['HOME']}/Library/Application Support/Google/Chrome/Default/Cookies"
5
6
 
6
- class QuoraNotify::CookieReaders::ChromeCookieReader
7
+ # Returns an array of Cookie objects
8
+ # Raises: binarycookieReaderException
9
+ def read_cookies
10
+ raise QuoraNotify::Exceptions::CookieReaderException, 'No cookie file found' unless File.exists?(cookie_file_path)
7
11
 
8
- DEFAULT_CHROME_COOKIE_PATH = "#{ENV['HOME']}/Library/Application Support/Google/Chrome/Default/Cookies"
12
+ cookies = []
13
+ db = SQLite3::Database.new(cookie_file_path)
14
+ db.execute('SELECT name, value, host_key, path, secure, httponly, expires_utc, creation_utc FROM cookies') do |row|
15
+ cookies << cookie_for_row(row)
16
+ end
9
17
 
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)
18
+ cookies
25
19
  end
26
20
 
27
- cookies
28
- end
29
-
30
- private
21
+ private
31
22
 
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]
23
+ def cookie_for_row(row)
24
+ name = row[0]
25
+ value = row[1]
26
+ domain = row[2]
27
+ path = row[3]
28
+ flag = flag(row[4], row[5])
29
+ expires = row[6]
30
+ created = row[7]
41
31
 
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
32
+ QuoraNotify::Cookie.new(name: name, value: value, domain: domain, path: path, flag: flag, expires: expires, created: created)
33
+ end
34
+ end
56
35
  end
@@ -0,0 +1,32 @@
1
+ module QuoraNotify::CookieReaders
2
+ # Subclasses should define a DEFAULT_COOKIE_PATH constant
3
+ # that will be used if no file path is provided to the constructor
4
+ class CookieReader
5
+ DEFAULT_COOKIE_PATH = nil
6
+ # Accepts:
7
+ # cookie_file_path: Use DEFAULT_COOKIE_PATH if nil (default)
8
+ def initialize(file_path = nil)
9
+ @cookie_file_path = file_path
10
+ end
11
+
12
+ # Returns an array of Cookie objects
13
+ # Raises: binarycookieReaderException
14
+ def read_cookies
15
+ raise QuoraNotify::Exceptions::CookieReaderException, 'Not implemented'
16
+ end
17
+
18
+ # Defaults to the standard safari cookie system path
19
+ def cookie_file_path
20
+ @cookie_file_path || self.class::DEFAULT_COOKIE_PATH
21
+ end
22
+
23
+ protected
24
+
25
+ def flag(secure, httponly)
26
+ return 'Secure: HttpOnly' if secure == 1 && httponly == 1
27
+ return 'Secure' if secure == 1
28
+ return 'HttpOnly' if httponly == 1
29
+ 'Unknown'
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ require 'sqlite3'
2
+
3
+ module QuoraNotify::CookieReaders
4
+ class FirefoxCookieReader < CookieReader
5
+ DEFAULT_COOKIE_PATH = "#{ENV['HOME']}/Library/Application Support/Firefox/Profiles/*/cookies.sqlite"
6
+
7
+ # Returns an array of Cookie objects
8
+ # Raises: binarycookieReaderException
9
+ def read_cookies
10
+ cookie_file = Dir[cookie_file_path][0]
11
+ raise QuoraNotify::Exceptions::CookieReaderException, 'No cookie file found' unless cookie_file && File.exists?(cookie_file)
12
+
13
+ cookies = []
14
+ db = SQLite3::Database.new(cookie_file)
15
+ db.execute('SELECT name, value, baseDomain, path, isSecure, isHttpOnly, expiry, creationTime FROM moz_cookies') do |row|
16
+ cookies << cookie_for_row(row)
17
+ end
18
+
19
+ cookies
20
+ end
21
+
22
+ private
23
+
24
+ def cookie_for_row(row)
25
+ name = row[0]
26
+ value = row[1]
27
+ domain = row[2]
28
+ path = row[3]
29
+ flag = flag(row[4], row[5])
30
+ expires = row[6]
31
+ created = row[7]
32
+
33
+ QuoraNotify::Cookie.new(name: name, value: value, domain: domain, path: path, flag: flag, expires: expires, created: created)
34
+ end
35
+ end
36
+ end
@@ -1,107 +1,67 @@
1
+ module QuoraNotify::CookieReaders
2
+ class SafariCookieReader < CookieReader
3
+ DEFAULT_COOKIE_PATH = "#{ENV['HOME']}/Library/Cookies/Cookies.binarycookies"
1
4
 
2
- require 'stringio'
3
- require 'quora_notify/cookie_readers/cookie'
5
+ # Returns an array of Cookie objects
6
+ # Raises: CookieReaderException
7
+ def read_cookies
8
+ raise QuoraNotify::Exceptions::CookieReaderException, 'No cookie file found' unless File.exists?(cookie_file_path)
4
9
 
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'
10
+ File.open(cookie_file_path, 'rb') do |cookie_file|
11
+ process_file cookie_file
25
12
  end
26
13
  end
27
14
 
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"
15
+ private
35
16
 
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
17
+ def process_file(cookie_file)
18
+ header = cookie_file.read(4)
19
+ raise QuoraNotify::Exceptions::CookieReaderException, 'Not recognized as a binarycookie file' unless header == 'cook'
41
20
 
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)
21
+ n_pages = cookie_file.read(4).unpack('l>')[0]
22
+ sizes = (0..n_pages - 1).collect { |page| cookie_file.read(4).unpack('l>')[0] }
23
+ pages = sizes.collect { |size| cookie_file.read(size) }
46
24
 
47
- File.open(cookie_file_path, 'rb') do |cookie_file|
48
- process_file cookie_file
49
- end
50
- end
25
+ cookie_groups = pages.collect do |page|
26
+ page = CookieIO.new(page); page.next
51
27
 
52
- def process_file(cookie_file)
53
- header = cookie_file.read(4)
54
- raise SafariCookieReaderException 'Not recognized as a binarycookie file' unless header == 'cook'
28
+ n_items = page.next_as_int
29
+ cookie_offsets = (0..n_items - 1).collect { |item| page.next_as_int }
55
30
 
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) }
31
+ page.next
59
32
 
60
- cookie_groups = pages.collect do |page|
61
- page = CookieIO.new(page); page.next
33
+ cookie_offsets.collect do |offset|
34
+ page.seek(offset) # Move to the start of the next page of cookies
35
+ cookie_for_data CookieIO.new(page.read(page.next_as_int)) # Pulls each cookie out of the page
36
+ end
37
+ end
62
38
 
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
39
+ cookie_groups.flatten
71
40
  end
72
- end
73
41
 
74
- cookie_groups.flatten
75
- end
42
+ def cookie_for_data(cookie)
43
+ cookie.next; flag = cookie.read_as_flag; cookie.next
76
44
 
77
- def cookie_for_data(cookie)
78
- cookie.next; flag = cookie.read_as_flag; cookie.next
45
+ domain_off, name_off, path_off, value_off = 4.times.map { cookie.next_as_int }
79
46
 
80
- domain_off, name_off, path_off, value_off = 4.times.map { cookie.next_as_int }
47
+ cookie.next; cookie.next
81
48
 
82
- cookie.next; cookie.next
49
+ expires, created = 2.times.map { cookie.read_as_date }
83
50
 
84
- expires, created = 2.times.map { cookie.read_as_date }
51
+ domain, name, path, value = [domain_off, name_off, path_off, value_off].collect do |offset|
52
+ cookie.seek(offset - 4)
85
53
 
86
- domain, name, path, value = [domain_off, name_off, path_off, value_off].collect do |offset|
87
- cookie.seek(offset - 4)
54
+ data = ''
55
+ while char = cookie.read(1)
56
+ new_data = char.unpack('c')[0]
57
+ break if new_data == 0
58
+ data << new_data
59
+ end
88
60
 
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
61
+ data
62
+ end
95
63
 
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
64
+ QuoraNotify::Cookie.new(name: name, value: value, domain: domain, path: path, flag: flag, expires: expires, created: created)
65
+ end
105
66
  end
106
-
107
67
  end
@@ -0,0 +1,4 @@
1
+ module QuoraNotify::Exceptions
2
+ class QNError < StandardError; end
3
+ class CookieReaderException < QNError; end
4
+ end
@@ -2,7 +2,6 @@ require "fileutils"
2
2
  require 'erb'
3
3
 
4
4
  class QuoraNotify::Install
5
-
6
5
  INSTALL_PATH = File.join(ENV["HOME"], "Library", "LaunchAgents")
7
6
  LAUNCHD_PROCESS_NAME = "com.joeycarmello.quora_notify"
8
7
  LAUNCHD_FILE_NAME = "#{LAUNCHD_PROCESS_NAME}.plist"
@@ -11,9 +10,12 @@ class QuoraNotify::Install
11
10
  class << self
12
11
  def run!
13
12
  uninstall!
13
+
14
+ # Used with the ERB binding
14
15
  gem_path = ENV['GEM_HOME']
15
16
  ruby_path = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
16
17
  bin_path = `which quora_notify`.chomp
18
+
17
19
  template = ERB.new File.read(erb_path)
18
20
  File.write(install_file_path, template.result(binding))
19
21
  start
@@ -1,3 +1,3 @@
1
1
  module QuoraNotify
2
- VERSION = '0.0.7'
2
+ VERSION = '0.0.9'
3
3
  end
@@ -0,0 +1,49 @@
1
+ require 'test/unit'
2
+ require 'quora_notify'
3
+ require 'mocha/setup'
4
+ require 'fileutils'
5
+
6
+ def fill_with_mocks
7
+ # create some notifications
8
+ QuoraNotify.expects(:quora_notifications).returns(mock_notifications)
9
+ # go fetch for the fake ones, creating real local notifs
10
+ QuoraNotify.run!
11
+ end
12
+
13
+ def mock_notifications
14
+ {
15
+ 'notifs' => {
16
+ 'unseen_count' => 2,
17
+ 'unseen' => [
18
+ '<a href="http://quora.com">Some text</a>',
19
+ '<a href="http://quora.com">Some text 2</a>'
20
+ ]
21
+ }
22
+ }
23
+ end
24
+
25
+ def mock_empty_notifications
26
+ {
27
+ 'notifs' => {
28
+ 'unseen_count' => 0,
29
+ 'unseen' => []
30
+ }
31
+ }
32
+ end
33
+
34
+ def make_tmp_file_for_reference
35
+ tmp_path = '/tmp/some_file_that_will_be_deleted'
36
+ FileUtils.touch(tmp_path)
37
+ yield tmp_path if block_given?
38
+ File.delete tmp_path
39
+ end
40
+
41
+ class MockSqlite3DBResults
42
+ NUMBER_OF_COOKIES = 3
43
+
44
+ def execute(query)
45
+ result = NUMBER_OF_COOKIES.times.collect { ['name', 'value', 'host', 'path', 1, 0, Time.now.to_i, Time.now.to_i] }
46
+ result.each { |row| yield row } if block_given?
47
+ result
48
+ end
49
+ end
@@ -1,6 +1,4 @@
1
- require 'test/unit'
2
- require 'mocha/setup'
3
- require 'quora_notify'
1
+ require 'test_helper'
4
2
 
5
3
  class QuoraNotifyTest < Test::Unit::TestCase
6
4
  def test_can_parse_quora_api_response
@@ -37,33 +35,4 @@ class QuoraNotifyTest < Test::Unit::TestCase
37
35
  fill_with_mocks
38
36
  end
39
37
 
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
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quora_notify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joey Carmello
@@ -14,58 +14,58 @@ dependencies:
14
14
  name: terminal-notifier
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sqlite3
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: htmlentities
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '4.3'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '4.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mocha
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.13'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.13'
69
69
  description: |2
70
70
  QuoraNotify provides basic access to one of the few API's Quora.com has opened to the public.
71
71
  It uses local quora cookies to access this API as a logged-in user.
@@ -78,15 +78,19 @@ extensions: []
78
78
  extra_rdoc_files: []
79
79
  files:
80
80
  - lib/quora_notify/base.rb
81
+ - lib/quora_notify/cookie.rb
81
82
  - lib/quora_notify/cookie_readers/chrome_cookie_reader.rb
82
- - lib/quora_notify/cookie_readers/cookie.rb
83
+ - lib/quora_notify/cookie_readers/cookie_reader.rb
84
+ - lib/quora_notify/cookie_readers/firefox_cookie_reader.rb
83
85
  - lib/quora_notify/cookie_readers/safari_cookie_reader.rb
84
86
  - lib/quora_notify/cookie_readers.rb
87
+ - lib/quora_notify/exceptions.rb
85
88
  - lib/quora_notify/install.rb
86
89
  - lib/quora_notify/notification.rb
87
90
  - lib/quora_notify/version.rb
88
91
  - lib/quora_notify.rb
89
92
  - bin/quora_notify
93
+ - test/test_helper.rb
90
94
  - test/test_quora_notify.rb
91
95
  - Gemfile
92
96
  - Gemfile.lock
@@ -1,14 +0,0 @@
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