Compare commits

..

No commits in common. "b60a67c8cbe77e3ccaa48bc37fa5fe9cf887dd4b" and "187a7bc84a75cb587c5946cb117a0b97d67a5b3a" have entirely different histories.

19 changed files with 58 additions and 277 deletions

View file

@ -8,7 +8,6 @@ SERVER_ENDPOINT="http://127.0.0.1:18901"
API_KEY= API_KEY=
ACCEPT_TOR=false ACCEPT_TOR=false
TOR_SOCKS="127.0.0.1:9050" TOR_SOCKS="127.0.0.1:9050"
IPV6_CAPABLE=false
# Server Config # Server Config
# ############# # #############

View file

@ -38,14 +38,14 @@ To build the executable binaries, you need:
- MySQL/MariaDB - MySQL/MariaDB
- [GeoIP Database][geoip_doc] (optional). Place it to `./assets/geoip`, - [GeoIP Database][geoip_doc] (optional). Place it to `./assets/geoip`,
see [./internal/ip/geo/geoip.go](./internal/ip/geo/geoip.go). see [./internal/geo/ip.go](./internal/geo/ip.go).
## Installation ## Installation
### For initial server setup: ### For initial server setup:
1. Download [GeoIP Database][geoip_doc] and place it to `./assets/geoip`. 1. Download [GeoIP Database][geoip_doc] and place it to `./assets/geoip`.
(see [./internal/ip/geo/geoip.go](./internal/ip/geo/geoip.go)). (see [./internal/geo/ip.go](./internal/geo/ip.go)).
2. Pepare your MySQL/MariaDB. 2. Pepare your MySQL/MariaDB.
3. Copy `.env.example` to `.env` and edit it to match with server environment. 3. Copy `.env.example` to `.env` and edit it to match with server environment.
4. Build the binary with `make server` (or `make build` to build both 4. Build the binary with `make server` (or `make build` to build both

View file

@ -14,7 +14,6 @@ import (
"time" "time"
"github.com/ditatompel/xmr-remote-nodes/internal/config" "github.com/ditatompel/xmr-remote-nodes/internal/config"
"github.com/ditatompel/xmr-remote-nodes/internal/ip"
"github.com/ditatompel/xmr-remote-nodes/internal/monero" "github.com/ditatompel/xmr-remote-nodes/internal/monero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -37,22 +36,20 @@ func (err errProber) Error() string {
} }
type proberClient struct { type proberClient struct {
endpoint string // server endpoint endpoint string // server endpoint
apiKey string // prober api key apiKey string // prober api key
acceptTor bool // accept tor acceptTor bool // accept tor
torSOCKS string // IP:Port of tor socks torSOCKS string // IP:Port of tor socks
acceptIPv6 bool // accept ipv6 message string // message to include when reporting back to server
message string // message to include when reporting back to server
} }
func newProber() *proberClient { func newProber() *proberClient {
cfg := config.AppCfg() cfg := config.AppCfg()
return &proberClient{ return &proberClient{
endpoint: cfg.ServerEndpoint, endpoint: cfg.ServerEndpoint,
apiKey: cfg.APIKey, apiKey: cfg.APIKey,
acceptTor: cfg.AcceptTor, acceptTor: cfg.AcceptTor,
torSOCKS: cfg.TorSOCKS, torSOCKS: cfg.TorSOCKS,
acceptIPv6: cfg.IPv6Capable,
} }
} }
@ -88,10 +85,6 @@ func (p *proberClient) SetAcceptTor(acceptTor bool) {
p.acceptTor = acceptTor p.acceptTor = acceptTor
} }
func (p *proberClient) SetAcceptIPv6(acceptIPv6 bool) {
p.acceptIPv6 = acceptIPv6
}
// Fetch a new job from the server, fetches node info, and sends it to the server // Fetch a new job from the server, fetches node info, and sends it to the server
func (p *proberClient) Run() error { func (p *proberClient) Run() error {
if err := p.validateConfig(); err != nil { if err := p.validateConfig(); err != nil {
@ -128,26 +121,20 @@ func (p *proberClient) validateConfig() error {
// Get monero node info to fetch from the server // Get monero node info to fetch from the server
func (p *proberClient) fetchJob() (monero.Node, error) { func (p *proberClient) fetchJob() (monero.Node, error) {
acceptTor := 0 queryParams := ""
if p.acceptTor { if p.acceptTor {
acceptTor = 1 queryParams = "?accept_tor=1"
}
acceptIPv6 := 0
if p.acceptIPv6 {
acceptIPv6 = 1
} }
var node monero.Node 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%s", p.endpoint, queryParams)
slog.Info(fmt.Sprintf("[PROBE] Getting node from %s", uri)) slog.Info(fmt.Sprintf("[PROBE] Getting node from %s", uri))
req, err := http.NewRequest(http.MethodGet, uri, nil) req, err := http.NewRequest(http.MethodGet, uri, nil)
if err != nil { if err != nil {
return node, err return node, err
} }
req.Header.Add(monero.ProberAPIKey, p.apiKey) req.Header.Add(monero.ProberAPIKey, p.apiKey)
req.Header.Set("User-Agent", RPCUserAgent) req.Header.Set("User-Agent", RPCUserAgent)
@ -335,13 +322,6 @@ func (p *proberClient) fetchFee(client http.Client, endpoint string) (uint, erro
} }
func (p *proberClient) reportResult(node monero.Node, tookTime float64) error { func (p *proberClient) reportResult(node monero.Node, tookTime float64) error {
if !node.IsTor {
if hostIps, err := net.LookupIP(node.Hostname); err == nil {
node.IPv6Only = ip.IsIPv6Only(hostIps)
node.IPAddresses = ip.SliceToString(hostIps)
}
}
jsonData, err := json.Marshal(monero.ProbeReport{ jsonData, err := json.Marshal(monero.ProbeReport{
TookTime: tookTime, TookTime: tookTime,
Message: p.message, Message: p.message,

View file

@ -21,7 +21,6 @@ declare global {
is_tor: boolean; is_tor: boolean;
is_available: boolean; is_available: boolean;
nettype: string; nettype: string;
ip_addresses: string;
} }
interface ApiResponse { interface ApiResponse {

View file

@ -1,23 +1,19 @@
<script> <script>
import { getModalStore } from '@skeletonlabs/skeleton'; import { getModalStore } from '@skeletonlabs/skeleton';
import { formatHostname } from '$lib/utils/strings';
const modalStore = getModalStore(); const modalStore = getModalStore();
/**
* @type {{
* is_tor: boolean,
* hostname: string,
* port: number,
* ipv6_only: boolean
* }}
*/
export let is_tor;
export let hostname;
export let port;
export let ipv6_only;
/** @type {string} */ /** @type {string} */
export let ip_addresses; export let ip;
/** @type {boolean} */
export let is_tor;
/** @type {string} */
export let hostname;
/** @type {number} */
export let port;
// if (is_tor) {
// hostname = hostname.substring(0, 8) + '[...].onion';
// }
/** /**
* @param {string} onionAddr * @param {string} onionAddr
@ -37,20 +33,15 @@
{#if is_tor} {#if is_tor}
<button <button
class="max-w-40 truncate text-orange-800 dark:text-orange-300" class="max-w-32 truncate text-orange-800 dark:text-orange-300"
on:click={() => modalAlert(hostname, port)} on:click={() => modalAlert(hostname, port)}
> >
👁 {hostname} 👁 {hostname}
</button><br />.onion:<span class="text-indigo-800 dark:text-indigo-400">{port}</span> </button><br />.onion:<span class="text-indigo-800 dark:text-indigo-400">{port}</span>
<span class="text-gray-700 dark:text-gray-400">(TOR)</span> <span class="text-gray-700 dark:text-gray-400">(TOR)</span>
{:else} {:else}
{formatHostname(hostname)}:<span class="text-indigo-800 dark:text-indigo-400">{port}</span><br /> {hostname}:<span class="text-indigo-800 dark:text-indigo-400">{port}</span>
<div class="max-w-40 text-ellipsis overflow-x-auto md:overflow-hidden hover:overflow-visible"> {#if ip !== ''}
<span class="whitespace-break-spaces text-gray-700 dark:text-gray-400" <br /><span class="text-gray-700 dark:text-gray-400">{ip}</span>
>{ip_addresses.replace(/,/g, ' ')}</span {/if}
>
{#if ipv6_only}
<span class="text-rose-800 dark:text-rose-400">(IPv6 only)</span>
{/if}
</div>
{/if} {/if}

View file

@ -1,26 +1,3 @@
/**
* Modifies the input string based on whether it is an IPv6 address.
* If the input is an IPv6 address, it wraps it in square brackets `[ ]`.
* Otherwise, it returns the input string as-is (for domain names or
* IPv4 addresses). AND I'M SORRY USING REGEX FOR THIS!
*
* @param {string} hostname
* @returns {string} - The modified string, IPv6 addresses wrapped in `[ ]`.
*/
export const formatHostname = (hostname) => {
// const ipv6Pattern = /^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/; // full
// pattern for both full and compressed IPv6 addresses.
// source: https://regex101.com/library/cP9mH9?filterFlavors=dotnet&filterFlavors=javascript&orderBy=RELEVANCE&search=ip
// This may be incorrect, but let's assume it's correct. xD
const ipv6Pattern =
/^(([0-9A-Fa-f]{1,4}:){7})([0-9A-Fa-f]{1,4})$|(([0-9A-Fa-f]{1,4}:){1,6}:)(([0-9A-Fa-f]{1,4}:){0,4})([0-9A-Fa-f]{1,4})$/;
if (ipv6Pattern.test(hostname)) {
return `[${hostname}]`;
}
return hostname;
};
/** /**
* @param {number} bytes * @param {number} bytes
* @param {number} decimals * @param {number} decimals

View file

@ -4,7 +4,7 @@ export async function load() {
meta: { meta: {
title: 'Monero Remote Node', title: 'Monero Remote Node',
description: description:
'A website that helps you monitor your favourite Monero remote nodes, but YOU BETTER RUN AND USE YOUR OWN NODE.', 'A website that helps you monitor your favourite Monero remote nodes, a device on the internet running the Monero software with copy of the Monero blockchain.',
keywords: keywords:
'monero,monero,xmr,monero node,xmrnode,cryptocurrency,monero remote node,monero testnet,monero stagenet' 'monero,monero,xmr,monero node,xmrnode,cryptocurrency,monero remote node,monero testnet,monero stagenet'
}, },

View file

@ -42,7 +42,7 @@
<section id="form-add-monero-node"> <section id="form-add-monero-node">
<div class="section-container text-center"> <div class="section-container text-center">
<p>Enter your Monero node information below (IPv6 host check is experimental):</p> <p>Enter your Monero node information below (IPv4 host only):</p>
<form <form
class="mx-auto w-full max-w-3xl py-2" class="mx-auto w-full max-w-3xl py-2"

View file

@ -4,7 +4,7 @@ export async function load() {
// prettier-ignore // prettier-ignore
meta: { meta: {
title: 'Public Monero Remote Nodes List', title: 'Public Monero Remote Nodes List',
description: "Although it's possible to use these existing public Monero nodes, you're MUST RUN AND USE YOUR OWN NODE!", description: 'List of public Monero remote nodes that you can use with your favourite Monero wallet. You can filter by country, protocol, or CORS capable nodes.',
keywords: 'monero remote nodes,public monero nodes,monero public nodes,monero wallet,tor monero node,monero cors rpc' keywords: 'monero remote nodes,public monero nodes,monero public nodes,monero wallet,tor monero node,monero cors rpc'
} }
}; };

View file

@ -79,7 +79,7 @@
<section id="introduction "> <section id="introduction ">
<div class="section-container text-center !max-w-4xl"> <div class="section-container text-center !max-w-4xl">
<p>Remote node can be used by people who, for their own reasons (usually because of hardware requirements, disk space, or technical abilities), cannot/don't want to run their own node and prefer to relay on one publicly available on the Monero network.</p> <p>Remote node can be used by people who, for their own reasons (usually because of hardware requirements, disk space, or technical abilities), cannot/don't want to run their own node and prefer to relay on one publicly available on the Monero network.</p>
<p>Using an open node will allow to make a transaction instantaneously, without the need to download the blockchain and sync to the Monero network first, but at the cost of the control over your privacy. the <strong>Monero community suggests to <span class="font-extrabold text-2xl underline decoration-double decoration-2 decoration-pink-500">always run and use your own node</span></strong> to obtain the maximum possible privacy and to help decentralize the network.</p> <p>Using an open node will allow to make a transaction instantaneously, without the need to download the blockchain and sync to the Monero network first, but at the cost of the control over your privacy. the <strong>Monero community suggests to always run your own node</strong> to obtain the maximum possible privacy and to help decentralize the network.</p>
</div> </div>
</section> </section>
@ -211,12 +211,12 @@
<tr> <tr>
<td <td
><HostPortCell ><HostPortCell
ip_addresses={row.ip_addresses} ip={row.ip}
is_tor={row.is_tor} is_tor={row.is_tor}
hostname={row.hostname} hostname={row.hostname}
port={row.port} port={row.port}
ipv6_only={row.ipv6_only}
/> />
<a class="anchor" href="/remote-nodes/logs/?node_id={row.id}">[Logs]</a>
</td> </td>
<td><NetTypeCell nettype={row.nettype} height={row.height} /></td> <td><NetTypeCell nettype={row.nettype} height={row.height} /></td>
<td><ProtocolCell protocol={row.protocol} cors={row.cors} /></td> <td><ProtocolCell protocol={row.protocol} cors={row.cors} /></td>
@ -241,13 +241,7 @@
majority_fee={majorityFee[row.nettype]} majority_fee={majorityFee[row.nettype]}
/> />
</td> </td>
<td <td><UptimeCell uptime={row.uptime} /></td>
><UptimeCell uptime={row.uptime} /><br />
<a
class="anchor !text-purple-800 dark:!text-purple-400"
href="/remote-nodes/logs/?node_id={row.id}">[Logs]</a
>
</td>
<td> <td>
{format(row.last_checked * 1000, 'PP HH:mm')}<br /> {format(row.last_checked * 1000, 'PP HH:mm')}<br />
{formatDistance(row.last_checked * 1000, new Date(), { addSuffix: true })} {formatDistance(row.last_checked * 1000, new Date(), { addSuffix: true })}
@ -284,12 +278,7 @@
rel="noopener">still can return high fee only if you about to create a transactions</a rel="noopener">still can return high fee only if you about to create a transactions</a
>. >.
</li> </li>
<li> <li><strong>The best and safest way is running your own node</strong>!</li>
<strong
class="font-extrabold text-2xl underline decoration-double decoration-2 decoration-pink-500"
>The best and safest way is running your own node!</strong
>
</li>
<li> <li>
Nodes with 0% uptime within 1 month with more than 300 check attempt will be removed. You Nodes with 0% uptime within 1 month with more than 300 check attempt will be removed. You
can always add your node again latter. can always add your node again latter.

View file

@ -3,7 +3,7 @@
import { format, formatDistance } from 'date-fns'; import { format, formatDistance } from 'date-fns';
import { loadData, loadNodeInfo } from './api-handler'; import { loadData, loadNodeInfo } from './api-handler';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { formatHostname, formatHashes, formatBytes } from '$lib/utils/strings'; import { formatHashes, formatBytes } from '$lib/utils/strings';
import { import {
DtSrRowsPerPage, DtSrRowsPerPage,
DtSrThSort, DtSrThSort,
@ -71,11 +71,11 @@
<tbody> <tbody>
<tr> <tr>
<td class="font-bold">Hostname:Port</td> <td class="font-bold">Hostname:Port</td>
<td>{formatHostname(nodeInfo?.hostname)}:{nodeInfo?.port}</td> <td>{nodeInfo?.hostname}:{nodeInfo?.port}</td>
</tr> </tr>
<tr> <tr>
<td class="font-bold">Public IP</td> <td class="font-bold">Public IP</td>
<td>{nodeInfo?.ip_addresses.replace(/,/g, ', ')}</td> <td>{nodeInfo?.ip}</td>
</tr> </tr>
<tr> <tr>
<td class="font-bold">Net Type</td> <td class="font-bold">Net Type</td>

View file

@ -24,7 +24,6 @@ type App struct {
APIKey string APIKey string
AcceptTor bool AcceptTor bool
TorSOCKS string TorSOCKS string
IPv6Capable bool
} }
func init() { func init() {
@ -66,5 +65,4 @@ func LoadApp() {
app.APIKey = os.Getenv("API_KEY") app.APIKey = os.Getenv("API_KEY")
app.AcceptTor, _ = strconv.ParseBool(os.Getenv("ACCEPT_TOR")) app.AcceptTor, _ = strconv.ParseBool(os.Getenv("ACCEPT_TOR"))
app.TorSOCKS = os.Getenv("TOR_SOCKS") app.TorSOCKS = os.Getenv("TOR_SOCKS")
app.IPv6Capable, _ = strconv.ParseBool(os.Getenv("IPV6_CAPABLE"))
} }

View file

@ -7,7 +7,7 @@ import (
type migrateFn func(*DB) error type migrateFn func(*DB) error
var dbMigrate = [...]migrateFn{v1, v2, v3} var dbMigrate = [...]migrateFn{v1, v2}
func MigrateDb(db *DB) error { func MigrateDb(db *DB) error {
version := getSchemaVersion(db) version := getSchemaVersion(db)
@ -256,19 +256,3 @@ func v2(db *DB) error {
return nil return nil
} }
func v3(db *DB) error {
slog.Debug("[DB] Migrating database schema version 3")
// table: tbl_node
slog.Debug("[DB] Adding additional columns to tbl_node")
_, err := db.Exec(`
ALTER TABLE tbl_node
ADD COLUMN ipv6_only TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER cors_capable,
ADD COLUMN ip_addresses TEXT NOT NULL DEFAULT '' AFTER cors_capable;`)
if err != nil {
return err
}
return nil
}

View file

@ -171,10 +171,9 @@ func Countries(c *fiber.Ctx) error {
// This handler should protected by `CheckProber` middleware. // This handler should protected by `CheckProber` middleware.
func GiveJob(c *fiber.Ctx) error { func GiveJob(c *fiber.Ctx) error {
acceptTor := c.QueryInt("accept_tor", 0) acceptTor := c.QueryInt("accept_tor", 0)
acceptIPv6 := c.QueryInt("accept_ipv6", 0)
moneroRepo := monero.New() moneroRepo := monero.New()
node, err := moneroRepo.GiveJob(acceptTor, acceptIPv6) node, err := moneroRepo.GiveJob(acceptTor)
if err != nil { if err != nil {
return c.JSON(fiber.Map{ return c.JSON(fiber.Map{
"status": "error", "status": "error",

View file

@ -1,28 +0,0 @@
// Package ip provides IP address related functions
package ip
import (
"net"
"strings"
)
// IsIPv6Only returns true if all given IPs are IPv6
func IsIPv6Only(ips []net.IP) bool {
for _, ip := range ips {
if ip.To4() != nil {
return false
}
}
return true
}
// SliceToString converts []net.IP to a string separated by comma.
// If the separator is empty, it defaults to ",".
func SliceToString(ips []net.IP) string {
r := make([]string, len(ips))
for i, j := range ips {
r[i] = j.String()
}
return strings.Join(r, ",")
}

View file

@ -1,86 +0,0 @@
package ip
import (
"net"
"testing"
)
// Single test: go test ./internal/ip -bench TestIsIPv6Only -benchmem -run=^$ -v
func TestIsIPv6Only(t *testing.T) {
tests := []struct {
name string
ips []net.IP
want bool
}{
{
name: "IPv4",
ips: []net.IP{
net.ParseIP("1.1.1.1"),
},
want: false,
},
{
name: "IPv6",
ips: []net.IP{
net.ParseIP("2606:4700::6810:85e5"),
},
want: true,
},
{
name: "IPv6 and IPv4",
ips: []net.IP{
net.ParseIP("1.1.1.1"),
net.ParseIP("2606:4700::6810:84e5"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsIPv6Only(tt.ips); got != tt.want {
t.Errorf("IsIPv6Only() = %v, want %v", got, tt.want)
}
})
}
}
// Single test: go test ./internal/ip -bench TestSliceToString -benchmem -run=^$ -v
func TestSliceToString(t *testing.T) {
tests := []struct {
name string
ips []net.IP
want string
}{
{
name: "IPv4",
ips: []net.IP{
net.ParseIP("1.1.1.1"),
},
want: "1.1.1.1",
},
{
name: "IPv6",
ips: []net.IP{
net.ParseIP("2606:4700::6810:85e5"),
},
want: "2606:4700::6810:85e5",
},
{
name: "IPv6 and IPv4",
ips: []net.IP{
net.ParseIP("1.1.1.1"),
net.ParseIP("2606:4700::6810:85e5"),
},
want: "1.1.1.1,2606:4700::6810:85e5",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SliceToString(tt.ips); got != tt.want {
t.Errorf("SliceToString() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -12,7 +12,7 @@ import (
"time" "time"
"github.com/ditatompel/xmr-remote-nodes/internal/database" "github.com/ditatompel/xmr-remote-nodes/internal/database"
"github.com/ditatompel/xmr-remote-nodes/internal/ip"
"github.com/jmoiron/sqlx/types" "github.com/jmoiron/sqlx/types"
) )
@ -54,8 +54,6 @@ type Node struct {
FailedCount uint `json:"failed_count,omitempty" db:"failed_count"` FailedCount uint `json:"failed_count,omitempty" db:"failed_count"`
LastCheckStatus types.JSONText `json:"last_check_statuses" db:"last_check_status"` LastCheckStatus types.JSONText `json:"last_check_statuses" db:"last_check_status"`
CORSCapable bool `json:"cors" db:"cors_capable"` CORSCapable bool `json:"cors" db:"cors_capable"`
IPv6Only bool `json:"ipv6_only" db:"ipv6_only"`
IPAddresses string `json:"ip_addresses" db:"ip_addresses"`
} }
// Get node from database by id // Get node from database by id
@ -197,10 +195,7 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
if strings.HasSuffix(hostname, ".onion") { if strings.HasSuffix(hostname, ".onion") {
is_tor = true is_tor = true
} }
ip := ""
ipAddr := ""
ips := ""
ipv6_only := false
if !is_tor { if !is_tor {
hostIps, err := net.LookupIP(hostname) hostIps, err := net.LookupIP(hostname)
@ -208,9 +203,10 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
return err return err
} }
ipv6_only = ip.IsIPv6Only(hostIps) hostIp := hostIps[0].To4()
if hostIp == nil {
hostIp := hostIps[0] return errors.New("Host IP is not IPv4")
}
if hostIp.IsPrivate() { if hostIp.IsPrivate() {
return errors.New("IP address is private") return errors.New("IP address is private")
} }
@ -218,8 +214,7 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
return errors.New("IP address is loopback address") return errors.New("IP address is loopback address")
} }
ipAddr = hostIp.String() ip = hostIp.String()
ips = ip.SliceToString(hostIps)
} }
row, err := r.db.Query(` row, err := r.db.Query(`
@ -253,9 +248,7 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
lon, lon,
date_entered, date_entered,
last_checked, last_checked,
last_check_status, last_check_status
ip_addresses,
ipv6_only
) VALUES ( ) VALUES (
?, ?,
?, ?,
@ -267,8 +260,6 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
?, ?,
?, ?,
?, ?,
?,
?,
? ?
)`, )`,
protocol, protocol,
@ -276,14 +267,12 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
port, port,
is_tor, is_tor,
"", "",
ipAddr, ip,
0, 0,
0, 0,
time.Now().Unix(), time.Now().Unix(),
0, 0,
string(statusDb), string(statusDb))
ips,
ipv6_only)
if err != nil { if err != nil {
return err return err
} }

View file

@ -10,7 +10,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/ditatompel/xmr-remote-nodes/internal/ip/geo" "github.com/ditatompel/xmr-remote-nodes/internal/geo"
) )
type QueryLogs struct { type QueryLogs struct {
@ -108,7 +108,7 @@ func (r *moneroRepo) Logs(q QueryLogs) (FetchLogs, error) {
} }
// GiveJob returns node that should be probed for the next time // 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 int) (Node, error) {
args := []interface{}{} args := []interface{}{}
wq := []string{} wq := []string{}
where := "" where := ""
@ -117,10 +117,6 @@ func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
wq = append(wq, "is_tor = ?") wq = append(wq, "is_tor = ?")
args = append(args, 0) args = append(args, 0)
} }
if acceptIPv6 != 1 {
wq = append(wq, "ipv6_only = ?")
args = append(args, 0)
}
if len(wq) > 0 { if len(wq) > 0 {
where = "WHERE " + strings.Join(wq, " AND ") where = "WHERE " + strings.Join(wq, " AND ")
@ -308,9 +304,7 @@ func (r *moneroRepo) ProcessJob(report ProbeReport, proberId int64) error {
city = ?, city = ?,
last_checked = ?, last_checked = ?,
last_check_status = ?, last_check_status = ?,
cors_capable = ?, cors_capable = ?
ip_addresses = ?,
ipv6_only = ?
WHERE WHERE
id = ?` id = ?`
_, err := r.db.Exec(update, _, err := r.db.Exec(update,
@ -332,8 +326,6 @@ func (r *moneroRepo) ProcessJob(report ProbeReport, proberId int64) error {
now.Unix(), now.Unix(),
statuses, statuses,
report.Node.CORSCapable, report.Node.CORSCapable,
report.Node.IPAddresses,
report.Node.IPv6Only,
report.Node.ID) report.Node.ID)
if err != nil { if err != nil {
slog.Warn(err.Error()) slog.Warn(err.Error())
@ -345,12 +337,10 @@ func (r *moneroRepo) ProcessJob(report ProbeReport, proberId int64) error {
is_available = ?, is_available = ?,
uptime = ?, uptime = ?,
last_checked = ?, last_checked = ?,
last_check_status = ?, last_check_status = ?
ip_addresses = ?,
ipv6_only = ?
WHERE WHERE
id = ?` id = ?`
if _, err := r.db.Exec(u, 0, report.Node.Uptime, now.Unix(), statuses, report.Node.IPAddresses, report.Node.IPv6Only, report.Node.ID); err != nil { if _, err := r.db.Exec(u, 0, report.Node.Uptime, now.Unix(), statuses, report.Node.ID); err != nil {
slog.Warn(err.Error()) slog.Warn(err.Error())
} }
} }