mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 00:39:13 +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.
|
description: MockIndexer is a mock indexer.
|
||||||
language: en-us
|
language: en-us
|
||||||
urls:
|
urls:
|
||||||
- http://localhost.test/
|
- http://localhost:3999
|
||||||
privacy: private
|
privacy: private
|
||||||
protocol: torrent
|
protocol: torrent
|
||||||
supports:
|
supports:
|
||||||
|
@ -20,10 +20,10 @@ settings:
|
||||||
regex: /([\da-fA-F]{20})
|
regex: /([\da-fA-F]{20})
|
||||||
|
|
||||||
irc:
|
irc:
|
||||||
network: LocalHost
|
network: Mock
|
||||||
server: localhost
|
server: localhost
|
||||||
port: 6697
|
port: 6697
|
||||||
tls: true
|
tls: false
|
||||||
channels:
|
channels:
|
||||||
- "#announces"
|
- "#announces"
|
||||||
announcers:
|
announcers:
|
||||||
|
@ -51,8 +51,8 @@ irc:
|
||||||
type: single
|
type: single
|
||||||
lines:
|
lines:
|
||||||
- test:
|
- 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' - http://localhost:3999/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' freeleech - http://localhost:3999/torrent/000000"
|
||||||
pattern: New Torrent Announcement:\s*<([^>]*)>\s*Name:'(.*)' uploaded by '([^']*)'\s*(freeleech)*\s*-\s*(https?\:\/\/[^\/]+\/)torrent\/(\d+)
|
pattern: New Torrent Announcement:\s*<([^>]*)>\s*Name:'(.*)' uploaded by '([^']*)'\s*(freeleech)*\s*-\s*(https?\:\/\/[^\/]+\/)torrent\/(\d+)
|
||||||
vars:
|
vars:
|
||||||
- category
|
- category
|
||||||
|
@ -63,6 +63,6 @@ irc:
|
||||||
- torrentId
|
- torrentId
|
||||||
|
|
||||||
match:
|
match:
|
||||||
torrenturl: "/rss/download/{{ .torrentId }}/{{ .rsskey }}/{{ .torrentName }}.torrent"
|
torrenturl: "/file/{{ .torrentId }}/{{ .torrentName }}.torrent"
|
||||||
encode:
|
encode:
|
||||||
- torrentName
|
- 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