From 2daeedbdc70821e31dbfed1d1f4db6de3840207b Mon Sep 17 00:00:00 2001 From: Ludvig Lundgren Date: Thu, 13 Jan 2022 21:26:23 +0100 Subject: [PATCH] Feature: Support multi user per irc network (#78) * feat: delete irc network in transaction * feat: use compound key for irc handlers * chore: update deps * refactor: start network * refactor: init irc handler * indexers: update network name --- go.mod | 6 +- go.sum | 151 ------ internal/database/irc.go | 14 +- internal/database/sqlite.go | 17 + internal/http/irc.go | 16 - internal/indexer/definitions/hd-torrents.yaml | 2 +- internal/indexer/definitions/milkie.yaml | 2 +- internal/indexer/definitions/mock1.yaml | 63 +++ internal/indexer/definitions/mock2.yaml | 63 +++ .../indexer/definitions/trancetraffic.yaml | 4 +- internal/indexer/service.go | 10 + internal/irc/handler.go | 475 ++++++++++-------- internal/irc/service.go | 94 ++-- web/src/forms/settings/IndexerForms.tsx | 2 +- 14 files changed, 491 insertions(+), 428 deletions(-) create mode 100644 internal/indexer/definitions/mock1.yaml create mode 100644 internal/indexer/definitions/mock2.yaml diff --git a/go.mod b/go.mod index 7097133..3088761 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/gorilla/sessions v1.2.1 github.com/kr/pretty v0.3.0 // indirect github.com/lib/pq v1.10.4 - github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.10 github.com/pkg/errors v0.9.1 github.com/r3labs/sse/v2 v2.7.2 @@ -29,13 +28,10 @@ require ( golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac - golang.org/x/tools v0.1.8 // indirect gopkg.in/ini.v1 v1.64.0 // indirect gopkg.in/irc.v3 v3.1.4 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 - modernc.org/ccgo/v3 v3.14.0 // indirect - modernc.org/libc v1.13.2 // indirect - modernc.org/sqlite v1.14.3 ) diff --git a/go.sum b/go.sum index da56f64..2288238 100644 --- a/go.sum +++ b/go.sum @@ -257,7 +257,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -280,8 +279,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -342,8 +339,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -377,12 +372,9 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-sqlite3 v1.7.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -441,8 +433,6 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4 github.com/r3labs/sse/v2 v2.7.2 h1:GUyMTu1EPAVUDPZUSkFWx1fXYXXxH4xAcTAIWSs89ZU= github.com/r3labs/sse/v2 v2.7.2/go.mod h1:hUrYMKfu9WquG9MyI0r6TKiNH+6Sw/QPKm2YbNbU5g8= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -504,7 +494,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= @@ -569,8 +558,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -617,7 +604,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -696,7 +682,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -716,9 +701,6 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -785,7 +767,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -797,12 +778,9 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -970,135 +948,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/cc/v3 v3.35.22 h1:BzShpwCAP7TWzFppM4k2t03RhXhgYqaibROWkrWq7lE= -modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= -modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= -modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= -modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= -modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= -modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= -modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= -modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= -modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= -modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= -modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= -modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= -modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= -modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= -modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= -modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= -modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= -modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= -modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= -modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= -modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= -modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= -modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= -modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= -modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= -modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= -modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= -modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= -modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= -modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= -modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= -modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= -modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= -modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= -modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= -modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= -modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM= -modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= -modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= -modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8= -modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= -modernc.org/ccgo/v3 v3.14.0 h1:Zr1Ny9+7r5yAiXpBdgp8XiXqkNA4ARrRphHGHVXeAp0= -modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q= -modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA= -modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= -modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= -modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= -modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= -modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= -modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= -modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= -modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= -modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= -modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= -modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= -modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= -modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= -modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= -modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= -modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= -modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= -modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= -modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= -modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= -modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= -modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= -modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= -modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= -modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= -modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= -modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= -modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= -modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= -modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= -modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= -modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= -modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= -modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= -modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= -modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= -modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= -modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= -modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= -modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= -modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= -modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= -modernc.org/libc v1.13.2 h1:GCFjY9bmwDZ/TJC4OZOUWaNgxIxwb104C/QZrqpcVEA= -modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= -modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= -modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.14.3 h1:psrTwgpEujgWEP3FNdsC9yNh5tSeA77U0GeWhHH4XmQ= -modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/tcl v1.9.2 h1:YA87dFLOsR2KqMka371a2Xgr+YsyUwo7OmHVSv/kztw= -modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.2.20 h1:DyboxM1sJR2NB803j2StnbnL6jcQXz273OhHDGu8dGk= -modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/database/irc.go b/internal/database/irc.go index 9531bce..690a0df 100644 --- a/internal/database/irc.go +++ b/internal/database/irc.go @@ -49,25 +49,25 @@ func (r *IrcRepo) GetNetworkByID(id int64) (*domain.IrcNetwork, error) { } func (r *IrcRepo) DeleteNetwork(ctx context.Context, id int64) error { - tx, err := r.db.handler.BeginTx(ctx, nil) + tx, err := r.db.BeginTx(ctx, nil) if err != nil { return err } defer tx.Rollback() - _, err = tx.ExecContext(ctx, `DELETE FROM irc_network WHERE id = ?`, id) - if err != nil { - log.Error().Stack().Err(err).Msgf("error deleting network: %v", id) - return err - } - _, err = tx.ExecContext(ctx, `DELETE FROM irc_channel WHERE network_id = ?`, id) if err != nil { log.Error().Stack().Err(err).Msgf("error deleting channels for network: %v", id) return err } + _, err = tx.ExecContext(ctx, `DELETE FROM irc_network WHERE id = ?`, id) + if err != nil { + log.Error().Stack().Err(err).Msgf("error deleting network: %v", id) + return err + } + err = tx.Commit() if err != nil { log.Error().Stack().Err(err).Msgf("error deleting network: %v", id) diff --git a/internal/database/sqlite.go b/internal/database/sqlite.go index 5030175..6589acf 100644 --- a/internal/database/sqlite.go +++ b/internal/database/sqlite.go @@ -79,3 +79,20 @@ func (db *SqliteDB) Close() error { } return nil } + +func (db *SqliteDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { + tx, err := db.handler.BeginTx(ctx, opts) + if err != nil { + return nil, err + } + + return &Tx{ + Tx: tx, + handler: db, + }, nil +} + +type Tx struct { + *sql.Tx + handler *SqliteDB +} diff --git a/internal/http/irc.go b/internal/http/irc.go index 8591eb5..5e14b25 100644 --- a/internal/http/irc.go +++ b/internal/http/irc.go @@ -19,7 +19,6 @@ type ircService interface { StoreNetwork(ctx context.Context, network *domain.IrcNetwork) error UpdateNetwork(ctx context.Context, network *domain.IrcNetwork) error StoreChannel(networkID int64, channel *domain.IrcChannel) error - StopNetwork(name string) error } type ircHandler struct { @@ -39,7 +38,6 @@ func (h ircHandler) Routes(r chi.Router) { r.Post("/", h.storeNetwork) r.Put("/network/{networkID}", h.updateNetwork) r.Post("/network/{networkID}/channel", h.storeChannel) - r.Get("/network/{networkID}/stop", h.stopNetwork) r.Get("/network/{networkID}", h.getNetworkByID) r.Delete("/network/{networkID}", h.deleteNetwork) } @@ -132,20 +130,6 @@ func (h ircHandler) storeChannel(w http.ResponseWriter, r *http.Request) { h.encoder.StatusResponse(ctx, w, nil, http.StatusCreated) } -func (h ircHandler) stopNetwork(w http.ResponseWriter, r *http.Request) { - var ( - ctx = r.Context() - networkID = chi.URLParam(r, "networkID") - ) - - err := h.service.StopNetwork(networkID) - if err != nil { - // - } - - h.encoder.StatusResponse(ctx, w, nil, http.StatusCreated) -} - func (h ircHandler) deleteNetwork(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() diff --git a/internal/indexer/definitions/hd-torrents.yaml b/internal/indexer/definitions/hd-torrents.yaml index 3dba54e..fab526a 100644 --- a/internal/indexer/definitions/hd-torrents.yaml +++ b/internal/indexer/definitions/hd-torrents.yaml @@ -20,7 +20,7 @@ settings: help: "Check how to get cookies in your browser and find the uid and pass cookies. Example: uid=1234; pass=asdf12347asdf13" irc: - network: P2P-NET + network: P2P-Network server: irc.p2p-network.net port: 6697 tls: true diff --git a/internal/indexer/definitions/milkie.yaml b/internal/indexer/definitions/milkie.yaml index 9a3a628..086168d 100644 --- a/internal/indexer/definitions/milkie.yaml +++ b/internal/indexer/definitions/milkie.yaml @@ -20,7 +20,7 @@ settings: regex: /([a-zA-Z0-9\+]) irc: - network: p2p-network.net + network: P2P-Network server: irc.p2p-network.net port: 6697 tls: true diff --git a/internal/indexer/definitions/mock1.yaml b/internal/indexer/definitions/mock1.yaml new file mode 100644 index 0000000..a898a31 --- /dev/null +++ b/internal/indexer/definitions/mock1.yaml @@ -0,0 +1,63 @@ +--- +#id: tracker01 +name: Mock1 +identifier: mock1 +description: Mock1 is just a mock indexer +language: en-us +urls: + - http://localhost.test +privacy: private +protocol: torrent +supports: + - irc + - rss +source: custom +settings: + - name: rsskey + type: secret + label: RSS key + help: "Go to your profile and copy your RSS key" + regex: /([\da-fA-F]{20}) + +irc: + network: LocalHost + server: localhost + port: 6697 + tls: true + channels: + - "#announces" + announcers: + - _AnnounceBot_ + settings: + - name: nickserv.account + type: text + required: true + label: NickServ Account + help: NickServ account. Make sure to group your user and bot. Eg. user_bot + - name: nickserv.password + type: secret + required: false + label: NickServ Password + help: NickServ password + +parse: + type: single + lines: + - test: + - "New Torrent Announcement: Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' - http://www.tracker01.test/torrent/000000" + - "New Torrent Announcement: Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' freeleech - http://www.tracker01.test/torrent/000000" + pattern: New Torrent Announcement:\s*<([^>]*)>\s*Name:'(.*)' uploaded by '([^']*)'\s*(freeleech)*\s*-\s*(https?\:\/\/[^\/]+\/)torrent\/(\d+) + vars: + - category + - torrentName + - uploader + - freeleech + - baseUrl + - torrentId + + match: + torrenturl: "{{ .baseUrl }}rss/download/{{ .torrentId }}/{{ .rsskey }}/{{ .torrentName }}.torrent" + encode: + - torrentName + + diff --git a/internal/indexer/definitions/mock2.yaml b/internal/indexer/definitions/mock2.yaml new file mode 100644 index 0000000..7bed51f --- /dev/null +++ b/internal/indexer/definitions/mock2.yaml @@ -0,0 +1,63 @@ +--- +#id: tracker01 +name: Mock2 +identifier: mock2 +description: Mock2 is just a mock indexer +language: en-us +urls: + - http://localhost.test +privacy: private +protocol: torrent +supports: + - irc + - rss +source: custom +settings: + - name: rsskey + type: secret + label: RSS key + help: "Go to your profile and copy your RSS key" + regex: /([\da-fA-F]{20}) + +irc: + network: LocalHost + server: localhost + port: 6697 + tls: true + channels: + - "#mannounces" + announcers: + - Jerry + settings: + - name: nickserv.account + type: text + required: true + label: NickServ Account + help: NickServ account. Make sure to group your user and bot. Eg. user_bot + - name: nickserv.password + type: secret + required: false + label: NickServ Password + help: NickServ password + +parse: + type: single + lines: + - test: + - "New Torrent Announcement: Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' - http://www.tracker01.test/torrent/000000" + - "New Torrent Announcement: Name:'debian live 10 6 0 amd64 standard iso' uploaded by 'Anonymous' freeleech - http://www.tracker01.test/torrent/000000" + pattern: New Torrent Announcement:\s*<([^>]*)>\s*Name:'(.*)' uploaded by '([^']*)'\s*(freeleech)*\s*-\s*(https?\:\/\/[^\/]+\/)torrent\/(\d+) + vars: + - category + - torrentName + - uploader + - freeleech + - baseUrl + - torrentId + + match: + torrenturl: "{{ .baseUrl }}rss/download/{{ .torrentId }}/{{ .rsskey }}/{{ .torrentName }}.torrent" + encode: + - torrentName + + diff --git a/internal/indexer/definitions/trancetraffic.yaml b/internal/indexer/definitions/trancetraffic.yaml index 00925ca..f5e16c0 100644 --- a/internal/indexer/definitions/trancetraffic.yaml +++ b/internal/indexer/definitions/trancetraffic.yaml @@ -19,7 +19,7 @@ settings: help: "Go to https://www.trancetraffic.com/links.php, click on RSS Feed and copy your passkey from the url." irc: - network: P2P-NET + network: P2P-Network server: irc.p2p-network.net port: 6697 tls: true @@ -35,7 +35,7 @@ irc: help: NickServ account. Make sure to group your user and bot. Eg. user|autodl - name: nickserv.password type: secret - required: false + required: true label: NickServ Password help: NickServ password diff --git a/internal/indexer/service.go b/internal/indexer/service.go index 50fb4b8..6fe389c 100644 --- a/internal/indexer/service.go +++ b/internal/indexer/service.go @@ -243,6 +243,16 @@ func (s *service) addIndexer(indexer domain.Indexer) error { s.mapIRCIndexerLookup(indexer.Identifier, *indexerDefinition) + // add to irc server lookup table + s.mapIRCServerDefinitionLookup(indexerDefinition.IRC.Server, *indexerDefinition) + + // check if it has api and add to api service + if indexerDefinition.Enabled && indexerDefinition.HasApi() { + if err := s.apiService.AddClient(indexerDefinition.Identifier, indexerDefinition.SettingsMap); err != nil { + log.Error().Stack().Err(err).Msgf("indexer.start: could not init api client for: '%v'", indexer.Identifier) + } + } + return nil } diff --git a/internal/irc/handler.go b/internal/irc/handler.go index 9b39052..0f7c4e3 100644 --- a/internal/irc/handler.go +++ b/internal/irc/handler.go @@ -52,7 +52,7 @@ type Handler struct { filterService filter.Service releaseService release.Service announceProcessors map[string]announce.Processor - definitions []domain.IndexerDefinition + definitions map[string]*domain.IndexerDefinition client *irc.Client conn net.Conn @@ -79,22 +79,35 @@ func NewHandler(network domain.IrcNetwork, filterService filter.Service, release network: &network, filterService: filterService, releaseService: releaseService, - definitions: definitions, + definitions: map[string]*domain.IndexerDefinition{}, announceProcessors: map[string]announce.Processor{}, validAnnouncers: map[string]struct{}{}, validChannels: map[string]struct{}{}, channelHealth: map[string]*channelHealth{}, } + // init indexer, announceProcessor + h.InitIndexers(definitions) + + return h +} + +func (h *Handler) InitIndexers(definitions []domain.IndexerDefinition) { // Networks can be shared by multiple indexers but channels are unique // so let's add a new AnnounceProcessor per channel for _, definition := range definitions { - // indexers can use multiple channels, but it's not common, but let's handle that anyway. + if _, ok := h.definitions[definition.Identifier]; ok { + continue + } + + h.definitions[definition.Identifier] = &definition + + // indexers can use multiple channels, but it'h not common, but let'h handle that anyway. for _, channel := range definition.IRC.Channels { // some channels are defined in mixed case channel = strings.ToLower(channel) - h.announceProcessors[channel] = announce.NewAnnounceProcessor(definition, filterService, releaseService) + h.announceProcessors[channel] = announce.NewAnnounceProcessor(definition, h.filterService, h.releaseService) h.channelHealth[channel] = &channelHealth{ name: channel, @@ -110,20 +123,25 @@ func NewHandler(network domain.IrcNetwork, filterService filter.Service, release h.validAnnouncers[announcer] = struct{}{} } } - - return h } -func (s *Handler) Run() error { - //log.Debug().Msgf("server %+v", s.network) +func (h *Handler) removeIndexer() { + // TODO remove validAnnouncers + // TODO remove validChannels + // TODO remove definition + // TODO remove announceProcessor +} - if s.network.Server == "" { +func (h *Handler) Run() error { + //log.Debug().Msgf("server %+v", h.network) + + if h.network.Server == "" { return errors.New("addr not set") } ctx, cancel := context.WithCancel(context.Background()) - s.ctx = ctx - s.cancel = cancel + h.ctx = ctx + h.cancel = cancel dialer := net.Dialer{ Timeout: connectTimeout, @@ -132,122 +150,49 @@ func (s *Handler) Run() error { var netConn net.Conn var err error - addr := fmt.Sprintf("%v:%v", s.network.Server, s.network.Port) + addr := fmt.Sprintf("%v:%v", h.network.Server, h.network.Port) // decide to use SSL or not - if s.network.TLS { + if h.network.TLS { tlsConf := &tls.Config{ InsecureSkipVerify: true, } - netConn, err = dialer.DialContext(s.ctx, "tcp", addr) + netConn, err = dialer.DialContext(h.ctx, "tcp", addr) if err != nil { log.Error().Err(err).Msgf("failed to dial %v", addr) return fmt.Errorf("failed to dial %q: %v", addr, err) } netConn = tls.Client(netConn, tlsConf) - s.conn = netConn + h.conn = netConn } else { - netConn, err = dialer.DialContext(s.ctx, "tcp", addr) + netConn, err = dialer.DialContext(h.ctx, "tcp", addr) if err != nil { log.Error().Err(err).Msgf("failed to dial %v", addr) return fmt.Errorf("failed to dial %q: %v", addr, err) } - s.conn = netConn + h.conn = netConn } log.Info().Msgf("Connected to: %v", addr) config := irc.ClientConfig{ - Nick: s.network.NickServ.Account, - User: s.network.NickServ.Account, - Name: s.network.NickServ.Account, - Pass: s.network.Pass, - Handler: irc.HandlerFunc(func(c *irc.Client, m *irc.Message) { - switch m.Command { - case "001": - // 001 is a welcome event, so we join channels there - err := s.onConnect(s.network.Channels) - if err != nil { - log.Error().Msgf("error joining channels %v", err) - } - - case "372", "375", "376": - // Handle MOTD - - // 322 TOPIC - // 333 UP - // 353 @ - // 396 Displayed host - case "366": // JOINED - s.handleJoined(m) - - case "JOIN": - log.Trace().Msgf("%v: JOIN %v", s.network.Server, m) - - case "433": - // TODO: handle nick in use - log.Debug().Msgf("%v: NICK IN USE: %v", s.network.Server, m) - - case "448", "473", "475", "477": - // TODO: handle join failed - log.Debug().Msgf("%v: JOIN FAILED %v: %v", s.network.Server, m.Params[1], m) - - case "900": // Invite bot logged in - log.Debug().Msgf("%v: %v", s.network.Server, m.Trailing()) - - case "KICK": - log.Debug().Msgf("%v: KICK: %v", s.network.Server, m) - - case "MODE": - err := s.handleMode(m) - if err != nil { - log.Error().Err(err).Msgf("error MODE change: %v", m) - } - - case "INVITE": - // TODO: handle invite - log.Debug().Msgf("%v: INVITE: %v", s.network.Server, m) - - case "PART": - // TODO: handle parted - log.Debug().Msgf("%v: PART: %v", s.network.Server, m) - - case "PRIVMSG": - err := s.onMessage(m) - if err != nil { - log.Error().Msgf("error on message %v", err) - } - - case "CAP": - log.Debug().Msgf("%v: CAP: %v", s.network.Server, m) - - case "NOTICE": - log.Trace().Msgf("%v: %v", s.network.Server, m) - - case "PING": - err := s.handlePing(m) - if err != nil { - log.Error().Stack().Err(err) - } - - //case "372": - // log.Debug().Msgf("372: %v", m) - default: - log.Trace().Msgf("%v: %v", s.network.Server, m) - } - }), + Nick: h.network.NickServ.Account, + User: h.network.NickServ.Account, + Name: h.network.NickServ.Account, + Pass: h.network.Pass, + Handler: irc.HandlerFunc(h.handleMessage), } // Create the client - client := irc.NewClient(s.conn, config) + client := irc.NewClient(h.conn, config) - s.client = client + h.client = client // set connected since now - s.setConnectionStatus() + h.setConnectionStatus() // Connect err = client.RunContext(ctx) @@ -255,7 +200,7 @@ func (s *Handler) Run() error { log.Error().Err(err).Msgf("could not connect to %v", addr) // reset connection status on handler and channels - s.resetConnectionStatus() + h.resetConnectionStatus() return err } @@ -263,79 +208,172 @@ func (s *Handler) Run() error { return nil } -func (s *Handler) setConnectionStatus() { - // set connected since now - s.connectedSince = time.Now() - s.connected = true +func (h *Handler) handleMessage(c *irc.Client, m *irc.Message) { + switch m.Command { + case "001": + // 001 is a welcome event, so we join channels there + err := h.onConnect(h.network.Channels) + if err != nil { + log.Error().Msgf("error joining channels %v", err) + } + + case "372", "375", "376": + // Handle MOTD + + // 322 TOPIC + // 333 UP + // 353 @ + // 396 Displayed host + case "366": // JOINED + h.handleJoined(m) + + case "JOIN": + if h.isOurNick(m.Prefix.Name) { + log.Trace().Msgf("%v: JOIN %v", h.network.Server, m) + } + + case "QUIT": + if h.isOurNick(m.Prefix.Name) { + log.Trace().Msgf("%v: QUIT %v", h.network.Server, m) + } + + case "433": + // TODO: handle nick in use + log.Debug().Msgf("%v: NICK IN USE: %v", h.network.Server, m) + + case "448", "473", "475", "477": + // TODO: handle join failed + log.Debug().Msgf("%v: JOIN FAILED %v: %v", h.network.Server, m.Params[1], m) + + case "900": // Invite bot logged in + log.Debug().Msgf("%v: %v", h.network.Server, m.Trailing()) + + case "KICK": + log.Debug().Msgf("%v: KICK: %v", h.network.Server, m) + + case "MODE": + err := h.handleMode(m) + if err != nil { + log.Error().Err(err).Msgf("error MODE change: %v", m) + } + + case "INVITE": + // TODO: handle invite + log.Debug().Msgf("%v: INVITE: %v", h.network.Server, m) + + case "PART": + // TODO: handle parted + if h.isOurNick(m.Prefix.Name) { + log.Debug().Msgf("%v: PART: %v", h.network.Server, m) + } + + case "PRIVMSG": + err := h.onMessage(m) + if err != nil { + log.Error().Msgf("error on message %v", err) + } + + case "CAP": + log.Debug().Msgf("%v: CAP: %v", h.network.Server, m) + + case "NOTICE": + log.Trace().Msgf("%v: %v", h.network.Server, m) + + case "PING": + err := h.handlePing(m) + if err != nil { + log.Error().Stack().Err(err) + } + + //case "372": + // log.Debug().Msgf("372: %v", m) + //default: + // log.Trace().Msgf("%v: %v", h.network.Server, m) + } + return } -func (s *Handler) resetConnectionStatus() { +func (h *Handler) isOurNick(nick string) bool { + return h.network.NickServ.Account == nick +} + +func (h *Handler) setConnectionStatus() { + // set connected since now + h.connectedSince = time.Now() + h.connected = true +} + +func (h *Handler) resetConnectionStatus() { // set connected false if we loose connection or stop - s.connectedSince = time.Time{} - s.connected = false + h.connectedSince = time.Time{} + h.connected = false // loop over channelHealth and reset each one - for _, h := range s.channelHealth { + for _, h := range h.channelHealth { if h != nil { h.resetMonitoring() } } } -func (s *Handler) GetNetwork() *domain.IrcNetwork { - return s.network +func (h *Handler) GetNetwork() *domain.IrcNetwork { + return h.network } -func (s *Handler) UpdateNetwork(network *domain.IrcNetwork) { - s.network = network +func (h *Handler) UpdateNetwork(network *domain.IrcNetwork) { + h.network = network } -func (s *Handler) Stop() { - s.cancel() +func (h *Handler) SetNetwork(network *domain.IrcNetwork) { + h.network = network +} - if !s.isStopped() { - close(s.stopped) +func (h *Handler) Stop() { + h.cancel() + + if !h.isStopped() { + close(h.stopped) } - if s.conn != nil { - s.conn.Close() + if h.conn != nil { + h.conn.Close() } } -func (s *Handler) isStopped() bool { +func (h *Handler) isStopped() bool { select { - case <-s.stopped: + case <-h.stopped: return true default: return false } } -func (s *Handler) Restart() error { - s.cancel() +func (h *Handler) Restart() error { + h.cancel() - if !s.isStopped() { - close(s.stopped) + if !h.isStopped() { + close(h.stopped) } - if s.conn != nil { - s.conn.Close() + if h.conn != nil { + h.conn.Close() } time.Sleep(2 * time.Second) - return s.Run() + return h.Run() } -func (s *Handler) onConnect(channels []domain.IrcChannel) error { +func (h *Handler) onConnect(channels []domain.IrcChannel) error { identified := false time.Sleep(2 * time.Second) - if s.network.NickServ.Password != "" { - err := s.handleNickServPRIVMSG(s.network.NickServ.Account, s.network.NickServ.Password) + if h.network.NickServ.Password != "" { + err := h.handleNickServPRIVMSG(h.network.NickServ.Account, h.network.NickServ.Password) if err != nil { - log.Error().Stack().Err(err).Msgf("error nickserv: %v", s.network.Name) + log.Error().Stack().Err(err).Msgf("error nickserv: %v", h.network.Name) return err } identified = true @@ -343,11 +381,10 @@ func (s *Handler) onConnect(channels []domain.IrcChannel) error { time.Sleep(3 * time.Second) - if s.network.InviteCommand != "" { - - err := s.handleInvitePRIVMSG(s.network.InviteCommand) + if h.network.InviteCommand != "" { + err := h.handleConnectCommands(h.network.InviteCommand) if err != nil { - log.Error().Stack().Err(err).Msgf("error sending connect command %v to network: %v", s.network.InviteCommand, s.network.Name) + log.Error().Stack().Err(err).Msgf("error sending connect command %v to network: %v", h.network.InviteCommand, h.network.Name) return err } @@ -356,7 +393,7 @@ func (s *Handler) onConnect(channels []domain.IrcChannel) error { if !identified { for _, channel := range channels { - err := s.HandleJoinChannel(channel.Name, channel.Password) + err := h.HandleJoinChannel(channel.Name, channel.Password) if err != nil { log.Error().Stack().Err(err) return err @@ -367,34 +404,33 @@ func (s *Handler) onConnect(channels []domain.IrcChannel) error { return nil } -func (s *Handler) OnJoin(msg string) (interface{}, error) { +func (h *Handler) OnJoin(msg string) (interface{}, error) { return nil, nil } -func (s *Handler) onMessage(msg *irc.Message) error { +func (h *Handler) onMessage(msg *irc.Message) error { // parse announce channel := &msg.Params[0] announcer := &msg.Name message := msg.Trailing() - // TODO add network // check if message is from a valid channel, if not return - validChannel := s.isValidChannel(*channel) + validChannel := h.isValidChannel(*channel) if !validChannel { return nil } // check if message is from announce bot, if not return - validAnnouncer := s.isValidAnnouncer(*announcer) + validAnnouncer := h.isValidAnnouncer(*announcer) if !validAnnouncer { return nil } // clean message cleanedMsg := cleanMessage(message) - log.Debug().Msgf("%v: %v %v: %v", s.network.Server, *channel, *announcer, cleanedMsg) + log.Debug().Msgf("%v: %v %v: %v", h.network.Server, *channel, *announcer, cleanedMsg) - if err := s.sendToAnnounceProcessor(*channel, cleanedMsg); err != nil { + if err := h.sendToAnnounceProcessor(*channel, cleanedMsg); err != nil { log.Error().Stack().Err(err).Msgf("could not queue line: %v", cleanedMsg) return err } @@ -402,11 +438,11 @@ func (s *Handler) onMessage(msg *irc.Message) error { return nil } -func (s *Handler) sendToAnnounceProcessor(channel string, msg string) error { +func (h *Handler) sendToAnnounceProcessor(channel string, msg string) error { channel = strings.ToLower(channel) // check if queue exists - queue, ok := s.announceProcessors[channel] + queue, ok := h.announceProcessors[channel] if !ok { return fmt.Errorf("queue '%v' not found", channel) } @@ -418,7 +454,7 @@ func (s *Handler) sendToAnnounceProcessor(channel string, msg string) error { return err } - v, ok := s.channelHealth[channel] + v, ok := h.channelHealth[channel] if !ok { return nil } @@ -428,11 +464,11 @@ func (s *Handler) sendToAnnounceProcessor(channel string, msg string) error { return nil } -func (s *Handler) sendPrivMessage(msg string) error { +func (h *Handler) sendPrivMessage(msg string) error { msg = strings.TrimLeft(msg, "/") - privMsg := fmt.Sprintf("PRIVMSG %s", msg) + privMsg := fmt.Sprintf("PRIVMSG %h", msg) - err := s.client.Write(privMsg) + err := h.client.Write(privMsg) if err != nil { log.Error().Err(err).Msgf("could not send priv msg: %v", msg) return err @@ -441,7 +477,7 @@ func (s *Handler) sendPrivMessage(msg string) error { return nil } -func (s *Handler) HandleJoinChannel(channel string, password string) error { +func (h *Handler) HandleJoinChannel(channel string, password string) error { // support channel password params := []string{channel} if password != "" { @@ -453,82 +489,105 @@ func (s *Handler) HandleJoinChannel(channel string, password string) error { Params: params, } - log.Trace().Msgf("%v: sending %v", s.network.Server, m.String()) + log.Trace().Msgf("%v: sending %v", h.network.Server, m.String()) time.Sleep(1 * time.Second) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Stack().Err(err).Msgf("error handling join: %v", m.String()) return err } - // only set values if channel is found in map - v, ok := s.channelHealth[channel] - if ok { - v.SetMonitoring() - } - return nil } -func (s *Handler) HandlePartChannel(channel string) error { +func (h *Handler) HandlePartChannel(channel string) error { m := irc.Message{ Command: "PART", Params: []string{channel}, } - log.Debug().Msgf("%v: %v", s.network.Server, m.String()) + log.Debug().Msgf("%v: %v", h.network.Server, m.String()) time.Sleep(1 * time.Second) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Err(err).Msgf("error handling part: %v", m.String()) return err } - log.Info().Msgf("Left channel '%v' on network '%s'", channel, s.network.Server) + // reset monitoring status + v, ok := h.channelHealth[channel] + if !ok { + return nil + } + + v.resetMonitoring() + + // TODO remove announceProcessor + + log.Info().Msgf("Left channel '%v' on network '%h'", channel, h.network.Server) return nil } -func (s *Handler) handleJoined(msg *irc.Message) { - log.Debug().Msgf("%v: JOINED: %v", s.network.Server, msg.Trailing()) +func (h *Handler) handleJoined(msg *irc.Message) { + log.Debug().Msgf("%v: JOINED: %v", h.network.Server, msg.Params[1]) - log.Info().Msgf("%v: Monitoring channel %s", s.network.Server, msg.Params[1]) -} + // get channel + channel := &msg.Params[1] -func (s *Handler) handleInvitePRIVMSG(msg string) error { - msg = strings.TrimPrefix(msg, "/msg") - split := strings.Split(msg, " ") - - m := irc.Message{ - Command: "PRIVMSG", - Params: split, + // set monitoring on current channelHealth, or add new + v, ok := h.channelHealth[strings.ToLower(*channel)] + if ok { + v.SetMonitoring() + } else if v == nil { + h.channelHealth[*channel] = &channelHealth{ + name: *channel, + monitoring: true, + monitoringSince: time.Now(), + } } - log.Info().Msgf("%v: Invite command: %v", s.network.Server, m.String()) + log.Info().Msgf("%v: Monitoring channel %v", h.network.Server, msg.Params[1]) +} - err := s.client.Write(m.String()) - if err != nil { - log.Error().Err(err).Msgf("error handling invite: %v", m.String()) - return err +func (h *Handler) handleConnectCommands(msg string) error { + connectCommand := strings.ReplaceAll(msg, "/msg", "") + connectCommands := strings.Split(connectCommand, ",") + + for _, command := range connectCommands { + cmd := strings.TrimSpace(command) + + m := irc.Message{ + Command: "PRIVMSG", + Params: strings.Split(cmd, " "), + } + + log.Debug().Msgf("%v: sending connect command", h.network.Server) + + err := h.client.Write(m.String()) + if err != nil { + log.Error().Err(err).Msgf("error handling invite: %v", m.String()) + return err + } } return nil } -func (s *Handler) handlePRIVMSG(msg string) error { +func (h *Handler) handlePRIVMSG(msg string) error { msg = strings.TrimLeft(msg, "/") m := irc.Message{ Command: "PRIVMSG", Params: []string{msg}, } - log.Debug().Msgf("%v: Handle privmsg: %v", s.network.Server, m.String()) + log.Debug().Msgf("%v: Handle privmsg: %v", h.network.Server, m.String()) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Err(err).Msgf("error handling PRIVMSG: %v", m.String()) return err @@ -537,15 +596,15 @@ func (s *Handler) handlePRIVMSG(msg string) error { return nil } -func (s *Handler) handleNickServPRIVMSG(nick, password string) error { +func (h *Handler) handleNickServPRIVMSG(nick, password string) error { m := irc.Message{ Command: "PRIVMSG", Params: []string{"NickServ", "IDENTIFY", nick, password}, } - log.Debug().Msgf("%v: NickServ: %v", s.network.Server, m.String()) + log.Debug().Msgf("%v: NickServ: %v", h.network.Server, m.String()) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Err(err).Msgf("error identifying with nickserv: %v", m.String()) return err @@ -554,15 +613,15 @@ func (s *Handler) handleNickServPRIVMSG(nick, password string) error { return nil } -func (s *Handler) HandleNickServIdentify(nick, password string) error { +func (h *Handler) HandleNickServIdentify(nick, password string) error { m := irc.Message{ Command: "PRIVMSG", Params: []string{"NickServ", "IDENTIFY", nick, password}, } - log.Debug().Msgf("%v: NickServ: %v", s.network.Server, m.String()) + log.Debug().Msgf("%v: NickServ: %v", h.network.Server, m.String()) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Stack().Err(err).Msgf("error identifying with nickserv: %v", m.String()) return err @@ -571,15 +630,15 @@ func (s *Handler) HandleNickServIdentify(nick, password string) error { return nil } -func (s *Handler) HandleNickChange(nick string) error { +func (h *Handler) HandleNickChange(nick string) error { m := irc.Message{ Command: "NICK", Params: []string{nick}, } - log.Debug().Msgf("%v: Nick change: %v", s.network.Server, m.String()) + log.Debug().Msgf("%v: Nick change: %v", h.network.Server, m.String()) - err := s.client.Write(m.String()) + err := h.client.Write(m.String()) if err != nil { log.Error().Stack().Err(err).Msgf("error changing nick: %v", m.String()) return err @@ -588,18 +647,18 @@ func (s *Handler) HandleNickChange(nick string) error { return nil } -func (s *Handler) handleMode(msg *irc.Message) error { - log.Debug().Msgf("%v: MODE: %v %v", s.network.Server, msg.User, msg.Trailing()) +func (h *Handler) handleMode(msg *irc.Message) error { + log.Debug().Msgf("%v: MODE: %v %v", h.network.Server, msg.User, msg.Trailing()) time.Sleep(2 * time.Second) - if s.network.NickServ.Password != "" && !strings.Contains(msg.String(), s.client.CurrentNick()) || !strings.Contains(msg.String(), "+r") { - log.Trace().Msgf("%v: MODE: Not correct permission yet: %v", s.network.Server, msg.String()) + if h.network.NickServ.Password != "" && !strings.Contains(msg.String(), h.client.CurrentNick()) || !strings.Contains(msg.String(), "+r") { + log.Trace().Msgf("%v: MODE: Not correct permission yet: %v", h.network.Server, msg.String()) return nil } - for _, ch := range s.network.Channels { - err := s.HandleJoinChannel(ch.Name, ch.Password) + for _, ch := range h.network.Channels { + err := h.HandleJoinChannel(ch.Name, ch.Password) if err != nil { log.Error().Err(err).Msgf("error joining channel: %v", ch.Name) continue @@ -611,30 +670,30 @@ func (s *Handler) handleMode(msg *irc.Message) error { return nil } -func (s *Handler) handlePing(msg *irc.Message) error { - log.Trace().Msgf("%v: %v", s.network.Server, msg) +func (h *Handler) handlePing(msg *irc.Message) error { + log.Trace().Msgf("%v: %v", h.network.Server, msg) pong := irc.Message{ Command: "PONG", Params: msg.Params, } - log.Trace().Msgf("%v: %v", s.network.Server, pong.String()) + log.Trace().Msgf("%v: %v", h.network.Server, pong.String()) - err := s.client.Write(pong.String()) + err := h.client.Write(pong.String()) if err != nil { log.Error().Err(err).Msgf("error PING PONG response: %v", pong.String()) return err } - s.setLastPing() + h.setLastPing() return nil } // check if announcer is one from the list in the definition -func (s *Handler) isValidAnnouncer(nick string) bool { - _, ok := s.validAnnouncers[nick] +func (h *Handler) isValidAnnouncer(nick string) bool { + _, ok := h.validAnnouncers[nick] if !ok { return false } @@ -643,8 +702,8 @@ func (s *Handler) isValidAnnouncer(nick string) bool { } // check if channel is one from the list in the definition -func (s *Handler) isValidChannel(channel string) bool { - _, ok := s.validChannels[strings.ToLower(channel)] +func (h *Handler) isValidChannel(channel string) bool { + _, ok := h.validChannels[strings.ToLower(channel)] if !ok { return false } @@ -652,12 +711,12 @@ func (s *Handler) isValidChannel(channel string) bool { return true } -func (s *Handler) setLastPing() { - s.lastPing = time.Now() +func (h *Handler) setLastPing() { + h.lastPing = time.Now() } -func (s *Handler) GetLastPing() time.Time { - return s.lastPing +func (h *Handler) GetLastPing() time.Time { + return h.lastPing } // irc line can contain lots of extra stuff like color so lets clean that diff --git a/internal/irc/service.go b/internal/irc/service.go index a37d372..20ebcfb 100644 --- a/internal/irc/service.go +++ b/internal/irc/service.go @@ -17,7 +17,7 @@ import ( type Service interface { StartHandlers() StopHandlers() - StopNetwork(name string) error + StopNetwork(key handlerKey) error ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error) GetNetworksWithHealth(ctx context.Context) ([]domain.IrcNetworkWithHealth, error) GetNetworkByID(id int64) (*domain.IrcNetwork, error) @@ -33,7 +33,7 @@ type service struct { indexerService indexer.Service releaseService release.Service indexerMap map[string]string - handlers map[string]*Handler + handlers map[handlerKey]*Handler stopWG sync.WaitGroup lock sync.Mutex @@ -45,10 +45,15 @@ func NewService(repo domain.IrcRepo, filterService filter.Service, indexerSvc in filterService: filterService, indexerService: indexerSvc, releaseService: releaseSvc, - handlers: make(map[string]*Handler), + handlers: make(map[handlerKey]*Handler), } } +type handlerKey struct { + server string + nick string +} + func (s *service) StartHandlers() { networks, err := s.repo.FindActiveNetworks(context.Background()) if err != nil { @@ -76,8 +81,9 @@ func (s *service) StartHandlers() { // init new irc handler handler := NewHandler(network, s.filterService, s.releaseService, definitions) - // TODO use network.Server? + nick? Need a way to use multiple indexers for one network if same nick - s.handlers[network.Server] = handler + // use network.Server + nick to use multiple indexers with different nick per network + // this allows for multiple handlers to one network + s.handlers[handlerKey{network.Server, network.NickServ.Account}] = handler s.lock.Unlock() log.Debug().Msgf("starting network: %+v", network.Name) @@ -105,7 +111,7 @@ func (s *service) StopHandlers() { func (s *service) startNetwork(network domain.IrcNetwork) error { // look if we have the network in handlers already, if so start it - if existingHandler, found := s.handlers[network.Server]; found { + if existingHandler, found := s.handlers[handlerKey{network.Server, network.NickServ.Account}]; found { log.Debug().Msgf("starting network: %+v", network.Name) if existingHandler.conn != nil { @@ -131,7 +137,7 @@ func (s *service) startNetwork(network domain.IrcNetwork) error { // init new irc handler handler := NewHandler(network, s.filterService, s.releaseService, definitions) - s.handlers[network.Server] = handler + s.handlers[handlerKey{network.Server, network.NickServ.Account}] = handler s.lock.Unlock() log.Debug().Msgf("starting network: %+v", network.Name) @@ -152,9 +158,8 @@ func (s *service) startNetwork(network domain.IrcNetwork) error { func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error { // look if we have the network in handlers, if so restart it - // TODO check if we need to add indexerDefinitions etc - if existingHandler, found := s.handlers[network.Server]; found { - log.Debug().Msgf("decide if irc network handler needs restart or updating: %+v", network.Name) + if existingHandler, found := s.handlers[handlerKey{network.Server, network.NickServ.Account}]; found { + log.Debug().Msgf("irc: decide if irc network handler needs restart or updating: %+v", network.Server) // if server, tls, invite command, port : changed - restart // if nickserv account, nickserv password : changed - stay connected, and change those @@ -173,18 +178,20 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error restartNeeded = true } if restartNeeded { - log.Info().Msgf("irc: restarting network: %+v", network.Name) + log.Info().Msgf("irc: restarting network: %+v", network.Server) // we need to reinitialize with new network config existingHandler.UpdateNetwork(network) + // todo reset channelHealth? + go func() { if err := existingHandler.Restart(); err != nil { log.Error().Stack().Err(err).Msgf("failed to restart network %q", existingHandler.network.Name) } }() - // return now since the restart will read the network again OR FIXME + // return now since the restart will read the network again return nil } @@ -230,6 +237,7 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error channelsToLeave = append(channelsToLeave, handlerChan.Name) } + // check new channels against handler to see which to join for _, channel := range network.Channels { _, ok := handlerChannels[channel.Name] if ok { @@ -243,6 +251,7 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error // leave channels for _, leaveChannel := range channelsToLeave { + log.Debug().Msgf("%v: part channel %v", network.Server, leaveChannel) err := existingHandler.HandlePartChannel(leaveChannel) if err != nil { log.Error().Stack().Err(err).Msgf("failed to leave channel: %q", leaveChannel) @@ -251,12 +260,21 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error // join channels for _, joinChannel := range channelsToJoin { - // TODO handle invite commands before? + log.Debug().Msgf("%v: join new channel %v", network.Server, joinChannel) err := existingHandler.HandleJoinChannel(joinChannel.Name, joinChannel.Password) if err != nil { log.Error().Stack().Err(err).Msgf("failed to join channel: %q", joinChannel.Name) } } + + // update network for handler + // TODO move all this restart logic inside handler to let it decide what to do + existingHandler.SetNetwork(network) + + // find indexer definitions for network and add + definitions := s.indexerService.GetIndexersByIRCNetwork(network.Server) + + existingHandler.InitIndexers(definitions) } } else { err := s.startNetwork(*network) @@ -270,7 +288,7 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error func (s *service) restartNetwork(network domain.IrcNetwork) error { // look if we have the network in handlers, if so restart it - if existingHandler, found := s.handlers[network.Server]; found { + if existingHandler, found := s.handlers[handlerKey{network.Server, network.NickServ.Account}]; found { log.Info().Msgf("restarting network: %+v", network.Name) if existingHandler.conn != nil { @@ -287,31 +305,31 @@ func (s *service) restartNetwork(network domain.IrcNetwork) error { return nil } -func (s *service) StopNetwork(name string) error { - if handler, found := s.handlers[name]; found { +func (s *service) StopNetwork(key handlerKey) error { + if handler, found := s.handlers[key]; found { handler.Stop() - log.Debug().Msgf("stopped network: %+v", name) + log.Debug().Msgf("stopped network: %+v", key.server) } return nil } -func (s *service) StopAndRemoveNetwork(name string) error { - if handler, found := s.handlers[name]; found { +func (s *service) StopAndRemoveNetwork(key handlerKey) error { + if handler, found := s.handlers[key]; found { handler.Stop() // remove from handlers - delete(s.handlers, name) - log.Debug().Msgf("stopped network: %+v", name) + delete(s.handlers, key) + log.Debug().Msgf("stopped network: %+v", key) } return nil } -func (s *service) StopNetworkIfRunning(name string) error { - if handler, found := s.handlers[name]; found { +func (s *service) StopNetworkIfRunning(key handlerKey) error { + if handler, found := s.handlers[key]; found { handler.Stop() - log.Debug().Msgf("stopped network: %+v", name) + log.Debug().Msgf("stopped network: %+v", key.server) } return nil @@ -351,8 +369,6 @@ func (s *service) ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error) } n.Channels = append(n.Channels, channels...) - // TODO get handler channelHealth - ret = append(ret, n) } @@ -382,7 +398,7 @@ func (s *service) GetNetworksWithHealth(ctx context.Context) ([]domain.IrcNetwor Connected: false, } - handler, ok := s.handlers[n.Server] + handler, ok := s.handlers[handlerKey{n.Server, n.NickServ.Account}] if ok { // only set connected and connected since if we have an active handler and connection if handler.conn != nil { @@ -441,7 +457,7 @@ func (s *service) DeleteNetwork(ctx context.Context, id int64) error { // Remove network and handler //if err = s.StopNetwork(network.Server); err != nil { - if err = s.StopAndRemoveNetwork(network.Server); err != nil { + if err = s.StopAndRemoveNetwork(handlerKey{network.Server, network.NickServ.Account}); err != nil { return err } @@ -478,9 +494,8 @@ func (s *service) UpdateNetwork(ctx context.Context, network *domain.IrcNetwork) } } else { - // TODO take into account multiple channels per network - //err := s.StopNetwork(network.Server) - err := s.StopAndRemoveNetwork(network.Server) + // take into account multiple channels per network + err := s.StopAndRemoveNetwork(handlerKey{network.Server, network.NickServ.Account}) if err != nil { log.Error().Stack().Err(err).Msgf("could not stop network: %+v", network.Name) return fmt.Errorf("could not stop network: %v", network.Name) @@ -514,16 +529,23 @@ func (s *service) StoreNetwork(ctx context.Context, network *domain.IrcNetwork) return nil } + // get channels for existing network + existingChannels, err := s.repo.ListChannels(existingNetwork.ID) + if err != nil { + log.Error().Err(err).Msgf("failed to list channels for network %q", existingNetwork.Server) + } + existingNetwork.Channels = existingChannels + if network.Channels != nil { for _, channel := range network.Channels { - // TODO store or add. Make sure it doesn't delete before + // add channels. Make sure it doesn't delete before if err := s.repo.StoreChannel(existingNetwork.ID, &channel); err != nil { return err } } // append channels to existing network - network.Channels = append(network.Channels, existingNetwork.Channels...) + existingNetwork.Channels = append(existingNetwork.Channels, network.Channels...) } if existingNetwork.Enabled { @@ -531,10 +553,10 @@ func (s *service) StoreNetwork(ctx context.Context, network *domain.IrcNetwork) // if nickserv account, nickserv password : changed - stay connected, and change those // if channels len : changes - join or leave - err := s.checkIfNetworkRestartNeeded(network) + err := s.checkIfNetworkRestartNeeded(existingNetwork) if err != nil { - log.Error().Err(err).Msgf("could not restart network: %+v", network.Name) - return fmt.Errorf("could not restart network: %v", network.Name) + log.Error().Err(err).Msgf("could not restart network: %+v", existingNetwork.Name) + return fmt.Errorf("could not restart network: %v", existingNetwork.Name) } } diff --git a/web/src/forms/settings/IndexerForms.tsx b/web/src/forms/settings/IndexerForms.tsx index 63fbe84..b5bceb1 100644 --- a/web/src/forms/settings/IndexerForms.tsx +++ b/web/src/forms/settings/IndexerForms.tsx @@ -68,7 +68,7 @@ export function IndexerAddForm({ isOpen, toggle }: AddProps) { } const network: Network = { - name: ind.name, + name: ind.irc.network, enabled: false, server: ind.irc.server, port: ind.irc.port,