diff --git a/cmd/smshook/smshook.go b/cmd/smshook/smshook.go deleted file mode 100644 index b9f88b8..0000000 --- a/cmd/smshook/smshook.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "fmt" -) - -func main(){ - fmt.Println("Hi") -} diff --git a/ringbuffer/ringbuffer.go b/ringbuffer/ringbuffer.go new file mode 100644 index 0000000..dff6e75 --- /dev/null +++ b/ringbuffer/ringbuffer.go @@ -0,0 +1,70 @@ +package ringbuffer + +import ( + "sync" +) + + +type RingBuffer struct { + buffer []string + size int + head int + tail int + mu sync.Mutex +} + + +func NewRingBuffer(size int) *RingBuffer { + return &RingBuffer{ + buffer: make([]string, size), + size: size, + head: -1, + tail: -1, + } +} + + +func (rb *RingBuffer) Add(item string) { + rb.mu.Lock() + defer rb.mu.Unlock() + + if (rb.tail+1)%rb.size == rb.head { + rb.head = (rb.head + 1) % rb.size + } + + rb.tail = (rb.tail + 1) % rb.size + rb.buffer[rb.tail] = item + + if rb.head == -1 { + rb.head = rb.tail + } +} + + +func (rb *RingBuffer) GetLast() (string, int) { + rb.mu.Lock() + defer rb.mu.Unlock() + + if rb.head == -1 { + return "", -1 + } + + return rb.buffer[rb.tail], rb.tail +} + + +func (rb *RingBuffer) WaitForNewItem() string { + var newItem string + + for { + rb.mu.Lock() + if rb.head != -1 && rb.tail != -1 && rb.buffer[rb.tail] != newItem { + newItem = rb.buffer[rb.tail] + rb.mu.Unlock() + break + } + rb.mu.Unlock() + } + return newItem +} + diff --git a/smshook/smshook.go b/smshook/smshook.go new file mode 100644 index 0000000..be4d36c --- /dev/null +++ b/smshook/smshook.go @@ -0,0 +1,90 @@ +package smshook + +import ( + "encoding/json" + "net/http" + "sync" + + "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) 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() +} +