mirror of
https://github.com/sot-tech/mochi.git
synced 2026-05-12 14:08:36 -07:00
90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
// Package torrentapproval implements a Hook that fails an Announce based on a
|
|
// whitelist or blacklist of torrent hash.
|
|
package torrentapproval
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/sot-tech/mochi/bittorrent"
|
|
"github.com/sot-tech/mochi/middleware"
|
|
"github.com/sot-tech/mochi/middleware/torrentapproval/container"
|
|
// import directory watcher to enable appropriate support
|
|
_ "github.com/sot-tech/mochi/middleware/torrentapproval/container/directory"
|
|
// import static list to enable appropriate support
|
|
_ "github.com/sot-tech/mochi/middleware/torrentapproval/container/list"
|
|
"github.com/sot-tech/mochi/pkg/stop"
|
|
"github.com/sot-tech/mochi/storage"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
// Name is the name by which this middleware is registered with Conf.
|
|
const Name = "torrent approval"
|
|
|
|
func init() {
|
|
middleware.RegisterDriver(Name, driver{})
|
|
}
|
|
|
|
type baseConfig struct {
|
|
// Source - name of container for initial values
|
|
Source string `yaml:"initial_source"`
|
|
// Configuration depends on used container
|
|
Configuration map[string]interface{} `yaml:"configuration"`
|
|
}
|
|
|
|
type driver struct{}
|
|
|
|
func (d driver) NewHook(optionBytes []byte, storage storage.Storage) (middleware.Hook, error) {
|
|
var cfg baseConfig
|
|
err := yaml.Unmarshal(optionBytes, &cfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid options for middleware %s: %s", Name, err)
|
|
}
|
|
|
|
if len(cfg.Source) == 0 {
|
|
return nil, fmt.Errorf("invalid options for middleware %s: name not provided", Name)
|
|
}
|
|
|
|
if cfg.Configuration == nil {
|
|
return nil, fmt.Errorf("invalid options for middleware %s: options not provided", Name)
|
|
}
|
|
|
|
var confBytes []byte
|
|
var h *hook
|
|
if confBytes, err = yaml.Marshal(cfg.Configuration); err == nil {
|
|
var c container.Container
|
|
if c, err = container.GetContainer(cfg.Source, confBytes, storage); err == nil {
|
|
h = &hook{c}
|
|
}
|
|
}
|
|
return h, err
|
|
}
|
|
|
|
// ErrTorrentUnapproved is the error returned when a torrent hash is invalid.
|
|
var ErrTorrentUnapproved = bittorrent.ClientError("unapproved torrent")
|
|
|
|
type hook struct {
|
|
hashContainer container.Container
|
|
}
|
|
|
|
func (h *hook) HandleAnnounce(ctx context.Context, req *bittorrent.AnnounceRequest, _ *bittorrent.AnnounceResponse) (context.Context, error) {
|
|
var err error
|
|
|
|
if !h.hashContainer.Approved(req.InfoHash) {
|
|
err = ErrTorrentUnapproved
|
|
}
|
|
|
|
return ctx, err
|
|
}
|
|
|
|
func (h *hook) HandleScrape(ctx context.Context, _ *bittorrent.ScrapeRequest, _ *bittorrent.ScrapeResponse) (context.Context, error) {
|
|
// Scrapes don't require any protection.
|
|
return ctx, nil
|
|
}
|
|
|
|
func (h *hook) Stop() stop.Result {
|
|
if st, isOk := h.hashContainer.(stop.Stopper); isOk {
|
|
return st.Stop()
|
|
}
|
|
return stop.AlreadyStopped
|
|
}
|