Added a plugin repository, stabilized
This commit is contained in:
parent
519066e136
commit
251f975dc7
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module github.com/diamondburned/cchat
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/pkg/errors v0.9.1
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
@ -0,0 +1,63 @@
|
|||
// Package plugins provides a source for cchat services as Go plugins. This
|
||||
// package looks in UserConfigDir()/cchat/plugins/ by default.
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
|
||||
"github.com/diamondburned/cchat/services"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var pluginPath string
|
||||
|
||||
// SetPluginPath sets the plugin path before loading plugins. This only works
|
||||
// until LoadPlugins is called.
|
||||
func SetPluginPath(path string) {
|
||||
pluginPath = path
|
||||
}
|
||||
|
||||
// TryConfigPath returns a path to $cfgDir/suffix. cfgDir is from
|
||||
// os.UserConfigDir.
|
||||
func TryConfigPath(suffix ...string) (string, error) {
|
||||
d, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(append([]string{d}, suffix...)...), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
services.RegisterSource(loadPlugins)
|
||||
}
|
||||
|
||||
func loadPlugins() (errs []error) {
|
||||
if pluginPath == "" {
|
||||
p, err := TryConfigPath("cchat", "plugins")
|
||||
if err != nil {
|
||||
errs = []error{errors.Wrap(err, "Failed to get config path")}
|
||||
return
|
||||
}
|
||||
pluginPath = p
|
||||
}
|
||||
|
||||
d, err := ioutil.ReadDir(pluginPath)
|
||||
if err != nil {
|
||||
errs = []error{errors.Wrap(err, "Failed to read plugin path")}
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range d {
|
||||
// We only need the plugin to call its init() function.
|
||||
_, err := plugin.Open(filepath.Join(pluginPath, f.Name()))
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "Failed to open plugin"))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// Package services provides a global repository of cchat services. It also
|
||||
// supports additional sources.
|
||||
//
|
||||
// Registering services
|
||||
//
|
||||
// To register a service, it's best to call RegisterService() in the package's
|
||||
// init(). This allows for dash imports:
|
||||
//
|
||||
// _ "git.sr.ht/~user/cchat-abc"
|
||||
//
|
||||
// Registering sources
|
||||
//
|
||||
// Sources are simply functions that manage other services. An example of this
|
||||
// would be the plugins package. Note that only packages that can error out on
|
||||
// load should do this. A package can call RegisterService() multiple times.
|
||||
//
|
||||
// For examples on using RegisterSource(), check the plugins package.
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/diamondburned/cchat"
|
||||
)
|
||||
|
||||
var services []cchat.Service
|
||||
|
||||
// RegisterService adds a service.
|
||||
func RegisterService(service ...cchat.Service) {
|
||||
services = append(services, service...)
|
||||
}
|
||||
|
||||
var sources []func() []error
|
||||
var sourceErrs []error
|
||||
var sourceOnce sync.Once
|
||||
|
||||
// RegisterSource adds a service source. Services are expected to call
|
||||
// RegisterService() on source().
|
||||
func RegisterSource(source func() []error) {
|
||||
sources = append(sources, source)
|
||||
}
|
||||
|
||||
// Get returns all services. It will also fetch the plugins from all sources.
|
||||
// Future calls will not fetch the plugins again.
|
||||
func Get() ([]cchat.Service, []error) {
|
||||
sourceOnce.Do(func() {
|
||||
sourceErrs = []error{} // mark as non-nil
|
||||
for _, src := range sources {
|
||||
sourceErrs = append(sourceErrs, src()...)
|
||||
}
|
||||
})
|
||||
|
||||
// why are we here, just to suffer
|
||||
return services, sourceErrs
|
||||
}
|
Loading…
Reference in New Issue