2018-01-11 19:17:11 +02:00
|
|
|
package events
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/emersion/hydroxide/protonmail"
|
|
|
|
)
|
|
|
|
|
2018-01-12 14:20:17 +02:00
|
|
|
const pollInterval = 30 * time.Second
|
2018-01-11 19:17:11 +02:00
|
|
|
|
2018-01-13 12:35:10 +02:00
|
|
|
type Receiver struct {
|
|
|
|
c *protonmail.Client
|
|
|
|
|
2018-10-21 13:15:20 +03:00
|
|
|
locker sync.Mutex
|
2018-01-13 12:35:10 +02:00
|
|
|
channels []chan<- *protonmail.Event
|
|
|
|
|
|
|
|
poll chan struct{}
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|
|
|
|
|
2018-01-13 12:35:10 +02:00
|
|
|
func (r *Receiver) receiveEvents() {
|
2018-01-11 19:17:11 +02:00
|
|
|
t := time.NewTicker(pollInterval)
|
|
|
|
defer t.Stop()
|
|
|
|
|
2018-01-13 12:35:10 +02:00
|
|
|
var last string
|
|
|
|
for {
|
|
|
|
event, err := r.c.GetEvent(last)
|
2018-01-11 19:17:11 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Println("cannot receive event:", err)
|
2019-06-22 12:56:15 +03:00
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
case <-r.poll:
|
|
|
|
}
|
2018-01-11 19:17:11 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
last = event.ID
|
|
|
|
|
|
|
|
r.locker.Lock()
|
2018-01-12 14:20:17 +02:00
|
|
|
n := len(r.channels)
|
2018-01-11 19:17:11 +02:00
|
|
|
for _, ch := range r.channels {
|
|
|
|
ch <- event
|
|
|
|
}
|
|
|
|
r.locker.Unlock()
|
2018-01-12 14:20:17 +02:00
|
|
|
|
|
|
|
if n == 0 {
|
|
|
|
break
|
|
|
|
}
|
2018-01-13 12:35:10 +02:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
case <-r.poll:
|
|
|
|
}
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-13 12:35:10 +02:00
|
|
|
func (r *Receiver) Poll() {
|
|
|
|
r.poll <- struct{}{}
|
|
|
|
}
|
|
|
|
|
2018-01-11 19:17:11 +02:00
|
|
|
type Manager struct {
|
2018-01-13 12:35:10 +02:00
|
|
|
receivers map[string]*Receiver
|
2018-10-21 13:15:20 +03:00
|
|
|
locker sync.Mutex
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewManager() *Manager {
|
|
|
|
return &Manager{
|
2018-01-13 12:35:10 +02:00
|
|
|
receivers: make(map[string]*Receiver),
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-13 12:35:10 +02:00
|
|
|
func (m *Manager) Register(c *protonmail.Client, username string, ch chan<- *protonmail.Event, done <-chan struct{}) *Receiver {
|
2018-01-11 19:17:11 +02:00
|
|
|
m.locker.Lock()
|
|
|
|
defer m.locker.Unlock()
|
|
|
|
|
2018-01-12 14:20:17 +02:00
|
|
|
r, ok := m.receivers[username]
|
|
|
|
if ok {
|
2018-01-11 19:17:11 +02:00
|
|
|
r.locker.Lock()
|
|
|
|
r.channels = append(r.channels, ch)
|
|
|
|
r.locker.Unlock()
|
|
|
|
} else {
|
2018-01-13 12:35:10 +02:00
|
|
|
r = &Receiver{
|
2018-10-21 13:15:20 +03:00
|
|
|
c: c,
|
2018-01-11 19:17:11 +02:00
|
|
|
channels: []chan<- *protonmail.Event{ch},
|
2018-10-21 13:15:20 +03:00
|
|
|
poll: make(chan struct{}),
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|
2018-01-12 14:20:17 +02:00
|
|
|
|
|
|
|
go func() {
|
2018-01-13 12:35:10 +02:00
|
|
|
r.receiveEvents()
|
2018-01-12 14:20:17 +02:00
|
|
|
|
|
|
|
m.locker.Lock()
|
|
|
|
delete(m.receivers, username)
|
|
|
|
m.locker.Unlock()
|
|
|
|
}()
|
|
|
|
|
2018-01-11 19:17:11 +02:00
|
|
|
m.receivers[username] = r
|
|
|
|
}
|
2018-01-12 14:20:17 +02:00
|
|
|
|
|
|
|
if done != nil {
|
|
|
|
go func() {
|
|
|
|
<-done
|
|
|
|
|
|
|
|
r.locker.Lock()
|
|
|
|
for i, c := range r.channels {
|
|
|
|
if c == ch {
|
|
|
|
r.channels = append(r.channels[:i], r.channels[i+1:]...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r.locker.Unlock()
|
|
|
|
|
|
|
|
close(ch)
|
|
|
|
}()
|
|
|
|
}
|
2018-01-13 12:35:10 +02:00
|
|
|
|
|
|
|
return r
|
2018-01-11 19:17:11 +02:00
|
|
|
}
|