mirror of
https://github.com/ditatompel/xmr-remote-nodes.git
synced 2024-11-16 17:07:36 +00:00
feat: Added i2p support #148
For now, only p32 address is supported. ToDo: Accept i2p naming service from addressbook subscriptions ToDo: Imporve i2p UI display and add i2p filter
This commit is contained in:
parent
15804ee438
commit
e892733a55
12 changed files with 96 additions and 21 deletions
|
@ -8,6 +8,8 @@ SERVER_ENDPOINT="http://127.0.0.1:18901"
|
|||
API_KEY=
|
||||
ACCEPT_TOR=false
|
||||
TOR_SOCKS="127.0.0.1:9050"
|
||||
ACCEPT_I2P=false
|
||||
I2P_SOCKS="127.0.0.1:4447"
|
||||
IPV6_CAPABLE=false
|
||||
|
||||
# Server Config
|
||||
|
|
1
.github/workflows/test.yml
vendored
1
.github/workflows/test.yml
vendored
|
@ -3,6 +3,7 @@ on:
|
|||
branches:
|
||||
- main
|
||||
- htmx
|
||||
- i2p-support
|
||||
|
||||
pull_request:
|
||||
name: Test
|
||||
|
|
|
@ -84,6 +84,7 @@ See the [Makefile](./Makefile).
|
|||
- :white_check_mark: Accept IPv6 nodes.
|
||||
- :white_check_mark: Use `a-h/templ` and `HTMX` instead of `Svelte`.
|
||||
- Use Go standard `net/http` instead of `fiber`.
|
||||
- Accept I2P nodes.
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
|
|
|
@ -21,11 +21,12 @@ import (
|
|||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
const RPCUserAgent = "ditatombot/0.0.1 (Monero RPC Monitoring; https://github.com/ditatompel/xmr-remote-nodes)"
|
||||
const RPCUserAgent = "ditatombot/0.0.2 (Monero RPC Monitoring; https://github.com/ditatompel/xmr-remote-nodes)"
|
||||
|
||||
const (
|
||||
errNoEndpoint = errProber("no SERVER_ENDPOINT was provided")
|
||||
errNoTorSocks = errProber("no TOR_SOCKS was provided")
|
||||
errNoI2PSocks = errProber("no I2P_SOCKS was provided")
|
||||
errNoAPIKey = errProber("no API_KEY was provided")
|
||||
errInvalidCredentials = errProber("invalid API_KEY credentials")
|
||||
)
|
||||
|
@ -41,6 +42,8 @@ type proberClient struct {
|
|||
apiKey string // prober api key
|
||||
acceptTor bool // accept tor
|
||||
torSOCKS string // IP:Port of tor socks
|
||||
acceptI2P bool // accept i2p
|
||||
I2PSOCKS string // IP:Port of i2p socks
|
||||
acceptIPv6 bool // accept ipv6
|
||||
message string // message to include when reporting back to server
|
||||
}
|
||||
|
@ -52,6 +55,8 @@ func newProber() *proberClient {
|
|||
apiKey: cfg.APIKey,
|
||||
acceptTor: cfg.AcceptTor,
|
||||
torSOCKS: cfg.TorSOCKS,
|
||||
acceptI2P: cfg.AcceptI2P,
|
||||
I2PSOCKS: cfg.I2PSOCKS,
|
||||
acceptIPv6: cfg.IPv6Capable,
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +72,9 @@ var ProbeCmd = &cobra.Command{
|
|||
if t, _ := cmd.Flags().GetBool("no-tor"); t {
|
||||
prober.SetAcceptTor(false)
|
||||
}
|
||||
if t, _ := cmd.Flags().GetBool("no-i2p"); t {
|
||||
prober.SetAcceptI2P(false)
|
||||
}
|
||||
|
||||
if err := prober.Run(); err != nil {
|
||||
switch err.(type) {
|
||||
|
@ -88,6 +96,10 @@ func (p *proberClient) SetAcceptTor(acceptTor bool) {
|
|||
p.acceptTor = acceptTor
|
||||
}
|
||||
|
||||
func (p *proberClient) SetAcceptI2P(acceptI2P bool) {
|
||||
p.acceptI2P = acceptI2P
|
||||
}
|
||||
|
||||
func (p *proberClient) SetAcceptIPv6(acceptIPv6 bool) {
|
||||
p.acceptIPv6 = acceptIPv6
|
||||
}
|
||||
|
@ -122,6 +134,9 @@ func (p *proberClient) validateConfig() error {
|
|||
if p.acceptTor && p.torSOCKS == "" {
|
||||
return errNoTorSocks
|
||||
}
|
||||
if p.acceptI2P && p.I2PSOCKS == "" {
|
||||
return errNoI2PSocks
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -133,6 +148,11 @@ func (p *proberClient) fetchJob() (monero.Node, error) {
|
|||
acceptTor = 1
|
||||
}
|
||||
|
||||
acceptI2P := 0
|
||||
if p.acceptI2P {
|
||||
acceptI2P = 1
|
||||
}
|
||||
|
||||
acceptIPv6 := 0
|
||||
if p.acceptIPv6 {
|
||||
acceptIPv6 = 1
|
||||
|
@ -140,7 +160,7 @@ func (p *proberClient) fetchJob() (monero.Node, error) {
|
|||
|
||||
var node monero.Node
|
||||
|
||||
uri := fmt.Sprintf("%s/api/v1/job?accept_tor=%d&accept_ipv6=%d", p.endpoint, acceptTor, acceptIPv6)
|
||||
uri := fmt.Sprintf("%s/api/v1/job?accept_tor=%d&accept_i2p=%d&accept_ipv6=%d", p.endpoint, acceptTor, acceptI2P, acceptIPv6)
|
||||
slog.Info(fmt.Sprintf("[PROBE] Getting node from %s", uri))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, uri, nil)
|
||||
|
@ -198,8 +218,16 @@ func (p *proberClient) fetchNode(node monero.Node) (monero.Node, error) {
|
|||
req.Header.Set("Origin", "https://xmr.ditatompel.com")
|
||||
|
||||
var client http.Client
|
||||
var socks5 string
|
||||
|
||||
if p.acceptTor && node.IsTor {
|
||||
dialer, err := proxy.SOCKS5("tcp", p.torSOCKS, nil, proxy.Direct)
|
||||
socks5 = p.torSOCKS
|
||||
} else if p.acceptI2P && node.IsI2P {
|
||||
socks5 = p.I2PSOCKS
|
||||
}
|
||||
|
||||
if socks5 != "" {
|
||||
dialer, err := proxy.SOCKS5("tcp", socks5, nil, proxy.Direct)
|
||||
if err != nil {
|
||||
return node, err
|
||||
}
|
||||
|
@ -268,7 +296,7 @@ func (p *proberClient) fetchNode(node monero.Node) (monero.Node, error) {
|
|||
node.CORSCapable = true
|
||||
}
|
||||
|
||||
if !node.IsTor {
|
||||
if !node.IsTor && !node.IsI2P {
|
||||
hostIp, err := net.LookupIP(node.Hostname)
|
||||
if err != nil {
|
||||
fmt.Println("Warning: Could not resolve hostname: " + node.Hostname)
|
||||
|
@ -335,7 +363,7 @@ func (p *proberClient) fetchFee(client http.Client, endpoint string) (uint, erro
|
|||
}
|
||||
|
||||
func (p *proberClient) reportResult(node monero.Node, tookTime float64) error {
|
||||
if !node.IsTor {
|
||||
if !node.IsTor && !node.IsI2P {
|
||||
if hostIps, err := net.LookupIP(node.Hostname); err == nil {
|
||||
node.IPv6Only = ip.IsIPv6Only(hostIps)
|
||||
node.IPAddresses = ip.SliceToString(hostIps)
|
||||
|
|
|
@ -29,7 +29,8 @@ func init() {
|
|||
Root.PersistentFlags().StringVarP(&configFile, "config-file", "c", "", "Default to .env")
|
||||
Root.AddCommand(client.ProbeCmd)
|
||||
client.ProbeCmd.Flags().StringP("endpoint", "e", "", "Server endpoint")
|
||||
client.ProbeCmd.Flags().Bool("no-tor", false, "Only probe clearnet nodes")
|
||||
client.ProbeCmd.Flags().Bool("no-tor", false, "Do not probe tor nodes")
|
||||
client.ProbeCmd.Flags().Bool("no-i2p", false, "Do not probe i2p nodes")
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
|
|
|
@ -27,6 +27,8 @@ type App struct {
|
|||
APIKey string
|
||||
AcceptTor bool
|
||||
TorSOCKS string
|
||||
AcceptI2P bool
|
||||
I2PSOCKS string
|
||||
IPv6Capable bool
|
||||
}
|
||||
|
||||
|
@ -72,5 +74,7 @@ func LoadApp() {
|
|||
app.APIKey = os.Getenv("API_KEY")
|
||||
app.AcceptTor, _ = strconv.ParseBool(os.Getenv("ACCEPT_TOR"))
|
||||
app.TorSOCKS = os.Getenv("TOR_SOCKS")
|
||||
app.AcceptI2P, _ = strconv.ParseBool(os.Getenv("ACCEPT_I2P"))
|
||||
app.I2PSOCKS = os.Getenv("I2P_SOCKS")
|
||||
app.IPv6Capable, _ = strconv.ParseBool(os.Getenv("IPV6_CAPABLE"))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
type migrateFn func(*DB) error
|
||||
|
||||
var dbMigrate = [...]migrateFn{v1, v2, v3}
|
||||
var dbMigrate = [...]migrateFn{v1, v2, v3, v4}
|
||||
|
||||
func MigrateDb(db *DB) error {
|
||||
version := getSchemaVersion(db)
|
||||
|
@ -272,3 +272,18 @@ func v3(db *DB) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func v4(db *DB) error {
|
||||
slog.Debug("[DB] Migrating database schema version 4")
|
||||
|
||||
// table: tbl_node
|
||||
slog.Debug("[DB] Adding additional columns to tbl_node")
|
||||
_, err := db.Exec(`
|
||||
ALTER TABLE tbl_node
|
||||
ADD COLUMN is_i2p TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER is_tor;`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -402,10 +402,11 @@ func (s *fiberServer) countriesAPI(c *fiber.Ctx) error {
|
|||
// This handler should protected by `s.checkProberMW` middleware.
|
||||
func (s *fiberServer) giveJobAPI(c *fiber.Ctx) error {
|
||||
acceptTor := c.QueryInt("accept_tor", 0)
|
||||
acceptI2P := c.QueryInt("accept_i2p", 0)
|
||||
acceptIPv6 := c.QueryInt("accept_ipv6", 0)
|
||||
|
||||
moneroRepo := monero.New()
|
||||
node, err := moneroRepo.GiveJob(acceptTor, acceptIPv6)
|
||||
node, err := moneroRepo.GiveJob(acceptTor, acceptI2P, acceptIPv6)
|
||||
if err != nil {
|
||||
return c.JSON(fiber.Map{
|
||||
"status": "error",
|
||||
|
|
|
@ -7,11 +7,9 @@ templ AddNode() {
|
|||
<div class="relative z-10">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-10 lg:py-16">
|
||||
<div class="text-center">
|
||||
<!-- Title -->
|
||||
<div class="mt-5">
|
||||
<h1 class="block font-extrabold text-4xl md:text-5xl lg:text-6xl text-neutral-200">Add Monero Node</h1>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
<div class="mt-5">
|
||||
<p class="text-lg text-neutral-300">You can use this page to add known remote node to the system so my bots can monitor it.</p>
|
||||
</div>
|
||||
|
@ -25,6 +23,7 @@ templ AddNode() {
|
|||
<div class="mt-2 text-sm">
|
||||
<ul class="list-disc space-y-1 ps-5">
|
||||
<li>As an administrator of this instance, I have full rights to delete, and blacklist any submitted node with or without providing any reason.</li>
|
||||
<li>I2P nodes monitoring is beta and currently only support b32 address.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,9 +31,7 @@ templ AddNode() {
|
|||
</div>
|
||||
</div>
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||
<p class="mt-1 text-center">
|
||||
Enter your Monero node information below (IPv6 host check is experimental):
|
||||
</p>
|
||||
<p class="mt-1 text-center">Enter your Monero node information below:</p>
|
||||
<div class="mt-12">
|
||||
<form method="put" hx-swap="transition:true" hx-target="#form-result" hx-disabled-elt=".form" hx-on::after-request="this.reset()">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-4 gap-6">
|
||||
|
|
|
@ -37,7 +37,7 @@ func AddNode() templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative z-10\"><div class=\"max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-10 lg:py-16\"><div class=\"text-center\"><!-- Title --><div class=\"mt-5\"><h1 class=\"block font-extrabold text-4xl md:text-5xl lg:text-6xl text-neutral-200\">Add Monero Node</h1></div><!-- End Title --><div class=\"mt-5\"><p class=\"text-lg text-neutral-300\">You can use this page to add known remote node to the system so my bots can monitor it.</p></div></div><hr class=\"my-6 border-orange-400 mx-auto max-w-3xl\"><div class=\"max-w-4xl mx-auto px-4\"><div class=\"p-4 bg-blue-800/10 border border-blue-900 text-sm text-white rounded-lg\" role=\"alert\" tabindex=\"-1\" aria-labelledby=\"add-node-notice\"><div class=\"flex\"><div class=\"ms-4\"><h2 id=\"add-node-notice\" class=\"text-xl font-bold text-center\">Important Note</h2><div class=\"mt-2 text-sm\"><ul class=\"list-disc space-y-1 ps-5\"><li>As an administrator of this instance, I have full rights to delete, and blacklist any submitted node with or without providing any reason.</li></ul></div></div></div></div></div><div class=\"max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-6\"><p class=\"mt-1 text-center\">Enter your Monero node information below (IPv6 host check is experimental):</p><div class=\"mt-12\"><form method=\"put\" hx-swap=\"transition:true\" hx-target=\"#form-result\" hx-disabled-elt=\".form\" hx-on::after-request=\"this.reset()\"><div class=\"grid grid-cols-1 sm:grid-cols-4 gap-6\"><div><label for=\"protocol\" class=\"block text-neutral-200\">Protocol *</label> <select id=\"protocol\" name=\"protocol\" class=\"frameless form\" autocomplete=\"off\"><option value=\"http\">HTTP</option> <option value=\"https\">HTTPS</option></select></div><div class=\"md:col-span-2\"><label for=\"hostname\" class=\"block text-neutral-200\">Host / IP *</label> <input type=\"text\" name=\"hostname\" id=\"hostname\" class=\"frameless form\" autocomplete=\"off\" placeholder=\"Eg: node.example.com or 172.16.17.18\" required></div><div><label for=\"port\" class=\"block text-neutral-200\">Port *</label> <input type=\"text\" name=\"port\" id=\"port\" class=\"frameless form\" autocomplete=\"off\" placeholder=\"Eg: 18081\" required></div></div><div class=\"mt-6 grid\"><button type=\"submit\" class=\"form w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-bold rounded-lg border border-transparent bg-orange-600 text-white hover:bg-orange-500 focus:outline-none disabled:opacity-60 disabled:pointer-events-none\">Submit</button></div></form><div id=\"form-result\" class=\"max-w-4xl mx-auto my-6\"></div><div class=\"mt-3 text-center\"><p class=\"text-sm text-gray-500 dark:text-neutral-500\">Existing remote nodes can be found in <a href=\"/remote-nodes\" class=\"link\">/remote-nodes</a> page.</p></div></div></div></div></div></section><!-- End Hero -->")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative z-10\"><div class=\"max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-10 lg:py-16\"><div class=\"text-center\"><div class=\"mt-5\"><h1 class=\"block font-extrabold text-4xl md:text-5xl lg:text-6xl text-neutral-200\">Add Monero Node</h1></div><div class=\"mt-5\"><p class=\"text-lg text-neutral-300\">You can use this page to add known remote node to the system so my bots can monitor it.</p></div></div><hr class=\"my-6 border-orange-400 mx-auto max-w-3xl\"><div class=\"max-w-4xl mx-auto px-4\"><div class=\"p-4 bg-blue-800/10 border border-blue-900 text-sm text-white rounded-lg\" role=\"alert\" tabindex=\"-1\" aria-labelledby=\"add-node-notice\"><div class=\"flex\"><div class=\"ms-4\"><h2 id=\"add-node-notice\" class=\"text-xl font-bold text-center\">Important Note</h2><div class=\"mt-2 text-sm\"><ul class=\"list-disc space-y-1 ps-5\"><li>As an administrator of this instance, I have full rights to delete, and blacklist any submitted node with or without providing any reason.</li><li>I2P nodes monitoring is beta and currently only support b32 address.</li></ul></div></div></div></div></div><div class=\"max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-6\"><p class=\"mt-1 text-center\">Enter your Monero node information below:</p><div class=\"mt-12\"><form method=\"put\" hx-swap=\"transition:true\" hx-target=\"#form-result\" hx-disabled-elt=\".form\" hx-on::after-request=\"this.reset()\"><div class=\"grid grid-cols-1 sm:grid-cols-4 gap-6\"><div><label for=\"protocol\" class=\"block text-neutral-200\">Protocol *</label> <select id=\"protocol\" name=\"protocol\" class=\"frameless form\" autocomplete=\"off\"><option value=\"http\">HTTP</option> <option value=\"https\">HTTPS</option></select></div><div class=\"md:col-span-2\"><label for=\"hostname\" class=\"block text-neutral-200\">Host / IP *</label> <input type=\"text\" name=\"hostname\" id=\"hostname\" class=\"frameless form\" autocomplete=\"off\" placeholder=\"Eg: node.example.com or 172.16.17.18\" required></div><div><label for=\"port\" class=\"block text-neutral-200\">Port *</label> <input type=\"text\" name=\"port\" id=\"port\" class=\"frameless form\" autocomplete=\"off\" placeholder=\"Eg: 18081\" required></div></div><div class=\"mt-6 grid\"><button type=\"submit\" class=\"form w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-bold rounded-lg border border-transparent bg-orange-600 text-white hover:bg-orange-500 focus:outline-none disabled:opacity-60 disabled:pointer-events-none\">Submit</button></div></form><div id=\"form-result\" class=\"max-w-4xl mx-auto my-6\"></div><div class=\"mt-3 text-center\"><p class=\"text-sm text-gray-500 dark:text-neutral-500\">Existing remote nodes can be found in <a href=\"/remote-nodes\" class=\"link\">/remote-nodes</a> page.</p></div></div></div></div></div></section><!-- End Hero -->")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ type Node struct {
|
|||
Port uint `json:"port" db:"port"`
|
||||
Protocol string `json:"protocol" db:"protocol"`
|
||||
IsTor bool `json:"is_tor" db:"is_tor"`
|
||||
IsI2P bool `json:"is_i2p" db:"is_i2p"`
|
||||
IsAvailable bool `json:"is_available" db:"is_available"`
|
||||
Nettype string `json:"nettype" db:"nettype"`
|
||||
Height uint `json:"height" db:"height"`
|
||||
|
@ -196,14 +197,25 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
|||
|
||||
is_tor := false
|
||||
if strings.HasSuffix(hostname, ".onion") {
|
||||
if !validTorHostname(hostname) {
|
||||
return errors.New("Invalid TOR v3 .onion hostname")
|
||||
}
|
||||
is_tor = true
|
||||
}
|
||||
|
||||
is_i2p := false
|
||||
if strings.HasSuffix(hostname, ".i2p") {
|
||||
if !validI2PHostname(hostname) {
|
||||
return errors.New("Invalid I2P hostname")
|
||||
}
|
||||
is_i2p = true
|
||||
}
|
||||
|
||||
ipAddr := ""
|
||||
ips := ""
|
||||
ipv6_only := false
|
||||
|
||||
if !is_tor {
|
||||
if !is_tor && !is_i2p {
|
||||
hostIps, err := net.LookupIP(hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -221,10 +233,6 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
|||
|
||||
ipAddr = hostIp.String()
|
||||
ips = ip.SliceToString(hostIps)
|
||||
} else {
|
||||
if !validTorHostname(hostname) {
|
||||
return errors.New("Invalid TOR v3 .onion hostname")
|
||||
}
|
||||
}
|
||||
|
||||
row, err := r.db.Query(`
|
||||
|
@ -252,6 +260,7 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
|||
hostname,
|
||||
port,
|
||||
is_tor,
|
||||
is_i2p,
|
||||
nettype,
|
||||
ip_addr,
|
||||
lat,
|
||||
|
@ -274,12 +283,14 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
|||
?,
|
||||
?,
|
||||
?,
|
||||
?,
|
||||
?
|
||||
)`,
|
||||
protocol,
|
||||
hostname,
|
||||
port,
|
||||
is_tor,
|
||||
is_i2p,
|
||||
"",
|
||||
ipAddr,
|
||||
0,
|
||||
|
@ -304,6 +315,14 @@ func validTorHostname(hostname string) bool {
|
|||
return regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z2-7]{56}\.onion$`).MatchString(hostname)
|
||||
}
|
||||
|
||||
// validI2PHostname checks if a given hostname is a valid p32 I2P address
|
||||
//
|
||||
// Old b32 addresses are always {52 chars}.b32.i2p and new ones are {56+ chars}.b32.i2p.
|
||||
// See: https://geti2p.net/spec/b32encrypted
|
||||
func validI2PHostname(hostname string) bool {
|
||||
return regexp.MustCompile(`^[a-z2-7]{52,}\.b32\.i2p$`).MatchString(hostname)
|
||||
}
|
||||
|
||||
func (r *moneroRepo) Delete(id uint) error {
|
||||
if _, err := r.db.Exec(`DELETE FROM tbl_node WHERE id = ?`, id); err != nil {
|
||||
return err
|
||||
|
|
|
@ -109,7 +109,7 @@ func (r *moneroRepo) Logs(q QueryLogs) (FetchLogs, error) {
|
|||
}
|
||||
|
||||
// GiveJob returns node that should be probed for the next time
|
||||
func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
|
||||
func (r *moneroRepo) GiveJob(acceptTor, acceptI2P, acceptIPv6 int) (Node, error) {
|
||||
args := []interface{}{}
|
||||
wq := []string{}
|
||||
where := ""
|
||||
|
@ -118,6 +118,10 @@ func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
|
|||
wq = append(wq, "is_tor = ?")
|
||||
args = append(args, 0)
|
||||
}
|
||||
if acceptI2P != 1 {
|
||||
wq = append(wq, "is_i2p = ?")
|
||||
args = append(args, 0)
|
||||
}
|
||||
if acceptIPv6 != 1 {
|
||||
wq = append(wq, "ipv6_only = ?")
|
||||
args = append(args, 0)
|
||||
|
@ -136,10 +140,11 @@ func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
|
|||
port,
|
||||
protocol,
|
||||
is_tor,
|
||||
is_i2p,
|
||||
last_check_status
|
||||
FROM
|
||||
tbl_node
|
||||
%s -- where query if any
|
||||
%s
|
||||
ORDER BY
|
||||
last_checked ASC
|
||||
LIMIT 1`, where)
|
||||
|
@ -149,6 +154,7 @@ func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
|
|||
&node.Port,
|
||||
&node.Protocol,
|
||||
&node.IsTor,
|
||||
&node.IsI2P,
|
||||
&node.LastCheckStatus)
|
||||
if err != nil {
|
||||
return node, err
|
||||
|
|
Loading…
Reference in a new issue