Compare commits
No commits in common. "21e4c434fd8ce549ee128ab2b1d1795a4a6007ef" and "c920eb94a035913bf4f5dc98fe6ee26ff0c3f66f" have entirely different histories.
21e4c434fd
...
c920eb94a0
5 changed files with 16 additions and 149 deletions
|
@ -1,18 +1,6 @@
|
||||||
# Creating a Plugin
|
# Creating a Plugin
|
||||||
|
|
||||||
## Plugin Categories
|
## Example
|
||||||
|
|
||||||
ButterRobot organizes plugins into different categories:
|
|
||||||
|
|
||||||
- **Development**: Utility plugins like `ping`
|
|
||||||
- **Fun**: Entertainment plugins like dice rolling, coin flipping
|
|
||||||
- **Social**: Social media related plugins like URL transformers/expanders
|
|
||||||
|
|
||||||
When creating a new plugin, consider which category it fits into and place it in the appropriate directory.
|
|
||||||
|
|
||||||
## Plugin Examples
|
|
||||||
|
|
||||||
### Basic Example: Marco Polo
|
|
||||||
|
|
||||||
This simple "Marco Polo" plugin will answer _Polo_ to the user that says _Marco_:
|
This simple "Marco Polo" plugin will answer _Polo_ to the user that says _Marco_:
|
||||||
|
|
||||||
|
@ -59,92 +47,6 @@ func (p *MarcoPlugin) OnMessage(msg *model.Message, config map[string]interface{
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Advanced Example: URL Transformer
|
|
||||||
|
|
||||||
This more complex plugin transforms URLs, useful for improving media embedding in chat platforms:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package social
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.nakama.town/fmartingr/butterrobot/internal/model"
|
|
||||||
"git.nakama.town/fmartingr/butterrobot/internal/plugin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TwitterExpander transforms twitter.com links to fxtwitter.com links
|
|
||||||
type TwitterExpander struct {
|
|
||||||
plugin.BasePlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new TwitterExpander instance
|
|
||||||
func NewTwitter() *TwitterExpander {
|
|
||||||
return &TwitterExpander{
|
|
||||||
BasePlugin: plugin.BasePlugin{
|
|
||||||
ID: "social.twitter",
|
|
||||||
Name: "Twitter Link Expander",
|
|
||||||
Help: "Automatically converts twitter.com links to fxtwitter.com links and removes tracking parameters",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnMessage handles incoming messages
|
|
||||||
func (p *TwitterExpander) OnMessage(msg *model.Message, config map[string]interface{}) []*model.Message {
|
|
||||||
// Skip empty messages
|
|
||||||
if strings.TrimSpace(msg.Text) == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regex to match twitter.com links
|
|
||||||
twitterRegex := regexp.MustCompile(`https?://(www\.)?(twitter\.com|x\.com)/[^\s]+`)
|
|
||||||
|
|
||||||
// Check if the message contains a Twitter link
|
|
||||||
if !twitterRegex.MatchString(msg.Text) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform the URL
|
|
||||||
transformed := twitterRegex.ReplaceAllStringFunc(msg.Text, func(link string) string {
|
|
||||||
// Parse the URL
|
|
||||||
parsedURL, err := url.Parse(link)
|
|
||||||
if err != nil {
|
|
||||||
// If parsing fails, just do the simple replacement
|
|
||||||
link = strings.Replace(link, "twitter.com", "fxtwitter.com", 1)
|
|
||||||
link = strings.Replace(link, "x.com", "fxtwitter.com", 1)
|
|
||||||
return link
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the host
|
|
||||||
if strings.Contains(parsedURL.Host, "twitter.com") {
|
|
||||||
parsedURL.Host = strings.Replace(parsedURL.Host, "twitter.com", "fxtwitter.com", 1)
|
|
||||||
} else if strings.Contains(parsedURL.Host, "x.com") {
|
|
||||||
parsedURL.Host = strings.Replace(parsedURL.Host, "x.com", "fxtwitter.com", 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove query parameters
|
|
||||||
parsedURL.RawQuery = ""
|
|
||||||
|
|
||||||
// Return the cleaned URL
|
|
||||||
return parsedURL.String()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create response message
|
|
||||||
response := &model.Message{
|
|
||||||
Text: transformed,
|
|
||||||
Chat: msg.Chat,
|
|
||||||
ReplyTo: msg.ID,
|
|
||||||
Channel: msg.Channel,
|
|
||||||
}
|
|
||||||
|
|
||||||
return []*model.Message{response}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Registering Plugins
|
|
||||||
|
|
||||||
To use the plugin, register it in your application:
|
To use the plugin, register it in your application:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -153,10 +55,7 @@ func (a *App) Run() error {
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
// Register plugins
|
// Register plugins
|
||||||
plugin.Register(ping.New()) // Development plugin
|
plugin.Register(myplugin.New())
|
||||||
plugin.Register(fun.NewCoin()) // Fun plugin
|
|
||||||
plugin.Register(social.NewTwitter()) // Social media plugin
|
|
||||||
plugin.Register(myplugin.New()) // Your custom plugin
|
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,3 @@
|
||||||
- Lo quito: What happens when you say _"lo quito"_...? (Spanish pun)
|
- Lo quito: What happens when you say _"lo quito"_...? (Spanish pun)
|
||||||
- Dice: Put `!dice` and wathever roll you want to perform.
|
- Dice: Put `!dice` and wathever roll you want to perform.
|
||||||
- Coin: Flip a coin and get heads or tails.
|
- Coin: Flip a coin and get heads or tails.
|
||||||
|
|
||||||
### Social Media
|
|
||||||
|
|
||||||
- Twitter Link Expander: Automatically converts twitter.com and x.com links to fxtwitter.com links and removes tracking parameters. This allows for better media embedding in chat platforms.
|
|
||||||
- Instagram Link Expander: Automatically converts instagram.com links to ddinstagram.com links and removes tracking parameters. This allows for better media embedding in chat platforms.
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ type TemplateData struct {
|
||||||
Channels []*model.Channel
|
Channels []*model.Channel
|
||||||
Channel *model.Channel
|
Channel *model.Channel
|
||||||
ChannelPlugin *model.ChannelPlugin
|
ChannelPlugin *model.ChannelPlugin
|
||||||
Version string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admin represents the admin interface
|
// Admin represents the admin interface
|
||||||
|
@ -56,11 +55,10 @@ type Admin struct {
|
||||||
store *sessions.CookieStore
|
store *sessions.CookieStore
|
||||||
templates map[string]*template.Template
|
templates map[string]*template.Template
|
||||||
baseTemplate *template.Template
|
baseTemplate *template.Template
|
||||||
version string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Admin instance
|
// New creates a new Admin instance
|
||||||
func New(cfg *config.Config, database *db.Database, version string) *Admin {
|
func New(cfg *config.Config, database *db.Database) *Admin {
|
||||||
// Create session store with appropriate options
|
// Create session store with appropriate options
|
||||||
store := sessions.NewCookieStore([]byte(cfg.SecretKey))
|
store := sessions.NewCookieStore([]byte(cfg.SecretKey))
|
||||||
store.Options = &sessions.Options{
|
store.Options = &sessions.Options{
|
||||||
|
@ -128,7 +126,6 @@ func New(cfg *config.Config, database *db.Database, version string) *Admin {
|
||||||
store: store,
|
store: store,
|
||||||
templates: templates,
|
templates: templates,
|
||||||
baseTemplate: baseTemplate,
|
baseTemplate: baseTemplate,
|
||||||
version: version,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +264,6 @@ func (a *Admin) render(w http.ResponseWriter, r *http.Request, templateName stri
|
||||||
data.LoggedIn = a.isLoggedIn(r)
|
data.LoggedIn = a.isLoggedIn(r)
|
||||||
data.Path = r.URL.Path
|
data.Path = r.URL.Path
|
||||||
data.Flash = a.getFlashes(w, r)
|
data.Flash = a.getFlashes(w, r)
|
||||||
data.Version = a.version
|
|
||||||
|
|
||||||
// Get template
|
// Get template
|
||||||
tmpl, ok := a.templates[templateName]
|
tmpl, ok := a.templates[templateName]
|
||||||
|
|
|
@ -117,19 +117,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="footer footer-transparent d-print-none">
|
|
||||||
<div class="container-xl">
|
|
||||||
<div class="row text-center align-items-center flex-row-reverse">
|
|
||||||
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
|
|
||||||
<ul class="list-inline list-inline-dots mb-0">
|
|
||||||
<li class="list-inline-item">
|
|
||||||
ButterRobot {{if .Version}}v{{.Version}}{{else}}(development){{end}}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://unpkg.com/@tabler/core@latest/dist/js/tabler.min.js"></script>
|
<script src="https://unpkg.com/@tabler/core@latest/dist/js/tabler.min.js"></script>
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime/debug"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -33,7 +32,6 @@ type App struct {
|
||||||
router *http.ServeMux
|
router *http.ServeMux
|
||||||
queue *queue.Queue
|
queue *queue.Queue
|
||||||
admin *admin.Admin
|
admin *admin.Admin
|
||||||
version string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new App instance
|
// New creates a new App instance
|
||||||
|
@ -50,15 +48,8 @@ func New(cfg *config.Config, logger *slog.Logger) (*App, error) {
|
||||||
// Initialize message queue
|
// Initialize message queue
|
||||||
messageQueue := queue.New(logger)
|
messageQueue := queue.New(logger)
|
||||||
|
|
||||||
// Get version information
|
|
||||||
version := ""
|
|
||||||
info, ok := debug.ReadBuildInfo()
|
|
||||||
if ok {
|
|
||||||
version = info.Main.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize admin interface
|
// Initialize admin interface
|
||||||
adminInterface := admin.New(cfg, database, version)
|
adminInterface := admin.New(cfg, database)
|
||||||
|
|
||||||
return &App{
|
return &App{
|
||||||
config: cfg,
|
config: cfg,
|
||||||
|
@ -67,7 +58,6 @@ func New(cfg *config.Config, logger *slog.Logger) (*App, error) {
|
||||||
router: router,
|
router: router,
|
||||||
queue: messageQueue,
|
queue: messageQueue,
|
||||||
admin: adminInterface,
|
admin: adminInterface,
|
||||||
version: version,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue