-
-
Save dioncodes/cd4554d8593814a94925735cbcdea0c8 to your computer and use it in GitHub Desktop.
const initialData = { | |
servers: [ | |
{ | |
url: 'https://1.example.com/', | |
title: 'Server 1', | |
online: null, | |
}, | |
{ | |
url: 'https://2.example.com/', | |
title: 'Server 2', | |
online: null, | |
}, | |
{ | |
url: 'https://3.example.com/', | |
title: 'Server 3', | |
online: null, | |
}, | |
], | |
lastUpdate: null | |
} | |
// Refresh Interval in seconds | |
const refreshInterval = 300 | |
const widget = await createWidget() | |
if (!config.runsInWidget) { | |
await widget.presentSmall() | |
} | |
Script.setWidget(widget) | |
Script.complete() | |
async function createWidget(items) { | |
const data = await refresh() | |
const list = new ListWidget() | |
// uncomment the lines below if you want to show the header (not working with more than ~5 servers) | |
// const header = list.addText("Server Status") | |
// header.font = Font.mediumSystemFont(13) | |
// list.addSpacer() | |
data.servers.forEach((server) => { | |
const label = list.addText((server.online ? '🟢' : (server.online === false ? '🔴' : '❔')) + ' ' + server.title) | |
label.font = Font.boldSystemFont(12) | |
label.textColor = Color.gray() | |
list.refreshAfterDate = new Date(Date.now() + refreshInterval) | |
list.addSpacer(3) | |
}) | |
if (data.lastUpdate) { | |
list.addSpacer() | |
const lastRefreshLabel = list.addText('Last refresh: ' + data.lastUpdate) | |
lastRefreshLabel.font = Font.mediumSystemFont(8) | |
} | |
return list | |
} | |
async function refresh() { | |
let data = initialData | |
for (let server of data.servers) { | |
try { | |
let response = await new Request(server.url).loadString() | |
server.online = response && response.length > 0 | |
} catch (e) { | |
server.online = false | |
} | |
} | |
let now = new Date() | |
let hours = now.getHours() | |
let mins = now.getMinutes() | |
data.lastUpdate = (hours > 9 ? hours : '0' + hours) + ':' + (mins > 9 ? mins : '0' + mins) | |
return data | |
} |
@MrTheFirst Thanks, this is a great extension to the initial script. Would you mind if I adopt your notification functionality in the gist?
Of course use it! I just used the notification from the documentation. But I noticed an error in my script, if the server is not available, then a lot of notifications come (it seems as much as there are servers in the settings). This is because of the asynchronous functions in the loops.
I wanted to add ip addresses instead of http and for some reason it doesn't work. Help me how to do this?
@Sergey20482048 I used the above script with IP addresses by just using http://192.168.1.1/ in the server line , but my servers have a web page that you land on when you navigate to that IP. I'm not sure if yours are running a web server..
Does anyone know how to make this script use two columns so I can squeeze in two columns of 4 servers each?
Incorporating the advantages of the aforementioned modifications, this version also utilizes Promise.all for concurrent network requests to enhance the efficiency of checking server statuses. Additionally, it implements a retry mechanism among other optimization features. Moreover, this widget can display a list of up to 6-7 servers while showing a title.
// Variables used by Scriptable.
// icon-color: purple; icon-glyph: globe;
const initialData = {
servers: [
{ url: 'https://server1.example.com/', title: 'Server 1' },
{ url: 'https://server2.example.com/', title: 'Server 2' },
{ url: 'https://server3.example.com/', title: 'Server 3' },
{ url: 'https://server4.example.com/', title: 'Server 4' },
{ url: 'https://server5.example.com/', title: 'Server 5' },
{ url: 'https://server6.example.com/', title: 'Server 6' },
// 可以继续添加更多服务器...
],
lastUpdate: null
};
const refreshInterval = 161; // Refresh Interval in seconds
async function createWidget() {
const data = await refreshStatus();
const list = new ListWidget();
setGradientBackground(list);
addHeader(list, "CY Server&API Stat");
data.servers.forEach(server => {
addServerStatus(list, server);
list.addSpacer(3);
});
addFooter(list, data.lastUpdate);
list.refreshAfterDate = new Date(Date.now() + refreshInterval * 1000);
return list;
}
async function refreshStatus() {
let data = { ...initialData, servers: await checkServers(initialData.servers) };
data.lastUpdate = new Date().toLocaleTimeString();
return data;
}
async function checkServers(servers) {
const checks = servers.map(server => (
fetchServerStatus(server)
.then(online => ({ ...server, online }))
.catch(() => ({ ...server, online: false }))
));
return Promise.all(checks);
}
async function fetchServerStatus(server, retries = 3, delay = 1000) {
async function attemptFetch(remainingRetries) {
try {
const request = new Request(server.url);
await request.loadString(); // 尝试加载数据
return true; // 加载成功,返回在线状态
} catch (e) {
if (remainingRetries <= 0) throw e; // 重试次数用尽,抛出异常
await new Promise(resolve => setTimeout(resolve, delay)); // 等待一段时间再重试
return attemptFetch(remainingRetries - 1); // 递归调用,减少剩余重试次数
}
}
try {
return await attemptFetch(retries); // 初始调用,尝试获取状态
} catch (e) {
return false; // 所有尝试失败,返回离线状态
}
}
function setGradientBackground(list) {
const gradient = new LinearGradient();
gradient.locations = [0, 1];
gradient.colors = [
new Color('#2D1925'),
new Color('#402938')
];
list.backgroundGradient = gradient;
}
function addHeader(list, text) {
const header = list.addText(text);
header.font = Font.mediumSystemFont(13);
header.textColor = Color.white();
list.addSpacer(5);
}
function addServerStatus(list, server) {
let symbol = '❔'; // 默认状态未知
if (server.online === true) {
symbol = '🟢'; // 在线
} else if (server.online === false) {
symbol = '🔴'; // 离线
}
const label = list.addText(`${symbol} ${server.title}`);
label.font = Font.boldSystemFont(12);
label.textColor = Color.white();
}
function addFooter(list, lastUpdate) {
list.addSpacer();
const footer = list.addText(`Last refresh: ${lastUpdate}`);
footer.font = Font.mediumSystemFont(8);
footer.textColor = Color.white();
}
const widget = await createWidget();
if (!config.runsInWidget) {
await widget.presentSmall();
}
Script.setWidget(widget);
Script.complete();
@MrTheFirst Thanks, this is a great extension to the initial script. Would you mind if I adopt your notification functionality in the gist?