Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
377b1723c3 | |||
60ceaffd82 | |||
3a5b5c216d | |||
bdc797d5c1 | |||
0edf41c792 | |||
35c14ce8a8 | |||
e0ff369cff |
9 changed files with 150 additions and 15 deletions
10
CLAUDE.md
10
CLAUDE.md
|
@ -18,10 +18,12 @@ When creating, modifying, or removing plugins:
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Before committing plugin changes:
|
**CRITICAL**: After making ANY changes to code files, you MUST run these commands in order:
|
||||||
|
|
||||||
1. Check files are properly formatted: Run `make format`
|
1. **Format code**: `make format` - Format all code according to project standards
|
||||||
2. Check code style and linting: Run `make lint`
|
2. **Lint code**: `make lint` - Check code style and quality (must show "0 issues")
|
||||||
3. Test the plugin functionality: Run `make test`
|
3. **Run tests**: `make test` - Run all tests to ensure functionality works
|
||||||
4. Verify documentation accuracy
|
4. Verify documentation accuracy
|
||||||
5. Ensure all examples work as described
|
5. Ensure all examples work as described
|
||||||
|
|
||||||
|
**These commands are MANDATORY after every code change, no exceptions.**
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<input class="form-check-input" type="checkbox" name="enable_all_plugins" value="true" {{if .Channel.EnableAllPlugins}}checked{{end}}>
|
<input class="form-check-input" type="checkbox" name="enable_all_plugins" value="true" {{if .Channel.EnableAllPlugins}}checked{{end}}>
|
||||||
<span class="form-check-label">Enable All Plugins</span>
|
<span class="form-check-label">Enable All Plugins</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="form-help">
|
<div>
|
||||||
When enabled, all registered plugins will be automatically enabled for this channel. Individual plugin settings will be ignored.
|
When enabled, all registered plugins will be automatically enabled for this channel. Individual plugin settings will be ignored.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -235,7 +235,15 @@ func (t *TelegramPlatform) SendMessage(msg *model.Message) error {
|
||||||
payload := map[string]interface{}{
|
payload := map[string]interface{}{
|
||||||
"chat_id": chatID,
|
"chat_id": chatID,
|
||||||
"text": msg.Text,
|
"text": msg.Text,
|
||||||
"parse_mode": "Markdown",
|
}
|
||||||
|
|
||||||
|
// 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"] = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add reply if needed
|
// Add reply if needed
|
||||||
|
|
|
@ -131,12 +131,15 @@ func (p *HLTBPlugin) OnMessage(msg *model.Message, config map[string]interface{}
|
||||||
Channel: msg.Channel,
|
Channel: msg.Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add game cover as attachment if available
|
// Set parse mode for markdown formatting
|
||||||
if game.GameImage != "" {
|
|
||||||
imageURL := p.getFullImageURL(game.GameImage)
|
|
||||||
if responseMsg.Raw == nil {
|
if responseMsg.Raw == nil {
|
||||||
responseMsg.Raw = make(map[string]interface{})
|
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)
|
||||||
responseMsg.Raw["image_url"] = imageURL
|
responseMsg.Raw["image_url"] = imageURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ func (p *HelpPlugin) OnMessage(msg *model.Message, config map[string]interface{}
|
||||||
Chat: msg.Chat,
|
Chat: msg.Chat,
|
||||||
ReplyTo: msg.ID,
|
ReplyTo: msg.ID,
|
||||||
Channel: msg.Channel,
|
Channel: msg.Channel,
|
||||||
|
Raw: map[string]interface{}{"parse_mode": "Markdown"},
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*model.MessageAction{
|
return []*model.MessageAction{
|
||||||
|
@ -151,6 +152,7 @@ func (p *HelpPlugin) OnMessage(msg *model.Message, config map[string]interface{}
|
||||||
Chat: msg.Chat,
|
Chat: msg.Chat,
|
||||||
ReplyTo: msg.ID,
|
ReplyTo: msg.ID,
|
||||||
Channel: msg.Channel,
|
Channel: msg.Channel,
|
||||||
|
Raw: map[string]interface{}{"parse_mode": "Markdown"},
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*model.MessageAction{
|
return []*model.MessageAction{
|
||||||
|
|
120
internal/plugin/social/twitter_test.go
Normal file
120
internal/plugin/social/twitter_test.go
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue