pollter_geist 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05f056b84468423bb3113a3bc2e844e3c3dabb7e
4
- data.tar.gz: 78cc138e11dd795c7cc106c81eff536c98117175
3
+ metadata.gz: 03fbdbda08f63a1cf041006fc4ae9c31447e078f
4
+ data.tar.gz: c8b3ba475deffa7328ae24ac6702115793210aa1
5
5
  SHA512:
6
- metadata.gz: 8c08c5c6b54cd65e0ab5ebff4013fae453f2cccfdb2552091475744cdc421e6f16764c7b5583784f3b5d5758116f6c2779c764783e28dac6804878cf93f7219d
7
- data.tar.gz: a1184580b5972401a0e31e18a31015dd1a56c04bc38b250bd0369195963ea5486ce4443ca4c53f1c272cd21d98fabdd273eda21723a57c6341e91feb450836ff
6
+ metadata.gz: ebf69e6c55a0724232051b3295d60284ed078d4d7f18ae62c25da94bfecf3e4a76d4461afbaec0730bd2536aac3eb6ccf16c4729ae1b3714c54efbba79d953ed
7
+ data.tar.gz: c21efcbc291ac43e2e074481950e1c4a0378bb3c2dafc610df451d0b968814e1b0916f7383bc42a260c2e2f61b5d59ffc5ca9e322b5bceea25c0c680a54e8ceb
data/lib/pollter_geist.rb CHANGED
@@ -6,3 +6,4 @@ end
6
6
  require_relative 'pollter_geist/imap_commands'
7
7
  require_relative 'pollter_geist/imap_idler'
8
8
  require_relative 'pollter_geist/poller'
9
+ require_relative 'pollter_geist/change_listener'
@@ -0,0 +1,38 @@
1
+ module PollterGeist
2
+ class ChangeListener
3
+ def initialize
4
+ @previous = []
5
+ @current = []
6
+ @added = []
7
+ @removed = []
8
+ end
9
+
10
+ def tick current
11
+ @previous = @current
12
+ @current = current
13
+
14
+ @added = @current - @previous
15
+ @removed = @previous - @current
16
+ end
17
+
18
+ def added
19
+ @added
20
+ end
21
+
22
+ def added?
23
+ !added.empty?
24
+ end
25
+
26
+ def removed?
27
+ !removed.empty?
28
+ end
29
+
30
+ def changed?
31
+ added? || removed?
32
+ end
33
+
34
+ def removed
35
+ @removed
36
+ end
37
+ end
38
+ end
@@ -15,13 +15,15 @@ module PollterGeist
15
15
  # Issues IDLE command for the imap server, it takes a list of events to listen for and returns once one of
16
16
  # events occured or if there was a timeout.
17
17
  #
18
- # @param events [events] a list of events to listen for, EXPUNGE, RECENT
18
+ # @param events [events] a list of events to listen for, EXPUNGE, RECENT, EXISTS
19
19
  # @param timeout [Numeric] a timeout, if no event has ocoured for this time
20
20
  # @return will return an object which responds to #success?, #timeout? and #event
21
21
  def wait_for events, timeout = 29*60
22
22
  @idler.idle(events, timeout)
23
23
  end
24
24
 
25
+ # fetches a list of message UIDs
26
+ # @return [Array] of message UIDs
25
27
  def message_uids
26
28
  @logger.debug('fetching uids')
27
29
  # Searching for all messages where TO include @ is a workaround, since the imap#status method
@@ -31,11 +33,36 @@ module PollterGeist
31
33
  result.map { |r| r.attr['UID'].to_i }
32
34
  end
33
35
 
36
+ def remove uid
37
+ @logger.debug("removing #{uid}")
38
+ @imap.uid_store uid, "+FLAGS", [:Deleted]
39
+ end
40
+
41
+ def expunge
42
+ @logger.debug("expunge, remove all messages with Delete flag")
43
+ @imap.expunge
44
+ end
45
+
34
46
  def fetch uids
35
47
  logger.debug "fetching: #{uids}"
36
48
  @imap.uid_fetch(uids, ['RFC822']).map { |r| r.attr['RFC822'] }
37
49
  end
38
50
 
51
+ def wait_for_changes timeout = 20*60
52
+ logger.debug('waiting for changes in inbox')
53
+ change_set = ChangeListener.new
54
+ change_set.tick(message_uids)
55
+ result = wait_for(['RECENT', 'EXPUNGE'], timeout)
56
+ logger.debug('updating current view')
57
+ change_set.tick(message_uids)
58
+ if change_set.changed?
59
+ logger.debug('changes detected!')
60
+ yield(change_set)
61
+ else
62
+ logger.debug('no changes detected')
63
+ end
64
+ end
65
+
39
66
  def logger
40
67
  @logger
41
68
  end
@@ -1,4 +1,6 @@
1
1
  require 'timeout'
2
+ require 'thread'
3
+
2
4
  module PollterGeist
3
5
  class ImapIdler
4
6
  class IdleResult
@@ -26,21 +28,30 @@ module PollterGeist
26
28
  end
27
29
 
28
30
  def idle listen_for = ['RECENT'], timeout = false
29
- begin
30
- Timeout::timeout(timeout) do
31
- loop do
32
- event = do_idle
33
- if listen_for.include? event
34
- return IdleResult.new(true, event)
35
- else
36
- logger.debug "nope, we are not listening for #{event}"
31
+ Thread.handle_interrupt(Timeout::Error => :never, Interrupt => :never) do
32
+ begin
33
+ Timeout::timeout(timeout) do
34
+ loop do
35
+ event = nil
36
+ Thread.handle_interrupt(Timeout::Error => :immediate, Interrupt => :on_blocking) {
37
+ event = do_idle
38
+ }
39
+ if listen_for.include? event
40
+ logger.debug("returning event #{event} to caller")
41
+ return IdleResult.new(true, event)
42
+ else
43
+ logger.debug "nope, we are not listening for #{event}"
44
+ end
37
45
  end
38
46
  end
47
+ rescue Timeout::Error
48
+ imap.idle_done
49
+ logger.debug 'idle timed out'
50
+ return IdleResult.new(false, 'TIMEOUT')
51
+ rescue Interrupt => e
52
+ logger.debug 'idle was interrupted'
53
+ raise e
39
54
  end
40
- rescue Timeout::Error
41
- imap.idle_done
42
- logger.debug 'idle timed out'
43
- return IdleResult.new(false, 'TIMEOUT')
44
55
  end
45
56
  end
46
57
 
@@ -54,12 +65,15 @@ module PollterGeist
54
65
  end
55
66
 
56
67
  def do_idle
57
- event = ''
68
+ @events ||= Queue.new
69
+ until @events.empty?
70
+ return @events.pop
71
+ end
58
72
  imap.idle do |message|
59
73
  case message
60
74
  when Net::IMAP::UntaggedResponse
61
75
  logger.debug "event: #{message.name}, data: #{message.data}"
62
- event = message.name
76
+ @events.push(message.name)
63
77
  imap.idle_done
64
78
  when Net::IMAP::ContinuationRequest
65
79
  logger.debug 'IDLE accepted by the server'
@@ -67,7 +81,8 @@ module PollterGeist
67
81
  logger.warn "Unhandled IDLE response: #{message.class}, #{message.inspect}"
68
82
  end
69
83
  end
70
- event
84
+ logger.debug 'returning from idle'
85
+ @events.pop
71
86
  end
72
87
  end
73
88
  end
@@ -1,3 +1,3 @@
1
1
  module PollterGeist
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency('mail')
22
+ spec.add_dependency('virtus')
23
+
21
24
  spec.add_development_dependency "bundler", "~> 1.3"
22
25
  spec.add_development_dependency "minitest", "~> 5.0.6"
23
26
  spec.add_development_dependency "rake"
@@ -0,0 +1,46 @@
1
+ require 'test_helper'
2
+
3
+ describe PollterGeist::ChangeListener do
4
+ describe '#new' do
5
+ it 'should allow empty' do
6
+ PollterGeist::ChangeListener.new
7
+ end
8
+ end
9
+
10
+ describe '#added' do
11
+ it 'should show added messages' do
12
+ cl = PollterGeist::ChangeListener.new
13
+ cl.added.must_be_kind_of Array
14
+ cl.added.must_be_empty
15
+
16
+ cl.tick([1, 2, 3])
17
+ cl.added.wont_be_empty
18
+ cl.added.must_include 1
19
+ cl.added.must_include 2
20
+ cl.added.must_include 3
21
+ cl.tick([1, 4])
22
+ cl.added.size.must_equal 1
23
+ cl.tick([])
24
+ cl.added.must_be_empty
25
+ end
26
+ end
27
+
28
+ describe '#removed' do
29
+ it 'should show removed messages' do
30
+ cl = PollterGeist::ChangeListener.new
31
+ cl.removed.must_be_kind_of Array
32
+ cl.removed.must_be_empty
33
+
34
+ cl.tick([1, 2, 3])
35
+ cl.removed.must_be_empty
36
+ cl.tick([1, 4])
37
+ cl.removed.size.must_equal 2
38
+ cl.removed.must_include 2
39
+ cl.removed.must_include 3
40
+ cl.tick([])
41
+ cl.removed.wont_be_empty
42
+ cl.tick([])
43
+ cl.removed.must_be_empty
44
+ end
45
+ end
46
+ end
@@ -3,10 +3,36 @@ require 'test_helper'
3
3
  describe PollterGeist::Poller do
4
4
  describe '#session' do
5
5
  it 'should create a session' do
6
- poller = PollterGeist::Poller.new(CONFIG)
6
+ poller = PollterGeist::Poller.new(CONFIG)
7
+ changer = PollterGeist::ChangeListener.new
7
8
  poller.session do |imap|
8
9
  imap.select_mailbox('INBOX')
9
- imap.wait_for('RECENT', 1)
10
+ uids = imap.message_uids
11
+ changer.tick(uids)
12
+ changer.tick(uids)
13
+
14
+
15
+ =begin
16
+ 1.times do
17
+ imap.wait_for('RECENT', 1)
18
+ changer.tick(imap.message_uids)
19
+ imap.logger.debug("+#{changer.added} -#{changer.removed}")
20
+ if changer.added?
21
+ puts imap.fetch(changer.added)
22
+ end
23
+ end
24
+ =end
25
+
26
+
27
+ loop do
28
+ begin
29
+ imap.wait_for_changes(10 * 60) do |changes|
30
+ imap.logger.debug(changes)
31
+ end
32
+ rescue Interrupt => e
33
+ break
34
+ end
35
+ end
10
36
  end
11
37
  end
12
38
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pollter_geist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - kwando
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-23 00:00:00.000000000 Z
11
+ date: 2013-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mail
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: virtus
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'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -65,12 +93,14 @@ files:
65
93
  - README.md
66
94
  - Rakefile
67
95
  - lib/pollter_geist.rb
96
+ - lib/pollter_geist/change_listener.rb
68
97
  - lib/pollter_geist/imap_commands.rb
69
98
  - lib/pollter_geist/imap_idler.rb
70
99
  - lib/pollter_geist/poller.rb
71
100
  - lib/pollter_geist/version.rb
72
101
  - pollter_geist.gemspec
73
102
  - test/test_helper.rb
103
+ - test/unit/pollter_geist/change_listener_test.rb
74
104
  - test/unit/pollter_geist/poller_test.rb
75
105
  - test/unit/pollter_geist_test.rb
76
106
  homepage: ''
@@ -99,5 +129,6 @@ specification_version: 4
99
129
  summary: A small abstraction layer for polling IMAP servers for changes.
100
130
  test_files:
101
131
  - test/test_helper.rb
132
+ - test/unit/pollter_geist/change_listener_test.rb
102
133
  - test/unit/pollter_geist/poller_test.rb
103
134
  - test/unit/pollter_geist_test.rb