ronantakizawa/codereview-bench huggingface dataset:
Repository: louislam/uptime-kuma
File: server/notification-providers/yzj.js (JavaScript)

Code before:
            this.throwGeneralAxiosError(error);
        }
    }

    /**
     * Send message to YZJ
     * @param {object} notification Notification
     * @param {object} params Parameters of message
     * @returns {boolean} True if successful else false
     */
    async sendToYZJ(notification, params) {

        let config = {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            url: `${notification.yzjWebHookUrl}?yzjtype=${notification.yzjType}&yzjtoken=${notification.yzjToken}`,
            data: JSON.stringify(params),
        };

        let result = await axios(config);
        if (!result.data?.success) {
            throw new Error(result.data?.errmsg);
        }
    }

    /**
     * Convert status constant to string
     * @param {string} status The status constant
     * @returns {string} status
     */
    statusToString(status) {
        switch (status) {
            case DOWN:
                return "❌";
            case UP:
                return "✅";
            default:
                return status;
        }
    }
}

module.exports = YZJ;


Review comment (suggestion):
lets not make this notification provider special

```suggestion
            if (heartbeatJSON !== null) {
                msg = `${this.statusToString(heartbeatJSON["status"])} ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`;
            }

            const config = {
                headers: {
                    "Content-Type": "application/json",
                },
            };
            const params = {
                content: msg
            };
            const url = `${notification.yzjWebHookUrl}?yzjtype=${notification.yzjType}&yzjtoken=${notification.yzjToken}`;

            const result = await axios.post(url, params, config);
            if (!result.data?.success) {
                throw new Error(result.data?.errmsg ?? "yzj's server did not respond with the expected result");
            }
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
```

Code after:
            const url = `${notification.yzjWebHookUrl}?yzjtype=0&yzjtoken=${notification.yzjToken}`;

            const result = await axios.post(url, params, config);
            if (!result.data?.success) {
                throw new Error(result.data?.errmsg ?? "yzj's server did not respond with the expected result");
            }
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }

    /**
     * Convert status constant to string
     * @param {string} status The status constant
     * @returns {string} status
     */
    statusToString(status) {
        switch (status) {
            case DOWN:
                return "❌";
            case UP:
                return "✅";
            default:
                return status;
        }
    }
}

module.exports = YZJ;
Repository: louislam/uptime-kuma
File: src/components/notifications/PushPlus.vue (Vue)

Code before:
<template>
    <div class="mb-3">
        <label for="pushPlus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
        <HiddenInput id="pushPlus-sendkey" v-model="$parent.notification.pushPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
    </div>
    <a href="https://www.pushplus.plus/" target="_blank">LearnMore"</a>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>


Review comment (suggestion):
please include all translation keys in `en.json`, if it is not there our kickass army of translators will be unable to translate `SendKey`.

Code after:
<template>
    <div class="mb-3">
        <label for="pushPlus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
        <HiddenInput id="pushPlus-sendkey" v-model="$parent.notification.pushPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
    </div>
    <i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
        <a href="https://www.pushplus.plus/" target="_blank">https://www.pushplus.plus/</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>
Repository: louislam/uptime-kuma
File: src/components/notifications/PushPlus.vue (Vue)

Code before:
<template>
    <div class="mb-3">
        <label for="pushPlus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
        <HiddenInput id="pushPlus-sendkey" v-model="$parent.notification.pushPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
    </div>
    <a href="https://www.pushplus.plus/" target="_blank">LearnMore"</a>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>


Review comment (suggestion):
Here is how I think this should be localised instead.

```suggestion
    <i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
      <a href="https://www.pushplus.plus/" target="_blank">https://www.pushplus.plus/</a>
    </i18n-t>
```

Code after:
<template>
    <div class="mb-3">
        <label for="pushPlus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
        <HiddenInput id="pushPlus-sendkey" v-model="$parent.notification.pushPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
    </div>
    <i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
        <a href="https://www.pushplus.plus/" target="_blank">https://www.pushplus.plus/</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>
Repository: louislam/uptime-kuma
File: server/notification-providers/spugpush.js (JavaScript)

Code before:
            });

            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }

    /**
     * Get the formatted target for message
     * @param {object} monitorJSON Monitor details (For Up/Down only)
     * @returns {string} Formatted target
     */
    getTarget(monitorJSON) {
        let target = "-";
        if (monitorJSON["hostname"]) {
            target = monitorJSON["hostname"];
            if (monitorJSON["port"]) {
                target += ":" + monitorJSON["port"];
            }
        } else if (monitorJSON["url"]) {
            target = monitorJSON["url"];
        }
        return target;
    }
}

module.exports = SpugPush;


Review comment (refactor):
Is this what you meant?

https://github.com/louislam/uptime-kuma/blob/b22969a3e6c6fdf226325eca08347f369c0c4512/server/notification-providers/notification-provider.js#L30-L53

```suggestion
                "target": this.extractAddress(monitorJSON),
            });

            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
```

Code after:
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");

class SpugPush extends NotificationProvider {

    name = "SpugPush";

    /**
     * @inheritdoc
     */
    async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
        let okMsg = "Sent Successfully.";
        try {
            let formData = {
                msg
            };
            const apiUrl = `https://push.spug.cc/send/${notification.templateKey}`;
            if (heartbeatJSON == null) {
                formData.title = "Uptime Kuma Message";
            } else if (heartbeatJSON["status"] === UP) {
                formData.title = `UptimeKuma 「${monitorJSON["name"]}」 is Up`;
                formData.msg = `[✅ Up] ${heartbeatJSON["msg"]}`;
            } else if (heartbeatJSON["status"] === DOWN) {
                formData.title = `UptimeKuma 「${monitorJSON["name"]}」 is Down`;
                formData.msg = `[🔴 Down] ${heartbeatJSON["msg"]}`;
            }

            await axios.post(apiUrl, formData);
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = SpugPush;
Repository: louislam/uptime-kuma
File: server/notification-providers/notifery.js (JavaScript)

Code before:
            title: notification.notiferyTitle || "Uptime Kuma Alert",
            message: msg,
        };

        // Add group if specified
        if (notification.notiferyGroup) {
            data.group = notification.notiferyGroup;
        }

        // Add link to monitor
        const baseURL = await setting("primaryBaseURL");
        if (baseURL && monitorJSON) {
            // Add monitor link as part of the message
            data.message += `\n\nMonitor: ${baseURL}${getMonitorRelativeURL(monitorJSON.id)}`;
        }

        // Add code and duration if heartbeat exists
        if (heartbeatJSON) {
            // Add status code - if DOWN use code 1, otherwise 0
            data.code = heartbeatJSON.status === UP ? 0 : 1;

            // Add ping duration if available
            if (heartbeatJSON.ping) {
                data.duration = heartbeatJSON.ping;
            }
        }

        try {
            const headers = {
                "Content-Type": "application/json",
                "x-api-key": notification.notiferyApiKey,
            };

            await axios.post(url, data, { headers });
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = Notifery;


Review comment (suggestion):
I like to only add comments whree they add context, otherwise this feels too much like grafiti

```suggestion
        let data = {
            title: notification.notiferyTitle || "Uptime Kuma Alert",
            message: msg,
        };

        if (notification.notiferyGroup) {
            data.group = notification.notiferyGroup;
        }

        // Link to the monitor
        const baseURL = await setting("primaryBaseURL");
        if (baseURL && monitorJSON) {
            data.message += `\n\nMonitor: ${baseURL}${getMonitorRelativeURL(monitorJSON.id)}`;
        }

        if (heartbeatJSON) {
            data.code = heartbeatJSON.status === UP ? 0 : 1;

            if (heartbeatJSON.ping) {
                data.duration = heartbeatJSON.ping;
            }
        }
```

Code after:
            message: msg,
        };

        if (notification.notiferyGroup) {
            data.group = notification.notiferyGroup;
        }

        // Link to the monitor
        const baseURL = await setting("primaryBaseURL");
        if (baseURL && monitorJSON) {
            data.message += `\n\nMonitor: ${baseURL}${getMonitorRelativeURL(monitorJSON.id)}`;
        }

        if (heartbeatJSON) {
            data.code = heartbeatJSON.status === UP ? 0 : 1;

            if (heartbeatJSON.ping) {
                data.duration = heartbeatJSON.ping;
            }
        }

        try {
            const headers = {
                "Content-Type": "application/json",
                "x-api-key": notification.notiferyApiKey,
            };

            await axios.post(url, data, { headers });
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = Notifery;
Repository: louislam/uptime-kuma
File: src/components/notifications/Notifery.vue (Vue)

Code before:
<template>
    <div class="mb-3">
        <label for="notifery-api-key" class="form-label">{{
            $t("API Key")
        }}</label>
        <HiddenInput
            id="notifery-api-key"
            v-model="$parent.notification.notiferyApiKey"
            :required="true"
            autocomplete="new-password"
        ></HiddenInput>
    </div>

    <div class="mb-3">
        <label for="notifery-title" class="form-label">{{ $t("Title") }}</label>
        <input
            id="notifery-title"
            v-model="$parent.notification.notiferyTitle"
            type="text"
            class="form-control"
            :placeholder="$t('Uptime Kuma Alert')"
        />
    </div>

    <div class="mb-3">
        <label for="notifery-group" class="form-label">{{ $t("Group") }}</label>
        <input
            id="notifery-group"
            v-model="$parent.notification.notiferyGroup"
            type="text"
            class="form-control"
            :placeholder="$t('Optional')"
        />
    </div>

    <i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
        <a href="https://docs.notifery.com/api/event/" target="_blank">https://docs.notifery.com/api/event/</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,

Review comment (suggestion):
Not actually translated in the backend and not in `en.json` => cannot be translated

```suggestion
            placeholder="Uptime Kuma Alert"
```

Code after:
<template>
    <div class="mb-3">
        <label for="notifery-api-key" class="form-label">{{
            $t("API Key")
        }}</label>
        <HiddenInput
            id="notifery-api-key"
            v-model="$parent.notification.notiferyApiKey"
            :required="true"
            autocomplete="new-password"
        ></HiddenInput>
    </div>

    <div class="mb-3">
        <label for="notifery-title" class="form-label">{{ $t("Title") }}</label>
        <input
            id="notifery-title"
            v-model="$parent.notification.notiferyTitle"
            type="text"
            class="form-control"
            placeholder="Uptime Kuma Alert"
        />
    </div>

    <div class="mb-3">
        <label for="notifery-group" class="form-label">{{ $t("Group") }}</label>
        <input
            id="notifery-group"
            v-model="$parent.notification.notiferyGroup"
            type="text"
            class="form-control"
            :placeholder="$t('Optional')"
        />
    </div>

    <i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
        <a href="https://docs.notifery.com/api/event/" target="_blank">https://docs.notifery.com/api/event/</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
Repository: louislam/uptime-kuma
File: server/monitor-types/manual.js (JavaScript)

Code before:
const { MonitorType } = require("./monitor-type");

class ManualMonitorType extends MonitorType {
    name = "Manual";
    type = "manual";
    description = "Manual monitoring";
    supportsConditions = false;
    conditionVariables = [];

    /**
     * Checks the status of the monitor manually
     * @param {object} monitor - Monitor object
     * @param {object} heartbeat - Object to write the status of the check
     * @param {object} server - Server object
     * @returns {Promise<void>}
     */
    async check(monitor, heartbeat, server) {
        heartbeat.status = monitor.status;
        heartbeat.msg = monitor.msg || "Manual monitoring";
        heartbeat.time = new Date().getTime();
    }
}

module.exports = {
    ManualMonitorType
};


Review comment (suggestion):
the time at which it happens should be set here

```suggestion
```

Code after:
const { MonitorType } = require("./monitor-type");
const { UP, DOWN, PENDING } = require("../../src/util");

class ManualMonitorType extends MonitorType {
    name = "Manual";
    type = "manual";
    description = "A monitor that allows manual control of the status";
    supportsConditions = false;
    conditionVariables = [];

    /**
     * @inheritdoc
     */
    async check(monitor, heartbeat) {
        if (monitor.manual_status !== null) {
            heartbeat.status = monitor.manual_status;
            switch (monitor.manual_status) {
                case UP:
                    heartbeat.msg = "Up";
                    break;
                case DOWN:
                    heartbeat.msg = "Down";
                    break;
                default:
                    heartbeat.msg = "Pending";
            }
        } else {
            heartbeat.status = PENDING;
            heartbeat.msg = "Manual monitoring - No status set";
        }
    }
}

module.exports = {
    ManualMonitorType
};
Repository: louislam/uptime-kuma
File: server/monitor-types/manual.js (JavaScript)

Code before:
class ManualMonitorType extends MonitorType {
    name = "Manual";
    type = "manual";
    description = "A monitor that allows manual control of the status";
    supportsConditions = false;
    conditionVariables = [];

    /**
     * Checks the status of the monitor based on the manually set status
     * This monitor type is specifically designed for status pages where manual control is needed
     * @param {object} monitor - Monitor object containing the current status and message
     * @param {object} heartbeat - Object to write the status of the check
     * @returns {Promise<void>}
     */
    async check(monitor, heartbeat) {
        if (monitor.manual_status !== null) {
            heartbeat.status = monitor.manual_status;
            heartbeat.msg = monitor.manual_status === UP ? "Up" :
                monitor.manual_status === DOWN ? "Down" :
                    monitor.manual_status === MAINTENANCE ? "Maintenance" :
                        "Pending";
            heartbeat.ping = null;
        } else {
            heartbeat.status = PENDING;
            heartbeat.msg = "Manual monitoring - No status set";
            heartbeat.ping = null;
        }
    }
}

module.exports = {
    ManualMonitorType
};


Review comment (suggestion):
I don't think this is nesssesary, or?

```suggestion
        } else {
            heartbeat.status = PENDING;
            heartbeat.msg = "Manual monitoring - No status set";
```


Code after:
class ManualMonitorType extends MonitorType {
    name = "Manual";
    type = "manual";
    description = "A monitor that allows manual control of the status";
    supportsConditions = false;
    conditionVariables = [];

    /**
     * @inheritdoc
     */
    async check(monitor, heartbeat) {
        if (monitor.manual_status !== null) {
            heartbeat.status = monitor.manual_status;
            switch (monitor.manual_status) {
                case UP:
                    heartbeat.msg = "Up";
                    break;
                case DOWN:
                    heartbeat.msg = "Down";
                    break;
                default:
                    heartbeat.msg = "Pending";
            }
        } else {
            heartbeat.status = PENDING;
            heartbeat.msg = "Manual monitoring - No status set";
        }
    }
}

module.exports = {
    ManualMonitorType
};
Repository: louislam/uptime-kuma
File: server/server.js (JavaScript)

Code before:
                    data.monitorID,
                    socket.userID,
                ]);

                if (!monitor) {
                    throw new Error("Monitor not found");
                }

                let status;
                if (data.status === 1) {
                    status = UP;
                } else if (data.status === 0) {
                    status = DOWN;
                } else if (data.status === 3) {
                    status = MAINTENANCE;
                } else {
                    status = PENDING;
                }

                monitor.manual_status = status;
                await R.store(monitor);

                callback({
                    ok: true,
                    msg: "Saved.",
                    msgi18n: true,
                    id: monitor.id,
                });

            } catch (e) {
                callback({
                    ok: true,
                    msg: e.message,
                });
            }
        });

    });

    log.debug("server", "Init the server");

    server.httpServer.once("error", async (err) => {
        log.error("server", "Cannot listen: " + err.message);
        await shutdownFunction();
        process.exit(1);
    });

    await server.start();

    server.httpServer.listen(port, hostname, async () => {
        if (hostname) {

Review comment (suggestion):
You are setting that above msg is an i18n key.
You are not using it like this in the frontend though.

=> Please either use the i18n using the key or don't tell the frontend that this is a translation key.

Code after:

    server.httpServer.once("error", async (err) => {
        log.error("server", "Cannot listen: " + err.message);
        await shutdownFunction();
        process.exit(1);
    });

    await server.start();

    server.httpServer.listen(port, hostname, async () => {
        if (hostname) {
            log.info("server", `Listening on ${hostname}:${port}`);
        } else {
            log.info("server", `Listening on ${port}`);
        }
        await startMonitors();

        // Put this here. Start background jobs after the db and server is ready to prevent clear up during db migration.
        await initBackgroundJobs();

        checkVersion.startInterval();
    });

    // Start cloudflared at the end if configured
    await cloudflaredAutoStart(cloudflaredToken);

})();

/**
 * Update notifications for a given monitor
 * @param {number} monitorID ID of monitor to update
 * @param {number[]} notificationIDList List of new notification
 * providers to add
 * @returns {Promise<void>}
 */
async function updateMonitorNotification(monitorID, notificationIDList) {
    await R.exec("DELETE FROM monitor_notification WHERE monitor_id = ? ", [
        monitorID,
    ]);

    for (let notificationID in notificationIDList) {
        if (notificationIDList[notificationID]) {
            let relation = R.dispense("monitor_notification");
            relation.monitor_id = monitorID;
            relation.notification_id = notificationID;
            await R.store(relation);
        }
    }
}

/**