Repository navigation
Expand file tree
/
Copy pathscript.js
More file actions
135 lines (113 loc) · 5 KB
/
Copy pathscript.js
File metadata and controls
135 lines (113 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// СПИСОК ИСТОЧНИКОВ (Primary -> Backup -> Proxy)
// Если первый не работает, скрипт пойдет ко второму и так далее.
const API_SOURCES = [
'https://api.warframestat.us/pc', // Официальный API сообщества
'https://api.warframestat.us/pc/?language=en', // То же, но с явным языком (иногда помогает от кеша)
// Прокси через allorigins (обходит блокировки CORS и локальные глюки)
'https://api.allorigins.win/raw?url=' + encodeURIComponent('https://api.warframestat.us/pc')
];
// Функция форматирования времени
function formatTime(ms) {
if (ms < 0) return "00:00:00";
const seconds = Math.floor((ms / 1000) % 60);
const minutes = Math.floor((ms / (1000 * 60)) % 60);
const hours = Math.floor((ms / (1000 * 60 * 60)) % 24);
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
// Умная функция получения данных (перебирает источники)
async function fetchCycleData() {
let data = null;
let errorMsg = '';
// Проходим по списку источников по очереди
for (const source of API_SOURCES) {
try {
console.log(`Trying source: ${source}`);
const response = await fetch(source);
if (!response.ok) throw new Error(`Status: ${response.status}`);
// Пробуем прочитать JSON
const text = await response.text();
if (!text) throw new Error('Empty response');
data = JSON.parse(text);
// Если мы здесь - значит все получилось, выходим из цикла
console.log('Data received successfully from:', source);
break;
} catch (error) {
console.warn(`Failed to fetch from ${source}:`, error);
errorMsg = error.message;
// Цикл продолжится к следующему источнику
}
}
if (data) {
updateUI(data);
} else {
console.error('All sources failed.');
showErrorState();
}
}
// Если все сломалось, пишем ошибку в интерфейс
function showErrorState() {
const ids = ['earth', 'cetus', 'vallis', 'cambion', 'duviri'];
ids.forEach(id => {
const el = document.getElementById(`${id}-state`);
if(el) {
el.innerText = "OFFLINE";
el.style.color = "red";
}
});
}
// Обновление интерфейса
function updateUI(data) {
// 1. Earth
updateTimer('earth', data.earthCycle);
// 2. Cetus
updateTimer('cetus', data.cetusCycle);
// 3. Orb Vallis
updateTimer('vallis', data.vallisCycle);
// 4. Cambion Drift
updateTimer('cambion', data.cambionCycle);
// 5. Duviri (особая логика)
if(data.duviriCycle) {
const stateEl = document.getElementById('duviri-state');
const timerEl = document.getElementById('duviri-timer');
stateEl.innerText = data.duviriCycle.state.toUpperCase();
stateEl.style.color = '#c5a966'; // Duviri gold
timerEl.dataset.expiry = data.duviriCycle.expiry;
}
}
// Вспомогательная функция
function updateTimer(id, cycleData) {
const stateEl = document.getElementById(`${id}-state`);
const timerEl = document.getElementById(`${id}-timer`);
if (cycleData && stateEl && timerEl) {
let stateText = cycleData.state ? cycleData.state.toUpperCase() : 'UNKNOWN';
// Цвета
if(stateText.includes('NIGHT') || stateText === 'COLD' || stateText === 'FASS') {
stateEl.style.color = '#55aaff';
} else {
stateEl.style.color = '#ffaa00';
}
stateEl.innerText = stateText;
timerEl.dataset.expiry = cycleData.expiry;
}
}
// Тикающий таймер (работает локально, не требует запросов каждую секунду)
setInterval(() => {
const timerElements = document.querySelectorAll('[data-expiry]');
timerElements.forEach(el => {
const expiryStr = el.dataset.expiry;
if (!expiryStr) return;
const expiryDate = new Date(expiryStr).getTime();
const now = new Date().getTime();
const diff = expiryDate - now;
if (diff <= 0) {
el.innerText = "SYNC...";
// Не спамим запросами, если данные устарели, ждем следующего цикла обновления
} else {
el.innerText = formatTime(diff);
}
});
}, 1000);
// Запуск
fetchCycleData();
// Обновляем данные с сервера раз в 60 секунд
setInterval(fetchCycleData, 60000);