mirror of
https://github.com/idanoo/autobrr
synced 2025-07-22 16:29:12 +00:00
feat(tools): Add a simple MockIndexer helper for IRC announcing and indexing (#555)
* Add a simple SelfIndexer for IRC announcing and indexing * Rename to MockIndexer * fix: close file after reading
This commit is contained in:
parent
ef088c27ad
commit
0f2ce26ba2
7 changed files with 242 additions and 6 deletions
|
@ -5,7 +5,7 @@ identifier: mock
|
|||
description: MockIndexer is a mock indexer.
|
||||
language: en-us
|
||||
urls:
|
||||
- http://localhost.test/
|
||||
- http://localhost:3999
|
||||
privacy: private
|
||||
protocol: torrent
|
||||
supports:
|
||||
|
@ -20,10 +20,10 @@ settings:
|
|||
regex: /([\da-fA-F]{20})
|
||||
|
||||
irc:
|
||||
network: LocalHost
|
||||
network: Mock
|
||||
server: localhost
|
||||
port: 6697
|
||||
tls: true
|
||||
tls: false
|
||||
channels:
|
||||
- "#announces"
|
||||
announcers:
|
||||
|
@ -51,8 +51,8 @@ irc:
|
|||
type: single
|
||||
lines:
|
||||
- test:
|
||||
- "New Torrent Announcement: <PC :: Iso> Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' - http://www.localhost.test/torrent/000000"
|
||||
- "New Torrent Announcement: <PC :: Iso> Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' freeleech - http://www.localhost.test/torrent/000000"
|
||||
- "New Torrent Announcement: <PC :: Iso> Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' - http://localhost:3999/torrent/000000"
|
||||
- "New Torrent Announcement: <PC :: Iso> Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' freeleech - http://localhost:3999/torrent/000000"
|
||||
pattern: New Torrent Announcement:\s*<([^>]*)>\s*Name:'(.*)' uploaded by '([^']*)'\s*(freeleech)*\s*-\s*(https?\:\/\/[^\/]+\/)torrent\/(\d+)
|
||||
vars:
|
||||
- category
|
||||
|
@ -63,6 +63,6 @@ irc:
|
|||
- torrentId
|
||||
|
||||
match:
|
||||
torrenturl: "/rss/download/{{ .torrentId }}/{{ .rsskey }}/{{ .torrentName }}.torrent"
|
||||
torrenturl: "/file/{{ .torrentId }}/{{ .torrentName }}.torrent"
|
||||
encode:
|
||||
- torrentName
|
||||
|
|
29
test/mockindexer/README.md
Normal file
29
test/mockindexer/README.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# autobrr MockIndexer
|
||||
|
||||
This is a simple IRC announcer and torrent indexer rolled into one. It is built
|
||||
as a tool for testing IRC announces and actions.
|
||||
|
||||
## Getting started
|
||||
|
||||
* Put a torrent file in `./files`, name it `1.torrent`.
|
||||
* Run the MockIndexer with `go run main.go`.
|
||||
|
||||
For autobrr, uncomment the `customDefinitions` line in `config.toml` to load the
|
||||
extra indexer definitions. Then start autobrr as usual.
|
||||
|
||||
* Add an instance of the MockIndexer in autobrr UI. Pick any nickname,
|
||||
_don't set any auth_.
|
||||
* Set up an action - for example the watchdir action which will make autobrr
|
||||
actually download the announced torrent file from the MockIndexer.
|
||||
|
||||
Posting announces.
|
||||
|
||||
* Open `http://localhost:3999` in your browser. A simple input will allow you to
|
||||
post announces to the channel. For example, to announce the `1.torrent` file
|
||||
added to the `./files` dir, send this,
|
||||
|
||||
```
|
||||
New Torrent Announcement: <PC :: Iso> Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' freeleech - http://localhost:3999/torrent/1
|
||||
```
|
||||
|
||||
It is the `1` at the end of the announce line that should match the file name.
|
1
test/mockindexer/files/.gitignore
vendored
Normal file
1
test/mockindexer/files/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.torrent
|
59
test/mockindexer/irc/client.go
Normal file
59
test/mockindexer/irc/client.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package irc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
conn net.Conn
|
||||
writer chan string
|
||||
|
||||
botName string
|
||||
channelName string
|
||||
nick string
|
||||
user string
|
||||
|
||||
handler func(c *Client, cmd []string)
|
||||
}
|
||||
|
||||
type ClientHandler interface {
|
||||
Handle(c Client, cmd []string)
|
||||
}
|
||||
|
||||
func NewClient(conn net.Conn, botName, channelName string) *Client {
|
||||
client := &Client{
|
||||
botName: botName,
|
||||
channelName: channelName,
|
||||
conn: conn,
|
||||
writer: make(chan string),
|
||||
}
|
||||
|
||||
client.handler = RegistrationHandler
|
||||
|
||||
go client.readerLoop()
|
||||
go client.writerLoop()
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *Client) readerLoop() {
|
||||
scanner := bufio.NewScanner(c.conn)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
cmd := strings.Split(line, " ")
|
||||
|
||||
log.Printf("%s", scanner.Text())
|
||||
|
||||
c.handler(c, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) writerLoop() {
|
||||
for cmd := range c.writer {
|
||||
c.conn.Write([]byte(cmd + "\r\n"))
|
||||
}
|
||||
}
|
38
test/mockindexer/irc/handlers.go
Normal file
38
test/mockindexer/irc/handlers.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package irc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func RegistrationHandler(c *Client, cmd []string) {
|
||||
switch cmd[0] {
|
||||
case "NICK":
|
||||
c.nick = cmd[1]
|
||||
break
|
||||
case "USER":
|
||||
c.user = cmd[1]
|
||||
}
|
||||
|
||||
if c.nick != "" && c.user != "" {
|
||||
log.Printf("Logged in\n")
|
||||
|
||||
c.handler = CommandHandler
|
||||
|
||||
c.writer <- fmt.Sprintf(
|
||||
"001 %s :\r\n002 %s :\r\n003 %s :\r\n004 %s n n-d o o\r\n251 %s :\r\n422 %s :",
|
||||
c.nick, c.nick, c.nick, c.nick, c.nick, c.nick)
|
||||
}
|
||||
}
|
||||
|
||||
func CommandHandler(c *Client, cmd []string) {
|
||||
switch cmd[0] {
|
||||
case "JOIN":
|
||||
c.writer <- fmt.Sprintf("331 %s %s :No topic", c.nick, c.channelName)
|
||||
c.writer <- fmt.Sprintf("353 %s = %s :%s %s", c.nick, c.channelName, c.nick, c.botName)
|
||||
c.writer <- fmt.Sprintf("366 %s %s :End", c.nick, c.channelName)
|
||||
case "PING":
|
||||
c.writer <- fmt.Sprintf("PONG n %s", strings.Join(cmd[1:], " "))
|
||||
}
|
||||
}
|
50
test/mockindexer/irc/server.go
Normal file
50
test/mockindexer/irc/server.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package irc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
listener net.Listener
|
||||
clients []*Client
|
||||
options *ServerOptions
|
||||
}
|
||||
|
||||
type ServerOptions struct {
|
||||
BotName string
|
||||
Channel string
|
||||
}
|
||||
|
||||
func NewServer(options *ServerOptions) (*Server, error) {
|
||||
listener, err := net.Listen("tcp", "localhost:6697")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Server{
|
||||
listener: listener,
|
||||
options: options,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) Run() {
|
||||
for {
|
||||
conn, err := s.listener.Accept()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed accept: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
s.clients = append(s.clients, NewClient(conn, s.options.BotName, s.options.Channel))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) SendAll(line string) {
|
||||
for _, client := range s.clients {
|
||||
client.writer <- fmt.Sprintf(":%s PRIVMSG %s :%s", s.options.BotName, s.options.Channel, line)
|
||||
}
|
||||
}
|
59
test/mockindexer/main.go
Normal file
59
test/mockindexer/main.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/autobrr/autobrr/test/mockindexer/irc"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s, err := irc.NewServer(&irc.ServerOptions{
|
||||
BotName: "_AnnounceBot_",
|
||||
Channel: "#announces",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Err: %v", err)
|
||||
}
|
||||
|
||||
go s.Run()
|
||||
|
||||
log.Print("autobrr MockIndexer running")
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("<html><form method=\"POST\" action=\"/send\">Send an announce line to the channel<br><input style=\"width: 100%; margin-top: 5px; margin-bottom: 5px;\" name=\"line\" type=\"text\"><br><button type=\"submit\">Send to channel</button></form></html>"))
|
||||
})
|
||||
|
||||
r.Get("/file/{fileId}/{fileName}", func(w http.ResponseWriter, r *http.Request) {
|
||||
f, err := os.Open("files/" + chi.URLParam(r, "fileId") + ".torrent")
|
||||
if err != nil {
|
||||
log.Fatalf("Err: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
w.Header().Set("Content-Disposition", "attachment; filename="+chi.URLParam(r, "fileName"))
|
||||
w.Header().Set("Content-Type", "application/x-bittorrent")
|
||||
|
||||
io.Copy(w, bufio.NewReader(f))
|
||||
})
|
||||
|
||||
r.Post("/send", func(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
|
||||
line := r.Form.Get("line")
|
||||
s.SendAll(line)
|
||||
|
||||
http.Redirect(w, r, "/", 302)
|
||||
})
|
||||
|
||||
http.ListenAndServe("localhost:3999", r)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue