package smshook import ( "encoding/json" "net/http" "sync" "time" "git.directme.in/Joren/SmsHook/ringbuffer" ) type WebhookServer struct { buffer *ringbuffer.RingBuffer cond *sync.Cond mux *http.ServeMux } type WebhookPayload struct { Content string `json:"content"` } func NewWebhookServer(bufferSize int) *WebhookServer { mutex := sync.Mutex{} server := &WebhookServer{ buffer: ringbuffer.NewRingBuffer(bufferSize), cond: sync.NewCond(&mutex), mux: http.NewServeMux(), } server.mux.HandleFunc("/webhook", server.webhookHandler) return server } func (s *WebhookServer) webhookHandler(w http.ResponseWriter, r *http.Request) { var payload WebhookPayload err := json.NewDecoder(r.Body).Decode(&payload) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } s.buffer.Add(payload.Content) s.cond.Broadcast() } func (s *WebhookServer) GetLastItem() (string, int) { return s.buffer.GetLast() } func (s *WebhookServer) WaitForNewItem() string { s.cond.L.Lock() s.cond.Wait() newItem := s.buffer.WaitForNewItem() s.cond.L.Unlock() return newItem } func (s *WebhookServer) WaitForNewItemWithTimeout(timeout time.Duration) (string, bool) { s.cond.L.Lock() defer s.cond.L.Unlock() initialPos := s.buffer.GetLastPosition() timedOut := false timer := time.AfterFunc(timeout, func() { s.cond.Broadcast() timedOut = true }) for s.buffer.GetLastPosition() == initialPos { if timedOut { return "", false } s.cond.Wait() } timer.Stop() newItem := s.buffer.WaitForNewItem() return newItem, true } func (s *WebhookServer) Start(address string) error { return http.ListenAndServe(address, s.mux) } var Server *WebhookServer func Init(bufferSize int, address string) { Server = NewWebhookServer(bufferSize) go func() { if err := Server.Start(address); err != nil { panic(err) } }() } func GetLast() (string, int) { return Server.GetLastItem() } func WaitForNew() string { return Server.WaitForNewItem() } func WaitForNewWithTimeout(timeout time.Duration) (string, bool) { return Server.WaitForNewItemWithTimeout(timeout) }