mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-10-01 01:25:45 -04:00
Merge branch 'louislam:master' into logging
This commit is contained in:
commit
38f8a8ac2f
@ -41,6 +41,8 @@ docker volume create uptime-kuma
|
||||
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1
|
||||
```
|
||||
|
||||
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
|
||||
|
||||
Browse to http://localhost:3001 after starting.
|
||||
|
||||
### 💪🏻 Non-Docker
|
||||
|
@ -33,7 +33,7 @@ RUN apt update && \
|
||||
|
||||
COPY --from=build /app /app
|
||||
|
||||
ARG VERSION=1.9.1
|
||||
ARG VERSION
|
||||
ARG GITHUB_TOKEN
|
||||
ARG TARGETARCH
|
||||
ARG PLATFORM=debian
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.10.2",
|
||||
"version": "1.11.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -30,13 +30,13 @@
|
||||
"build-docker": "npm run build-docker-debian && npm run build-docker-alpine",
|
||||
"build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push",
|
||||
"build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push",
|
||||
"build-docker-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:1.10.2-alpine --target release . --push",
|
||||
"build-docker-debian": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.10.2 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.10.2-debian --target release . --push",
|
||||
"build-docker-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:1.11.1-alpine --target release . --push",
|
||||
"build-docker-debian": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.11.1 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.11.1-debian --target release . --push",
|
||||
"build-docker-nightly": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||
"build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push",
|
||||
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.10.2 && npm ci --production && npm run download-dist",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.11.1 && npm ci --production && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"update-version": "node extra/update-version.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
|
@ -297,6 +297,9 @@ class Monitor extends BeanModel {
|
||||
log_debug("monitor", "heartbeatCount" + heartbeatCount + " " + time);
|
||||
|
||||
if (heartbeatCount <= 0) {
|
||||
// Fix #922, since previous heartbeat could be inserted by api, it should get from database
|
||||
previousBeat = await Monitor.getPreviousHeartbeat(this.id);
|
||||
|
||||
throw new Error("No heartbeat in the time window");
|
||||
} else {
|
||||
// No need to insert successful heartbeat for push type, so end here
|
||||
@ -752,6 +755,15 @@ class Monitor extends BeanModel {
|
||||
log_debug("monitor", "No notification, no need to send cert notification");
|
||||
}
|
||||
}
|
||||
|
||||
static async getPreviousHeartbeat(monitorID) {
|
||||
return await R.getRow(`
|
||||
SELECT status, time FROM heartbeat
|
||||
WHERE id = (select MAX(id) from heartbeat where monitor_id = ?)
|
||||
`, [
|
||||
monitorID
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Monitor;
|
||||
|
@ -31,12 +31,7 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
||||
throw new Error("Monitor not found or not active.");
|
||||
}
|
||||
|
||||
const previousHeartbeat = await R.getRow(`
|
||||
SELECT status, time FROM heartbeat
|
||||
WHERE id = (select MAX(id) from heartbeat where monitor_id = ?)
|
||||
`, [
|
||||
monitor.id
|
||||
]);
|
||||
const previousHeartbeat = await Monitor.getPreviousHeartbeat(monitor.id);
|
||||
|
||||
let status = UP;
|
||||
if (monitor.isUpsideDown()) {
|
||||
@ -158,7 +153,10 @@ router.get("/api/status-page/monitor-list", cache("5 minutes"), async (_request,
|
||||
ON monitor_tag.tag_id = tag.id
|
||||
WHERE monitor_tag.monitor_id = ?`, [monitor.id]
|
||||
);
|
||||
return {...monitor, tags: tags}
|
||||
return {
|
||||
...monitor,
|
||||
tags: tags
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
export default {
|
||||
languageName: "Français (France)",
|
||||
languageName: "Français",
|
||||
checkEverySecond: "Vérifier toutes les {0} secondes",
|
||||
retryCheckEverySecond: "Réessayer toutes les {0} secondes.",
|
||||
retriesDescription: "Nombre d'essais avant que le service soit déclaré hors-ligne.",
|
||||
@ -13,17 +13,17 @@ export default {
|
||||
pauseDashboardHome: "En pause",
|
||||
deleteMonitorMsg: "Êtes-vous sûr de vouloir supprimer cette sonde ?",
|
||||
deleteNotificationMsg: "Êtes-vous sûr de vouloir supprimer ce type de notifications ? Une fois désactivée, les services qui l'utilisent ne pourront plus envoyer de notifications.",
|
||||
resoverserverDescription: "Le DNS de cloudflare est utilisé par défaut, mais vous pouvez le changer si vous le souhaitez.",
|
||||
rrtypeDescription: "Veuillez séléctionner un type d'enregistrement DNS",
|
||||
resoverserverDescription: "Le DNS de Cloudflare est utilisé par défaut, mais vous pouvez le changer si vous le souhaitez.",
|
||||
rrtypeDescription: "Veuillez sélectionner un type d'enregistrement DNS",
|
||||
pauseMonitorMsg: "Êtes-vous sûr de vouloir mettre en pause cette sonde ?",
|
||||
enableDefaultNotificationDescription: "Pour chaque nouvelle sonde, cette notification sera activée par défaut. Vous pouvez toujours désactiver la notification séparément pour chaque sonde.",
|
||||
clearEventsMsg: "Êtes-vous sûr de vouloir supprimer tous les événements pour cette sonde ?",
|
||||
clearHeartbeatsMsg: "Êtes-vous sûr de vouloir supprimer tous les vérifications pour cette sonde ?",
|
||||
confirmClearStatisticsMsg: "Êtes-vous sûr de vouloir supprimer tous les statistiques ?",
|
||||
clearHeartbeatsMsg: "Êtes-vous sûr de vouloir supprimer toutes les vérifications pour cette sonde ?",
|
||||
confirmClearStatisticsMsg: "Êtes-vous sûr de vouloir supprimer toutes les statistiques ?",
|
||||
importHandleDescription: "Choisissez 'Ignorer l'existant' si vous voulez ignorer chaque sonde ou notification portant le même nom. L'option 'Écraser' supprime toutes les sondes et notifications existantes.",
|
||||
confirmImportMsg: "Êtes-vous sûr de vouloir importer la sauvegarde ? Veuillez vous assurer que vous avez sélectionné la bonne option d'importation.",
|
||||
twoFAVerifyLabel: "Veuillez saisir votre jeton pour vérifier que le système 2FA fonctionne.",
|
||||
tokenValidSettingsMsg: "Le jeton est valide ; Vous pouvez maintenant sauvegarder les paramètres 2FA.",
|
||||
tokenValidSettingsMsg: "Le jeton est valide. Vous pouvez maintenant sauvegarder les paramètres 2FA.",
|
||||
confirmEnableTwoFAMsg: "Êtes-vous sûr de vouloir activer le 2FA ?",
|
||||
confirmDisableTwoFAMsg: "Êtes-vous sûr de vouloir désactiver le 2FA ?",
|
||||
Settings: "Paramètres",
|
||||
@ -68,9 +68,9 @@ export default {
|
||||
URL: "URL",
|
||||
Hostname: "Nom d'hôte / adresse IP",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Intervale de vérification",
|
||||
"Heartbeat Interval": "Intervalle de vérification",
|
||||
Retries: "Essais",
|
||||
"Heartbeat Retry Interval": "Réessayer l'intervale de vérification",
|
||||
"Heartbeat Retry Interval": "Réessayer l'intervalle de vérification",
|
||||
Advanced: "Avancé",
|
||||
"Upside Down Mode": "Mode inversé",
|
||||
"Max. Redirects": "Nombre maximum de redirections",
|
||||
@ -107,8 +107,8 @@ export default {
|
||||
Password: "Mot de passe",
|
||||
"Remember me": "Se souvenir de moi",
|
||||
Login: "Se connecter",
|
||||
"No Monitors, please": "Pas de sondes, veuillez ",
|
||||
"add one": "en ajouter une.",
|
||||
"No Monitors, please": "Pas de sondes, veuillez",
|
||||
"add one": "en ajouter une",
|
||||
"Notification Type": "Type de notification",
|
||||
Email: "Email",
|
||||
Test: "Tester",
|
||||
@ -132,7 +132,7 @@ export default {
|
||||
Heartbeats: "Vérfications",
|
||||
"Auto Get": "Récuperer automatiquement",
|
||||
backupDescription: "Vous pouvez sauvegarder toutes les sondes et toutes les notifications dans un fichier JSON.",
|
||||
backupDescription2: "PS: Les données relatives à l'historique et aux événements ne sont pas incluses.",
|
||||
backupDescription2: "PS : Les données relatives à l'historique et aux événements ne sont pas incluses.",
|
||||
backupDescription3: "Les données sensibles telles que les jetons de notification sont incluses dans le fichier d'exportation, veuillez les conserver soigneusement.",
|
||||
alertNoFile: "Veuillez sélectionner un fichier à importer.",
|
||||
alertWrongFileType: "Veuillez sélectionner un fichier JSON à importer.",
|
||||
@ -196,7 +196,7 @@ export default {
|
||||
webhookJsonDesc: "{0} est bien/bon pour tous les serveurs HTTP modernes comme express.js",
|
||||
webhookFormDataDesc: "{multipart} est bien/bon pour du PHP, vous avez juste besoin de mettre le json via/depuis {decodeFunction}",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "Aucun / STARTTLS (25, 587)",
|
||||
secureOptionNone: "Aucun/STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignorer les erreurs TLS",
|
||||
"From Email": "Depuis l'Email",
|
||||
@ -217,7 +217,7 @@ export default {
|
||||
Recipients: "Destinataires",
|
||||
needSignalAPI: "Vous avez besoin d'un client Signal avec l'API REST.",
|
||||
wayToCheckSignalURL: "Vous pouvez regarder l'URL sur comment le mettre en place :",
|
||||
signalImportant: "IMPORTANT: Vous ne pouvez pas mixer les groupes et les numéros en destinataires !",
|
||||
signalImportant: "IMPORTANT : Vous ne pouvez pas mixer les groupes et les numéros en destinataires !",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "Application Token",
|
||||
"Server URL": "Server URL",
|
||||
@ -226,7 +226,7 @@ export default {
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Nom du salon",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Plus d'informations sur les Webhooks ici: {0}",
|
||||
aboutWebhooks: "Plus d'informations sur les Webhooks ici : {0}",
|
||||
aboutChannelName: "Mettez le nom du salon dans {0} dans 'Channel Name' si vous voulez bypass le salon Webhook. Ex : #autre-salon",
|
||||
aboutKumaURL: "Si vous laissez l'URL d'Uptime Kuma vierge, elle redirigera vers la page du projet GitHub.",
|
||||
emojiCheatSheet: "Emoji cheat sheet : {0}",
|
||||
@ -244,14 +244,14 @@ export default {
|
||||
Device: "Appareil",
|
||||
"Message Title": "Titre du message",
|
||||
"Notification Sound": "Son de notification",
|
||||
"More info on:": "Plus d'informations sur: {0}",
|
||||
"More info on:": "Plus d'informations sur : {0}",
|
||||
pushoverDesc1: "Priorité d'urgence (2) a par défaut 30 secondes de délai dépassé entre les tentatives et expierera après 1 heure.",
|
||||
pushoverDesc2: "Si vous voulez envoyer des notifications sur différents Appareils, remplissez le champ 'Device'.",
|
||||
"SMS Type": "SMS Type",
|
||||
octopushTypePremium: "Premium (Rapide - recommandé pour les alertes)",
|
||||
octopushTypeLowCost: "A bas prix (Lent, bloqué de temps en temps par l'opérateur)",
|
||||
octopushTypeLowCost: "À bas prix (Lent, bloqué de temps en temps par l'opérateur)",
|
||||
"Check octopush prices": "Vérifier les prix d'octopush {0}.",
|
||||
octopushPhoneNumber: "Numéro de téléphone (format intérn., ex : +33612345678) ",
|
||||
octopushPhoneNumber: "Numéro de téléphone (format int., ex : +33612345678) ",
|
||||
octopushSMSSender: "Nom de l'envoyer : 3-11 caractères alphanumériques avec espace (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
@ -259,8 +259,8 @@ export default {
|
||||
"Read more:": "En savoir plus : {0}",
|
||||
"Status:": "Status : {0}",
|
||||
"Read more": "En savoir plus",
|
||||
appriseInstalled: "Apprise est intallé.",
|
||||
appriseNotInstalled: "Apprise n'est pas intallé. {0}",
|
||||
appriseInstalled: "Apprise est installé.",
|
||||
appriseNotInstalled: "Apprise n'est pas installé. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
@ -278,30 +278,30 @@ export default {
|
||||
promosmsTypeFull: "SMS FULL - Version Premium des SMS, Vous pouvez mettre le nom de l'expéditeur (Vous devez vous enregistrer avant). Fiable pour les alertes.",
|
||||
promosmsTypeSpeed: "SMS SPEED - La plus haute des priorités dans le système. Très rapide et fiable mais cher (environ le double du prix d'un SMS FULL).",
|
||||
promosmsPhoneNumber: "Numéro de téléphone (Poiur les déstinataires Polonais, vous pouvez enlever les codes interna.)",
|
||||
promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base : InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Primary Base URL": "Primary Base URL",
|
||||
emailCustomSubject: "Sujet personalisé",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
checkPrice: "Vérification {0} tarifs:",
|
||||
checkPrice: "Vérification {0} tarifs :",
|
||||
apiCredentials: "Crédentials de l'API",
|
||||
octopushLegacyHint: "Vous utilisez l'ancienne version d'Octopush (2011-2020) ou la nouvelle version ?",
|
||||
"Feishu WebHookUrl": "Feishu WebHookURL",
|
||||
matrixHomeserverURL: "L'URL du serveur (avec http(s):// et le port de manière facultatif)",
|
||||
"Internal Room Id": "ID de la salle interne",
|
||||
matrixDesc1: "Vous pouvez trouvez l'ID de salle interne en regardant dans la section avancée des paramètres dans le client Matrix. C'est sensé ressembler à: !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc1: "Vous pouvez trouver l'ID de salle interne en regardant dans la section avancée des paramètres dans le client Matrix. C'est censé ressembler à !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc2: "Il est fortement recommandé de créer un nouvel utilisateur et de ne pas utiliser le jeton d'accès de votre propre utilisateur Matrix, car il vous donnera un accès complet à votre compte et à toutes les salles que vous avez rejointes. Au lieu de cela, créez un nouvel utilisateur et invitez-le uniquement dans la salle dans laquelle vous souhaitez recevoir la notification. Vous pouvez obtenir le jeton d'accès en exécutant {0}",
|
||||
Method: "Méthode",
|
||||
Body: "Le corps",
|
||||
Headers: "En-têtes",
|
||||
PushUrl: "Push URL",
|
||||
HeadersInvalidFormat: "L'en-têtes de la requête n'est pas dans un format JSON valide: ",
|
||||
HeadersInvalidFormat: "Les en-têtes de la requête ne sont pas dans un format JSON valide: ",
|
||||
BodyInvalidFormat: "Le corps de la requête n'est pas dans un format JSON valide: ",
|
||||
"Monitor History": "Historique de la sonde",
|
||||
clearDataOlderThan: "Garder l'historique des données de la sonde durant {0} jours.",
|
||||
PasswordsDoNotMatch: "Les mots de passe ne correspondent pas.",
|
||||
records: "Enregistrements",
|
||||
"One record": "Un enregistrement",
|
||||
steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici: ",
|
||||
steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici : ",
|
||||
"Current User": "Utilisateur actuel",
|
||||
recent: "Récent",
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ export default {
|
||||
deleteMonitorMsg: "您確定要刪除此監測器嗎?",
|
||||
deleteNotificationMsg: "您確定要為所有監測器刪除此通知嗎?",
|
||||
resoverserverDescription: "Cloudflare 為預設伺服器。您可以隨時更換解析伺服器。",
|
||||
rrtypeDescription: "選擇您想要監測的資源記錄",
|
||||
rrtypeDescription: "選擇您想要監測的資源記錄類型",
|
||||
pauseMonitorMsg: "您確定要暫停嗎?",
|
||||
enableDefaultNotificationDescription: "預設情況下,新監測器將啟用此通知。您仍可分別停用各監測器的通知。",
|
||||
clearEventsMsg: "您確定要刪除此監測器的所有事件嗎?",
|
||||
@ -307,4 +307,50 @@ export default {
|
||||
"Showing {from} to {to} of {count} records": "正在顯示 {count} 項記錄中的 {from} 至 {to} 項",
|
||||
steamApiKeyDescription: "若要監測 Steam 遊戲伺服器,您將需要 Steam Web-API 金鑰。您可以在此註冊您的 API 金鑰:",
|
||||
"Current User": "目前使用者",
|
||||
recent: "最近",
|
||||
Done: "完成",
|
||||
Info: "資訊",
|
||||
Security: "安全性",
|
||||
"Steam API Key": "Steam API 金鑰",
|
||||
"Shrink Database": "壓縮資料庫",
|
||||
"Pick a RR-Type...": "選擇資源記錄類型...",
|
||||
"Pick Accepted Status Codes...": "選擇可接受的狀態碼...",
|
||||
Default: "預設",
|
||||
"HTTP Options": "HTTP 選項",
|
||||
"Create Incident": "建立事件",
|
||||
Title: "標題",
|
||||
Content: "內容",
|
||||
Style: "樣式",
|
||||
info: "資訊",
|
||||
warning: "警告",
|
||||
danger: "危險",
|
||||
primary: "主要",
|
||||
light: "淺色",
|
||||
dark: "暗色",
|
||||
Post: "發佈",
|
||||
"Please input title and content": "請輸入標題及內容",
|
||||
Created: "建立",
|
||||
"Last Updated": "最後更新",
|
||||
Unpin: "取消釘選",
|
||||
"Switch to Light Theme": "切換至淺色佈景主題",
|
||||
"Switch to Dark Theme": "切換至深色佈景主題",
|
||||
"Show Tags": "顯示標籤",
|
||||
"Hide Tags": "隱藏標籤",
|
||||
Description: "說明",
|
||||
"No monitors available.": "沒有可用的監測器。",
|
||||
"Add one": "新增一個",
|
||||
"No Monitors": "無監測器",
|
||||
"Add one": "新增一個",
|
||||
"Untitled Group": "未命名群組",
|
||||
Services: "服務",
|
||||
Discard: "捨棄",
|
||||
Cancel: "取消",
|
||||
"Powered by": "技術支援",
|
||||
shrinkDatabaseDescription: "觸發 SQLite 的資料庫清理 (VACUUM)。如果您的資料庫是在 1.10.0 版本後建立,AUTO_VACUUM 已自動啟用,則無需此操作。",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API 使用者名稱 (包括 webapi_ 前綴)",
|
||||
serwersmsAPIPassword: "API 密碼",
|
||||
serwersmsPhoneNumber: "電話號碼",
|
||||
serwersmsSenderName: "SMS 寄件人名稱 (由客戶入口網站註冊)",
|
||||
"stackfield": "Stackfield",
|
||||
};
|
||||
|
@ -49,8 +49,9 @@ export default {
|
||||
|
||||
computed: {
|
||||
currentPage() {
|
||||
let pathEnd = useRoute().path.split("/").at(-1);
|
||||
if (pathEnd == "settings" || pathEnd == null) {
|
||||
let pathSplit = useRoute().path.split("/");
|
||||
let pathEnd = pathSplit[pathSplit.length - 1];
|
||||
if (!pathEnd || pathEnd === "settings") {
|
||||
return "general";
|
||||
}
|
||||
return pathEnd;
|
||||
|
Loading…
Reference in New Issue
Block a user