diff --git a/CLAUDE.md b/CLAUDE.md index cb4e70a..2191848 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,12 +18,10 @@ When creating, modifying, or removing plugins: ## Testing -**CRITICAL**: After making ANY changes to code files, you MUST run these commands in order: +Before committing plugin changes: -1. **Format code**: `make format` - Format all code according to project standards -2. **Lint code**: `make lint` - Check code style and quality (must show "0 issues") -3. **Run tests**: `make test` - Run all tests to ensure functionality works +1. Check files are properly formatted: Run `make format` +2. Check code style and linting: Run `make lint` +3. Test the plugin functionality: Run `make test` 4. Verify documentation accuracy 5. Ensure all examples work as described - -**These commands are MANDATORY after every code change, no exceptions.** diff --git a/internal/admin/templates/channel_detail.html b/internal/admin/templates/channel_detail.html index 7e12d57..9f9a78d 100644 --- a/internal/admin/templates/channel_detail.html +++ b/internal/admin/templates/channel_detail.html @@ -32,7 +32,7 @@ Enable All Plugins -
+
When enabled, all registered plugins will be automatically enabled for this channel. Individual plugin settings will be ignored.
@@ -124,4 +124,4 @@ -{{end}} +{{end}} \ No newline at end of file diff --git a/internal/db/db_test.go b/internal/db/db_test.go index beb485d..88ab470 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -200,4 +200,4 @@ func TestEnableAllPlugins(t *testing.T) { t.Errorf("EnableAllPlugins should be true after update") } }) -} +} \ No newline at end of file diff --git a/internal/model/message_test.go b/internal/model/message_test.go index d2dfedc..d94c5ea 100644 --- a/internal/model/message_test.go +++ b/internal/model/message_test.go @@ -231,4 +231,4 @@ func TestChannelName(t *testing.T) { t.Errorf("Expected channel name to fallback to 'fallback-id', got '%s'", result) } }) -} +} \ No newline at end of file diff --git a/internal/platform/telegram/telegram.go b/internal/platform/telegram/telegram.go index b015793..24714f2 100644 --- a/internal/platform/telegram/telegram.go +++ b/internal/platform/telegram/telegram.go @@ -233,17 +233,9 @@ func (t *TelegramPlatform) SendMessage(msg *model.Message) error { // Prepare payload payload := map[string]interface{}{ - "chat_id": chatID, - "text": msg.Text, - } - - // Set parse_mode based on plugin preference or default to empty string - if msg.Raw != nil && msg.Raw["parse_mode"] != nil { - // Plugin explicitly set parse_mode - payload["parse_mode"] = msg.Raw["parse_mode"] - } else { - // Default to empty string (no formatting) - payload["parse_mode"] = "" + "chat_id": chatID, + "text": msg.Text, + "parse_mode": "Markdown", } // Add reply if needed diff --git a/internal/plugin/fun/hltb.go b/internal/plugin/fun/hltb.go index f94f2ba..227d637 100644 --- a/internal/plugin/fun/hltb.go +++ b/internal/plugin/fun/hltb.go @@ -131,15 +131,12 @@ func (p *HLTBPlugin) OnMessage(msg *model.Message, config map[string]interface{} Channel: msg.Channel, } - // Set parse mode for markdown formatting - if responseMsg.Raw == nil { - responseMsg.Raw = make(map[string]interface{}) - } - responseMsg.Raw["parse_mode"] = "Markdown" - // Add game cover as attachment if available if game.GameImage != "" { imageURL := p.getFullImageURL(game.GameImage) + if responseMsg.Raw == nil { + responseMsg.Raw = make(map[string]interface{}) + } responseMsg.Raw["image_url"] = imageURL } diff --git a/internal/plugin/help/help.go b/internal/plugin/help/help.go index 4e6215a..88b25dd 100644 --- a/internal/plugin/help/help.go +++ b/internal/plugin/help/help.go @@ -74,7 +74,6 @@ func (p *HelpPlugin) OnMessage(msg *model.Message, config map[string]interface{} Chat: msg.Chat, ReplyTo: msg.ID, Channel: msg.Channel, - Raw: map[string]interface{}{"parse_mode": "Markdown"}, } return []*model.MessageAction{ @@ -152,7 +151,6 @@ func (p *HelpPlugin) OnMessage(msg *model.Message, config map[string]interface{} Chat: msg.Chat, ReplyTo: msg.ID, Channel: msg.Channel, - Raw: map[string]interface{}{"parse_mode": "Markdown"}, } return []*model.MessageAction{ diff --git a/internal/plugin/plugin_test.go b/internal/plugin/plugin_test.go index 0bfd207..e0b68d3 100644 --- a/internal/plugin/plugin_test.go +++ b/internal/plugin/plugin_test.go @@ -328,4 +328,4 @@ func TestPluginRegistry(t *testing.T) { t.Errorf("Expected error when getting plugin after clearing registry, got nil") } }) -} +} \ No newline at end of file diff --git a/internal/plugin/social/twitter_test.go b/internal/plugin/social/twitter_test.go deleted file mode 100644 index c0e1681..0000000 --- a/internal/plugin/social/twitter_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package social - -import ( - "testing" - - "git.nakama.town/fmartingr/butterrobot/internal/model" -) - -func TestTwitterExpander_OnMessage(t *testing.T) { - plugin := NewTwitterExpander() - - tests := []struct { - name string - input string - config map[string]interface{} - expected string - hasReply bool - }{ - { - name: "Twitter URL with default domain", - input: "https://twitter.com/user/status/123456789", - config: map[string]interface{}{}, - expected: "https://fxtwitter.com/user/status/123456789", - hasReply: true, - }, - { - name: "X.com URL with custom domain", - input: "https://x.com/elonmusk/status/987654321", - config: map[string]interface{}{"domain": "vxtwitter.com"}, - expected: "https://vxtwitter.com/elonmusk/status/987654321", - hasReply: true, - }, - { - name: "Twitter URL with tracking parameters", - input: "https://twitter.com/openai/status/555?ref_src=twsrc%5Etfw&s=20", - config: map[string]interface{}{}, - expected: "https://fxtwitter.com/openai/status/555", - hasReply: true, - }, - { - name: "www.twitter.com URL", - input: "https://www.twitter.com/user/status/789", - config: map[string]interface{}{"domain": "nitter.net"}, - expected: "https://nitter.net/user/status/789", - hasReply: true, - }, - { - name: "Mixed text with Twitter URL", - input: "Check this out: https://twitter.com/user/status/123 amazing!", - config: map[string]interface{}{}, - expected: "Check this out: https://fxtwitter.com/user/status/123 amazing!", - hasReply: true, - }, - { - name: "No Twitter URLs", - input: "Just some regular text https://youtube.com/watch?v=abc", - config: map[string]interface{}{}, - expected: "", - hasReply: false, - }, - { - name: "Empty message", - input: "", - config: map[string]interface{}{}, - expected: "", - hasReply: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - msg := &model.Message{ - ID: "test_msg", - Text: tt.input, - Chat: "test_chat", - Channel: &model.Channel{ - ID: 1, - Platform: "telegram", - PlatformChannelID: "test_chat", - }, - } - - actions := plugin.OnMessage(msg, tt.config, nil) - - if !tt.hasReply { - if len(actions) != 0 { - t.Errorf("Expected no actions, got %d", len(actions)) - } - return - } - - if len(actions) != 1 { - t.Errorf("Expected 1 action, got %d", len(actions)) - return - } - - action := actions[0] - if action.Type != model.ActionSendMessage { - t.Errorf("Expected ActionSendMessage, got %s", action.Type) - } - - if action.Message == nil { - t.Error("Expected message in action, got nil") - return - } - - if action.Message.Text != tt.expected { - t.Errorf("Expected '%s', got '%s'", tt.expected, action.Message.Text) - } - - if action.Message.ReplyTo != msg.ID { - t.Errorf("Expected ReplyTo '%s', got '%s'", msg.ID, action.Message.ReplyTo) - } - - if action.Message.Raw == nil || action.Message.Raw["parse_mode"] != "" { - t.Error("Expected parse_mode to be empty string to disable markdown parsing") - } - }) - } -}