diff --git a/go.mod b/go.mod
index 39ce9e2..a1ee7e6 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
cloud.google.com/go/datastore v1.20.0
cloud.google.com/go/secretmanager v1.16.0
github.com/joho/godotenv v1.5.1
- github.com/julwrites/BotPlatform v0.0.0-20220206144002-60e1b8060734
+ github.com/julwrites/BotPlatform v0.0.0-20251128175347-656700b2e4d4
golang.org/x/net v0.43.0
google.golang.org/api v0.247.0
gopkg.in/yaml.v2 v2.4.0
diff --git a/go.sum b/go.sum
index d9946e4..8500953 100644
--- a/go.sum
+++ b/go.sum
@@ -35,8 +35,8 @@ github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
-github.com/julwrites/BotPlatform v0.0.0-20220206144002-60e1b8060734 h1:U/z8aO/8zMpOzdR7kK9hnHfXber1fHa7FWlXGeuG3Yc=
-github.com/julwrites/BotPlatform v0.0.0-20220206144002-60e1b8060734/go.mod h1:RAVF1PibRuRYv1Z7VxNapzrikBrjtF48aFPCoCVnLpM=
+github.com/julwrites/BotPlatform v0.0.0-20251128175347-656700b2e4d4 h1:NeEPkJt4VXvyb/zxggO9zFs9tAJ07iiht1lAkUL/ZNs=
+github.com/julwrites/BotPlatform v0.0.0-20251128175347-656700b2e4d4/go.mod h1:PZT+yPLr4MrricOGOhXwiJCurNcGj36fD1jZOwMiuIk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
diff --git a/pkg/app/admin.go b/pkg/app/admin.go
index 6ff17b1..92c0625 100644
--- a/pkg/app/admin.go
+++ b/pkg/app/admin.go
@@ -5,14 +5,17 @@ import (
"strings"
"github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
func DumpUserList(env def.SessionData) def.SessionData {
- if env.User.Id == env.Secrets.ADMIN_ID {
+ adminID, _ := secrets.Get("TELEGRAM_ADMIN_ID")
+ if env.User.Id == adminID {
var message = ""
- users := utils.GetAllUsers(env.Secrets.PROJECT_ID)
+ projectID, _ := secrets.Get("GCLOUD_PROJECT_ID")
+ users := utils.GetAllUsers(projectID)
message += fmt.Sprintf("%d Users: \n", len(users))
for _, user := range users {
message += user.Firstname + " " + user.Lastname + " - @" + user.Username + "\n"
@@ -27,8 +30,10 @@ func DumpUserList(env def.SessionData) def.SessionData {
}
func Migrate(env def.SessionData) def.SessionData {
- if env.User.Id == env.Secrets.ADMIN_ID {
- users := utils.GetAllUsers(env.Secrets.PROJECT_ID)
+ adminID, _ := secrets.Get("TELEGRAM_ADMIN_ID")
+ if env.User.Id == adminID {
+ projectID, _ := secrets.Get("GCLOUD_PROJECT_ID")
+ users := utils.GetAllUsers(projectID)
for _, user := range users {
config := utils.DeserializeUserConfig(user.Config)
if len(config.Subscriptions) > 0 {
@@ -50,7 +55,7 @@ func Migrate(env def.SessionData) def.SessionData {
user.Config = utils.SerializeUserConfig(config)
- utils.PushUser(user, env.Secrets.PROJECT_ID)
+ utils.PushUser(user, projectID)
}
}
}
diff --git a/pkg/app/ask.go b/pkg/app/ask.go
index 0b694ed..2dbc630 100644
--- a/pkg/app/ask.go
+++ b/pkg/app/ask.go
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
@@ -25,7 +26,8 @@ func GetBibleAsk(env def.SessionData) def.SessionData {
}
var resp OQueryResponse
- err := SubmitQuery(req, &resp, env.Secrets.PROJECT_ID)
+ projectID, _ := secrets.Get("GCLOUD_PROJECT_ID")
+ err := SubmitQuery(req, &resp, projectID)
if err != nil {
log.Printf("Error asking bible: %v", err)
env.Res.Message = "Sorry, I encountered an error processing your question."
diff --git a/pkg/app/command.go b/pkg/app/command.go
index e3dc41b..618a5ea 100644
--- a/pkg/app/command.go
+++ b/pkg/app/command.go
@@ -1,8 +1,11 @@
package app
-import "github.com/julwrites/BotPlatform/pkg/def"
+import (
+ "github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/BotPlatform/pkg/platform"
+)
-func ProcessCommand(env def.SessionData) def.SessionData {
+func ProcessCommand(env def.SessionData, bot platform.Platform) def.SessionData {
switch env.Msg.Command {
case ADM_CMD_DUMP:
env = DumpUserList(env)
@@ -17,7 +20,7 @@ func ProcessCommand(env def.SessionData) def.SessionData {
env = GetTMSVerse(env)
break
case CMD_DEVO:
- env = GetDevo(env)
+ env = GetDevo(env, bot)
break
case CMD_SUBSCRIBE:
env = UpdateSubscription(env)
diff --git a/pkg/app/devo.go b/pkg/app/devo.go
index 6e5098b..582980a 100644
--- a/pkg/app/devo.go
+++ b/pkg/app/devo.go
@@ -167,7 +167,7 @@ func GetDevotionalData(env def.SessionData, devo string) def.ResponseData {
return response
}
-func GetDevo(env def.SessionData) def.SessionData {
+func GetDevo(env def.SessionData, bot platform.Platform) def.SessionData {
switch env.User.Action {
case CMD_DEVO:
log.Printf("Detected existing action /devo")
@@ -180,7 +180,7 @@ func GetDevo(env def.SessionData) def.SessionData {
env.Res.Message = "Just a moment..."
log.Printf("Affordances before posting: %+v", env.Res.Affordances)
- platform.PostFromProps(env)
+ bot.Post(env)
// Retrieve devotional
env.Res = GetDevotionalData(env, devo)
diff --git a/pkg/app/devo_test.go b/pkg/app/devo_test.go
index aca3f9d..47e7efa 100644
--- a/pkg/app/devo_test.go
+++ b/pkg/app/devo_test.go
@@ -101,7 +101,7 @@ func TestGetDevo(t *testing.T) {
env.User.Action = ""
env.Msg.Message = CMD_DEVO
- env = GetDevo(env)
+ env = GetDevo(env, &MockBot{})
if len(env.Res.Message) == 0 {
t.Error("Failed TestGetDevo initial, no message")
}
@@ -123,7 +123,7 @@ func TestGetDevo(t *testing.T) {
env.Msg.Message = devoName
env.ResourcePath = "../../resource"
- env = GetDevo(env)
+ env = GetDevo(env, &MockBot{})
if len(env.Res.Message) == 0 && len(env.Res.Affordances.Options) == 0 {
t.Fatalf("Failed TestGetDevo for %s: no message or affordances", devoName)
diff --git a/pkg/app/passage.go b/pkg/app/passage.go
index aff6fe6..158c1ee 100644
--- a/pkg/app/passage.go
+++ b/pkg/app/passage.go
@@ -13,6 +13,7 @@ import (
"github.com/julwrites/BotPlatform/pkg/def"
"github.com/julwrites/BotPlatform/pkg/platform"
+ "github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
@@ -54,10 +55,9 @@ func ParseNodesForPassage(node *html.Node) string {
switch tag := child.Data; tag {
case "span":
childText := ParseNodesForPassage(child)
- if len(childText) > 0 {
- parts = append(parts, childText)
- } else {
- parts = append(parts, child.Data)
+ parts = append(parts, childText)
+ if len(strings.TrimSpace(childText)) > 0 {
+ parts = append(parts, "\n")
}
case "sup":
isFootnote := func(node *html.Node) bool {
@@ -200,7 +200,8 @@ func GetBiblePassage(env def.SessionData) def.SessionData {
}
var resp VerseResponse
- err := SubmitQuery(req, &resp, env.Secrets.PROJECT_ID)
+ projectID, _ := secrets.Get("GCLOUD_PROJECT_ID")
+ err := SubmitQuery(req, &resp, projectID)
// Fallback to direct passage retrieval logic
if err != nil {
diff --git a/pkg/app/passage_test.go b/pkg/app/passage_test.go
index ce53148..32e9ca2 100644
--- a/pkg/app/passage_test.go
+++ b/pkg/app/passage_test.go
@@ -102,7 +102,7 @@ func TestParsePassageFromHtml(t *testing.T) {
t.Run("HTML with spans", func(t *testing.T) {
html := `
Line 1.
Line 2.
`
- expected := "Line 1.\n Line 2."
+ expected := "Line 1.\n\n Line 2."
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
diff --git a/pkg/app/search.go b/pkg/app/search.go
index 1852f24..c51b3b5 100644
--- a/pkg/app/search.go
+++ b/pkg/app/search.go
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
@@ -38,7 +39,8 @@ func GetBibleSearch(env def.SessionData) def.SessionData {
}
var resp WordSearchResponse
- err := SubmitQuery(req, &resp, env.Secrets.PROJECT_ID)
+ projectID, _ := secrets.Get("GCLOUD_PROJECT_ID")
+ err := SubmitQuery(req, &resp, projectID)
if err != nil {
log.Printf("Error searching bible: %v", err)
env.Res.Message = "Sorry, I encountered an error while searching."
diff --git a/pkg/app/test_utils.go b/pkg/app/test_utils.go
index 92442fc..c065d54 100644
--- a/pkg/app/test_utils.go
+++ b/pkg/app/test_utils.go
@@ -2,8 +2,20 @@ package app
import (
"os"
+
+ "github.com/julwrites/BotPlatform/pkg/def"
)
+type MockBot struct{}
+
+func (b *MockBot) Translate(body []byte) (def.SessionData, error) {
+ return def.SessionData{}, nil
+}
+
+func (b *MockBot) Post(env def.SessionData) bool {
+ return true
+}
+
// SetEnv is a helper function to temporarily set an environment variable and return a function to restore it.
func SetEnv(key, value string) func() {
originalValue, isSet := os.LookupEnv(key)
diff --git a/pkg/bot/bot.go b/pkg/bot/bot.go
index cadceae..f6646d6 100644
--- a/pkg/bot/bot.go
+++ b/pkg/bot/bot.go
@@ -8,6 +8,7 @@ import (
"log"
"github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/BotPlatform/pkg/platform"
"github.com/julwrites/ScriptureBot/pkg/app"
)
@@ -17,7 +18,7 @@ func HelpMessage(env *def.SessionData) string {
//\n/subscribe - Subscribe to / Unsubscribe from daily reading material
}
-func RunCommands(env def.SessionData) def.SessionData {
+func RunCommands(env def.SessionData, bot platform.Platform) def.SessionData {
if len(env.User.Action) > 0 {
log.Printf("Detected user has active action %s", env.User.Action)
env.Msg.Command = env.User.Action
@@ -27,13 +28,13 @@ func RunCommands(env def.SessionData) def.SessionData {
env.Msg.Command = app.CMD_CLOSE
}
- env = app.ProcessCommand(env)
+ env = app.ProcessCommand(env, bot)
return env
}
-func HandleBotLogic(env def.SessionData) def.SessionData {
- env = RunCommands(env)
+func HandleBotLogic(env def.SessionData, bot platform.Platform) def.SessionData {
+ env = RunCommands(env, bot)
// log.Printf("Commands run, resulting message: %s", env.Res.Message)
if len(env.Res.Message) == 0 {
diff --git a/pkg/bot/bot_test.go b/pkg/bot/bot_test.go
index edf47ed..9911239 100644
--- a/pkg/bot/bot_test.go
+++ b/pkg/bot/bot_test.go
@@ -20,7 +20,7 @@ func TestRunCommands(t *testing.T) {
env.User.Config = utils.SerializeUserConfig(conf)
env.Msg.Message = "psalm 1"
- env = RunCommands(env)
+ env = RunCommands(env, &app.MockBot{})
if !strings.Contains(env.Res.Message, "wicked") && !strings.Contains(env.Res.Message, "Blessed") {
t.Errorf("Failed TestRunCommands Passage command. Got: %s", env.Res.Message)
diff --git a/pkg/bot/sub.go b/pkg/bot/sub.go
index 7aa1ff7..eefb412 100644
--- a/pkg/bot/sub.go
+++ b/pkg/bot/sub.go
@@ -6,13 +6,12 @@ import (
"github.com/julwrites/BotPlatform/pkg/def"
"github.com/julwrites/BotPlatform/pkg/platform"
- bpsecrets "github.com/julwrites/BotPlatform/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/app"
"github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
-func HandleSubscriptionLogic(env def.SessionData) def.SessionData {
+func HandleSubscriptionLogic(env def.SessionData, bot platform.Platform) def.SessionData {
user := env.User
config := utils.DeserializeUserConfig(user.Config)
@@ -25,7 +24,7 @@ func HandleSubscriptionLogic(env def.SessionData) def.SessionData {
env.Res.Message = "Here are today's devotions!"
env.Res.Affordances.Remove = true
- platform.PostFromProps(env)
+ bot.Post(env)
// Send the devotional
for _, devo := range subscriptions {
@@ -33,22 +32,22 @@ func HandleSubscriptionLogic(env def.SessionData) def.SessionData {
log.Printf("Getting data for <%s>", devo)
env.Res = app.GetDevotionalData(env, devo)
- platform.PostFromProps(env)
+ bot.Post(env)
}
}
return env
}
-func HandleSubscriptionPublish(env def.SessionData) def.SessionData {
+func HandleSubscriptionPublish(env def.SessionData, bot platform.Platform, projectID string) def.SessionData {
// Check all users
- users := utils.GetAllUsers(env.Secrets.PROJECT_ID)
+ users := utils.GetAllUsers(projectID)
log.Printf("Retrieved %d users", len(users))
for _, user := range users {
env.User = user
env.User.Action = app.CMD_DEVO
- env = HandleSubscriptionLogic(env)
+ env = HandleSubscriptionLogic(env, bot)
}
return env
@@ -57,23 +56,19 @@ func HandleSubscriptionPublish(env def.SessionData) def.SessionData {
func SubscriptionHandler(localSecrets *secrets.SecretsData) {
env := def.SessionData{}
- platformSecrets := bpsecrets.SecretsData{
- TELEGRAM_ID: localSecrets.TELEGRAM_ID,
- PROJECT_ID: localSecrets.PROJECT_ID,
- }
+ bot := platform.NewTelegram(localSecrets.TELEGRAM_ID, localSecrets.TELEGRAM_ADMIN_ID)
- env.Secrets = platformSecrets
- log.Printf("Loaded secrets...")
+ // log.Printf("Loaded secrets...")
env.ResourcePath = "/go/bin/"
// TODO: Iterate through types
env.Type = def.TYPE_TELEGRAM
- env = HandleSubscriptionPublish(env)
+ env = HandleSubscriptionPublish(env, bot, localSecrets.PROJECT_ID)
log.Printf("Handled bot publish...")
- if !platform.PostFromProps(env) {
+ if !bot.Post(env) {
log.Printf("This message was not translatable from bot language")
return
}
diff --git a/pkg/bot/sub_test.go b/pkg/bot/sub_test.go
index dea82b2..bd04420 100644
--- a/pkg/bot/sub_test.go
+++ b/pkg/bot/sub_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/julwrites/BotPlatform/pkg/def"
+ "github.com/julwrites/ScriptureBot/pkg/app"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
@@ -16,7 +17,7 @@ func TestHandleSubscriptionLogic(t *testing.T) {
conf.Subscriptions = "DTMSV"
env.User.Config = utils.SerializeUserConfig(conf)
- env = HandleSubscriptionLogic(env)
+ env = HandleSubscriptionLogic(env, &app.MockBot{})
if len(env.Res.Message) == 0 {
t.Errorf("Failed TestHandleSubscriptionLogic")
diff --git a/pkg/bot/telegram.go b/pkg/bot/telegram.go
index cac7227..980ee69 100644
--- a/pkg/bot/telegram.go
+++ b/pkg/bot/telegram.go
@@ -4,48 +4,50 @@
package bot
import (
+ "io"
"log"
"net/http"
- "github.com/julwrites/BotPlatform/pkg/def"
"github.com/julwrites/BotPlatform/pkg/platform"
- bpsecrets "github.com/julwrites/BotPlatform/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)
func TelegramHandler(res http.ResponseWriter, req *http.Request, secrets *secrets.SecretsData) {
log.Printf("Loading session data...")
- env, ok := platform.TranslateToProps(req, def.TYPE_TELEGRAM)
- if !ok {
- log.Printf("This message was not translatable to bot language")
+
+ body, err := io.ReadAll(req.Body)
+ if err != nil {
+ log.Printf("Failed to read request body: %v", err)
return
}
- // Create a BotPlatform-compatible SecretsData struct using an import alias
- platformSecrets := bpsecrets.SecretsData{
- TELEGRAM_ID: secrets.TELEGRAM_ID,
- PROJECT_ID: secrets.PROJECT_ID,
+ bot := platform.NewTelegram(secrets.TELEGRAM_ID, secrets.TELEGRAM_ADMIN_ID)
+
+ env, err := bot.Translate(body)
+ if err != nil {
+ log.Printf("This message was not translatable to bot language: %v", err)
+ return
}
- env.Secrets = platformSecrets
+
// log.Printf("Loaded secrets...")
env.ResourcePath = "/go/bin/"
- user := utils.RegisterUser(env.User, env.Secrets.PROJECT_ID)
+ user := utils.RegisterUser(env.User, secrets.PROJECT_ID)
env.User = user
// log.Printf("Loaded user...")
- env = HandleBotLogic(env)
+ env = HandleBotLogic(env, bot)
// log.Printf("Handled bot logic...")
- if !platform.PostFromProps(env) {
+ if !bot.Post(env) {
log.Printf("This message was not translatable from bot language")
return
}
if env.User != user {
log.Printf("Updating user %v", env.User)
- utils.PushUser(env.User, env.Secrets.PROJECT_ID) // Any change to the user throughout the commands should be put to database
+ utils.PushUser(env.User, secrets.PROJECT_ID) // Any change to the user throughout the commands should be put to database
}
}
diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go
index 0c86a7c..f8d40fe 100644
--- a/pkg/secrets/secrets.go
+++ b/pkg/secrets/secrets.go
@@ -15,8 +15,9 @@ import (
// SecretsData holds all the secrets for the application.
type SecretsData struct {
- TELEGRAM_ID string
- PROJECT_ID string
+ TELEGRAM_ID string
+ TELEGRAM_ADMIN_ID string
+ PROJECT_ID string
// Add other secrets here as needed
}
@@ -49,7 +50,7 @@ func LoadSecrets() (SecretsData, error) {
var errs = make(chan error, 1) // Buffer to hold the first error
// List of secret names to fetch
- secretNames := []string{"TELEGRAM_ID"} // Add other secret names here
+ secretNames := []string{"TELEGRAM_ID", "TELEGRAM_ADMIN_ID"} // Add other secret names here
for _, secretName := range secretNames {
wg.Add(1)
@@ -66,6 +67,8 @@ func LoadSecrets() (SecretsData, error) {
switch name {
case "TELEGRAM_ID":
secrets.TELEGRAM_ID = value
+ case "TELEGRAM_ADMIN_ID":
+ secrets.TELEGRAM_ADMIN_ID = value
}
}(secretName)
}
diff --git a/pkg/secrets/secrets_test.go b/pkg/secrets/secrets_test.go
index bceffb5..8f2821a 100644
--- a/pkg/secrets/secrets_test.go
+++ b/pkg/secrets/secrets_test.go
@@ -107,3 +107,25 @@ func TestGetSecret(t *testing.T) {
}
})
}
+
+func TestLoadSecrets(t *testing.T) {
+ // Mock environment variables
+ t.Setenv("TELEGRAM_ID", "test_telegram_id")
+ t.Setenv("TELEGRAM_ADMIN_ID", "test_admin_id")
+ t.Setenv("GCLOUD_PROJECT_ID", "test_project_id")
+
+ secrets, err := LoadSecrets()
+ if err != nil {
+ t.Fatalf("LoadSecrets failed: %v", err)
+ }
+
+ if secrets.TELEGRAM_ID != "test_telegram_id" {
+ t.Errorf("Expected TELEGRAM_ID 'test_telegram_id', got '%s'", secrets.TELEGRAM_ID)
+ }
+ if secrets.TELEGRAM_ADMIN_ID != "test_admin_id" {
+ t.Errorf("Expected TELEGRAM_ADMIN_ID 'test_admin_id', got '%s'", secrets.TELEGRAM_ADMIN_ID)
+ }
+ if secrets.PROJECT_ID != "test_project_id" {
+ t.Errorf("Expected PROJECT_ID 'test_project_id', got '%s'", secrets.PROJECT_ID)
+ }
+}
diff --git a/pkg/utils/database.go b/pkg/utils/database.go
index c5a23e3..72d67df 100644
--- a/pkg/utils/database.go
+++ b/pkg/utils/database.go
@@ -54,6 +54,11 @@ func GetUser(user def.UserData, project string) def.UserData {
ctx := context.Background()
client := OpenClient(&ctx, project)
+ if client == nil {
+ return user
+ }
+ defer client.Close()
+
key := datastore.NameKey("User", user.Id, nil)
var entity def.UserData
err := client.Get(ctx, key, &entity)
@@ -74,6 +79,11 @@ func GetAllUsers(project string) []def.UserData {
ctx := context.Background()
client := OpenClient(&ctx, project)
+ if client == nil {
+ return []def.UserData{}
+ }
+ defer client.Close()
+
var users []def.UserData
_, err := client.GetAll(ctx, datastore.NewQuery("User"), &users)
@@ -93,6 +103,11 @@ func PushUser(user def.UserData, project string) bool {
ctx := context.Background()
client := OpenClient(&ctx, project)
+ if client == nil {
+ return false
+ }
+ defer client.Close()
+
key := datastore.NameKey("User", user.Id, nil)
_, err := client.Put(ctx, key, &user)