Repository: louislam/uptime-kuma
File: server/monitor-types/tailscale-ping.js (JavaScript)

Code before:
                }
                if (stderr) {
                    reject(`Error in output: ${stderr}`);
                    return;
                }
                resolve(stdout);
            });
        });
    }

// logic for handling stdout is now moved to parseTailscaleOutput
    parseTailscaleOutput(tailscaleOutput, heartbeat) {
        let lines = tailscaleOutput.split('\n');

        for (let line of lines) {
            // "pong from" counts as UP, and we update heartbeat status and ping time
            // otherwise if "no matching peer" (nonexistant or inaccessible due to ACLs) or "is local Tailscale IP" (ping self), throw error
            // otherwise throw error and the unexpected output itself
            if (line.includes("pong from")) {
                heartbeat.status = UP;
                let time = line.split(" in ")[1].split(" ")[0];
                heartbeat.ping = parseInt(time);
                heartbeat.msg = line;
                break;
            } else if (line.includes("no matching peer") || line.includes("is local Tailscale IP")) {
                throw new Error(`"${line}"`);
            } else if (line !== '') {
                throw new Error(`Unexpected output: "${line}"`);
            }
        }
    }
}

module.exports = {
    TailscalePing,
};


Review comment (suggestion):
I think integrating the warnings from above here would be better.

```suggestion
            } else if (line.includes("no matching peer")) {
                throw new Error(`Nonexistant or inaccessible due to ACLs: "${line}"`);
            } else if (line.includes("is local Tailscale IP")) {
                throw new Error(`Tailscale only works if used on other machines: "${line}"`);
```

Code after:
                    return;
                }

                resolve(stdout);
            });
        });
    }

    /**
     * Parses the output of the Tailscale ping command to update the heartbeat.
     *
     * @param {string} tailscaleOutput - The output of the Tailscale ping command.
     * @param {Object} heartbeat - The heartbeat object to update.
     * @throws Will throw an eror if the output contains any unexpected string.
     */
    parseTailscaleOutput(tailscaleOutput, heartbeat) {
        let lines = tailscaleOutput.split("\n");

        for (let line of lines) {
            if (line.includes("pong from")) {
                heartbeat.status = UP;
                let time = line.split(" in ")[1].split(" ")[0];
                heartbeat.ping = parseInt(time);
                heartbeat.msg = line;
                break;
            } else if (line.includes("timed out")) {
                throw new Error(`Ping timed out: "${line}"`);
                // Immediately throws upon "timed out" message, the server is expected to re-call the check function
            } else if (line.includes("no matching peer")) {
                throw new Error(`Nonexistant or inaccessible due to ACLs: "${line}"`);
            } else if (line.includes("is local Tailscale IP")) {
                throw new Error(`Tailscale only works if used on other machines: "${line}"`);
            } else if (line !== "") {
                throw new Error(`Unexpected output: "${line}"`);
            }
        }
    }
}

module.exports = {
    TailscalePing,
};