From 1dd9af52a0d1292595f39556053d2d536a97225e Mon Sep 17 00:00:00 2001
From: Chris Sexton <chrissexton@users.noreply.github.com>
Date: Mon, 15 Nov 2021 20:34:09 -0500
Subject: [PATCH] pubsub: add counter pub

---
 bot/handlers.go            | 26 ++++++++++++++++++++++++++
 bot/interfaces.go          |  3 +++
 bot/mock.go                | 17 +++++++++--------
 plugins/counter/api.go     |  6 +++---
 plugins/counter/counter.go |  5 +++++
 5 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/bot/handlers.go b/bot/handlers.go
index 5c69804..4464621 100644
--- a/bot/handlers.go
+++ b/bot/handlers.go
@@ -3,10 +3,14 @@
 package bot
 
 import (
+	"bytes"
 	"database/sql"
+	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
+	"net/http"
 	"reflect"
 	"regexp"
 	"strconv"
@@ -263,3 +267,25 @@ func (b *bot) selfSaid(conn Connector, channel, message string, action bool) {
 		}
 	}
 }
+
+// PubToASub sends updates to subscribed URLs
+func (b *bot) PubToASub(subject string, payload interface{}) {
+	key := fmt.Sprintf("pubsub.%s.url", subject)
+	subs := b.config.GetArray(key, []string{})
+	if len(subs) == 0 {
+		return
+	}
+	encodedBody, _ := json.Marshal(struct {
+		Payload interface{} `json:"payload"`
+	}{payload})
+	body := bytes.NewBuffer(encodedBody)
+	for _, url := range subs {
+		r, err := http.Post(url, "text/json", body)
+		if err != nil {
+			log.Error().Err(err).Msg("")
+		} else {
+			body, _ := ioutil.ReadAll(r.Body)
+			log.Debug().Msgf("Response body: %s", string(body))
+		}
+	}
+}
diff --git a/bot/interfaces.go b/bot/interfaces.go
index 5d54388..92e6cd3 100644
--- a/bot/interfaces.go
+++ b/bot/interfaces.go
@@ -172,6 +172,9 @@ type Bot interface {
 
 	// Check valid password
 	CheckPassword(secret, password string) bool
+
+	// PubToASub publishes a message to any subscribers
+	PubToASub(subject string, payload interface{})
 }
 
 // Connector represents a server connection to a chat service
diff --git a/bot/mock.go b/bot/mock.go
index 9279fb2..736a085 100644
--- a/bot/mock.go
+++ b/bot/mock.go
@@ -118,11 +118,12 @@ func NewMockBot() *MockBot {
 	return &b
 }
 
-func (mb *MockBot) GetPluginNames() []string                   { return nil }
-func (mb *MockBot) RefreshPluginBlacklist() error              { return nil }
-func (mb *MockBot) RefreshPluginWhitelist() error              { return nil }
-func (mb *MockBot) GetWhitelist() []string                     { return []string{} }
-func (mb *MockBot) OnBlacklist(ch, p string) bool              { return false }
-func (mb *MockBot) URLFormat(title, url string) string         { return title + url }
-func (mb *MockBot) CheckPassword(secret, password string) bool { return true }
-func (mb *MockBot) ListenAndServe()                            {}
+func (mb *MockBot) GetPluginNames() []string                      { return nil }
+func (mb *MockBot) RefreshPluginBlacklist() error                 { return nil }
+func (mb *MockBot) RefreshPluginWhitelist() error                 { return nil }
+func (mb *MockBot) GetWhitelist() []string                        { return []string{} }
+func (mb *MockBot) OnBlacklist(ch, p string) bool                 { return false }
+func (mb *MockBot) URLFormat(title, url string) string            { return title + url }
+func (mb *MockBot) CheckPassword(secret, password string) bool    { return true }
+func (mb *MockBot) ListenAndServe()                               {}
+func (mb *MockBot) PubToASub(subject string, payload interface{}) {}
diff --git a/plugins/counter/api.go b/plugins/counter/api.go
index 3c8fff1..fc6a0fa 100644
--- a/plugins/counter/api.go
+++ b/plugins/counter/api.go
@@ -160,7 +160,7 @@ func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request)
 }
 
 type Update struct {
-	Who    string
-	What   string
-	Amount int
+	Who    string `json:"who"`
+	What   string `json:"what"`
+	Amount int    `json:"amount"`
 }
diff --git a/plugins/counter/counter.go b/plugins/counter/counter.go
index eedc918..ae53b19 100644
--- a/plugins/counter/counter.go
+++ b/plugins/counter/counter.go
@@ -344,6 +344,11 @@ func New(b bot.Bot) *CounterPlugin {
 	b.Register(cp, bot.Help, cp.help)
 	cp.registerWeb()
 
+	RegisterUpdate(func(r bot.Request, u Update) {
+		log.Debug().Msgf("Publishing update %v", u)
+		b.PubToASub("counter", u)
+	})
+
 	return cp
 }