fix: рынок читает новый формат базы (shops+listings), живые источники первыми

#3
by Iosteps - opened
Files changed (1) hide show
  1. assets/market.js +46 -23
assets/market.js CHANGED
@@ -58,6 +58,15 @@
58
  return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c];
59
  });
60
  }
 
 
 
 
 
 
 
 
 
61
  function money(n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ' '); }
62
  function catName(c) { return CATS[c] || c || 'Прочее'; }
63
 
@@ -165,50 +174,64 @@
165
  if (lot) lot.classList.toggle('open');
166
  });
167
 
168
- var SOURCES = [
169
- 'assets/vendors.json',
170
  'https://dfo.spaceghosts.com/vendors.json',
171
  'https://api.allorigins.win/raw?url=' + encodeURIComponent('https://dfo.spaceghosts.com/vendors.json'),
172
  'https://api.codetabs.com/v1/proxy?quest=' + encodeURIComponent('https://dfo.spaceghosts.com/vendors.json')
173
  ];
174
 
175
- function fetchFirst(urls) {
176
- var p = Promise.reject(new Error('no sources'));
177
- urls.forEach(function (u) {
178
- p = p.catch(function () {
179
- return fetch(u, { cache: 'no-store' }).then(function (r) {
180
- if (!r.ok) throw new Error('HTTP ' + r.status);
181
- return r.json();
182
- });
183
- });
184
  });
 
 
 
 
 
185
  return p;
186
  }
187
 
188
- function startData(json, live) {
189
- data = json;
 
 
 
 
 
 
 
190
  buildControls();
191
- var upd = data.updatedAt ? new Date(data.updatedAt) : null;
192
  document.getElementById('mk-updated').innerHTML =
193
- (live ? 'Рынок онлайн' : 'Снимок рынка') + ': ' + (upd ? upd.toLocaleString('ru-RU', { day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit' }) : '—') +
194
- ' · <button class="mk-refresh" id="mk-refresh" type="button">обновить</button> · данные ' +
195
- '<a href="https://dfo.spaceghosts.com/#vendors" target="_blank" rel="noopener">Daggerfall Watch</a>';
 
196
  var rb = document.getElementById('mk-refresh');
197
  if (rb) rb.addEventListener('click', function () { load(true); });
198
  update();
199
  if (data.refreshMinutes && !load._t) {
200
- load._t = setInterval(function () { load(true); }, Math.max(5, data.refreshMinutes) * 60000);
201
  }
202
  }
203
 
204
  function load(manual) {
205
  var note = document.getElementById('mk-updated');
206
  if (manual && note) note.textContent = 'Обновляю рынок…';
207
- fetchFirst(SOURCES)
208
- .then(function (json) { startData(json, true); })
209
- .catch(function (err) {
210
- listEl.innerHTML = '<p class="note">Не удалось загрузить рынок (' + esc(err.message) +
211
- '). Живые данные — на <a href="https://dfo.spaceghosts.com/#vendors" target="_blank" rel="noopener">dfo.spaceghosts.com</a>.</p>';
 
 
 
 
 
 
212
  });
213
  }
214
 
 
58
  return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c];
59
  });
60
  }
61
+ function norm(raw) {
62
+ return {
63
+ updatedAt: raw.updatedAt,
64
+ refreshMinutes: raw.refreshMinutes || 60,
65
+ listings: raw.listings || [],
66
+ vendors: raw.vendors || raw.shops || [],
67
+ coverage: raw.coverage || null
68
+ };
69
+ }
70
  function money(n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ' '); }
71
  function catName(c) { return CATS[c] || c || 'Прочее'; }
72
 
 
174
  if (lot) lot.classList.toggle('open');
175
  });
176
 
177
+ var LOCAL_SRC = 'assets/vendors.json';
178
+ var LIVE_SOURCES = [
179
  'https://dfo.spaceghosts.com/vendors.json',
180
  'https://api.allorigins.win/raw?url=' + encodeURIComponent('https://dfo.spaceghosts.com/vendors.json'),
181
  'https://api.codetabs.com/v1/proxy?quest=' + encodeURIComponent('https://dfo.spaceghosts.com/vendors.json')
182
  ];
183
 
184
+ function getJson(url) {
185
+ return fetch(url, { cache: 'no-store' }).then(function (r) {
186
+ if (!r.ok) throw new Error('HTTP ' + r.status + ' ' + url);
187
+ return r.json().then(function (j) { return { json: j, url: url }; });
 
 
 
 
 
188
  });
189
+ }
190
+
191
+ function tryChain(urls) {
192
+ var p = Promise.reject(new Error('no sources'));
193
+ urls.forEach(function (u) { p = p.catch(function () { return getJson(u); }); });
194
  return p;
195
  }
196
 
197
+ function fmtUpd(ts) {
198
+ if (!ts) return '—';
199
+ var d = new Date(ts);
200
+ if (isNaN(d.getTime())) return '—';
201
+ return d.toLocaleString('ru-RU', { day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit', second: '2-digit' });
202
+ }
203
+
204
+ function startData(pack, live) {
205
+ data = norm(pack.json);
206
  buildControls();
207
+ var where = live ? ('живьём · ' + pack.url) : 'локальный снимок';
208
  document.getElementById('mk-updated').innerHTML =
209
+ (live ? 'Рынок онлайн' : 'Снимок рынка') + ': ' + fmtUpd(data.updatedAt) +
210
+ ' · <button class="mk-refresh" id="mk-refresh" type="button">обновить</button><br>' +
211
+ '<span class="mk-src">' + esc(where) + ' · каждые ' + (data.refreshMinutes || 60) + ' мин · данные ' +
212
+ '<a href="https://dfo.spaceghosts.com/#vendors" target="_blank" rel="noopener">Daggerfall Watch</a></span>';
213
  var rb = document.getElementById('mk-refresh');
214
  if (rb) rb.addEventListener('click', function () { load(true); });
215
  update();
216
  if (data.refreshMinutes && !load._t) {
217
+ load._t = setInterval(function () { load(false); }, Math.max(5, data.refreshMinutes) * 60000);
218
  }
219
  }
220
 
221
  function load(manual) {
222
  var note = document.getElementById('mk-updated');
223
  if (manual && note) note.textContent = 'Обновляю рынок…';
224
+ // свежие источники первыми; локальный снимок — только страховка
225
+ tryChain(LIVE_SOURCES)
226
+ .then(function (pack) { startData(pack, true); })
227
+ .catch(function (errLive) {
228
+ getJson(LOCAL_SRC)
229
+ .then(function (pack) { startData(pack, false); })
230
+ .catch(function (err) {
231
+ if (note) note.textContent = 'Не удалось загрузить рынок (' + errLive.message + ').';
232
+ listEl.innerHTML = '<p class="note">Не удалось загрузить рынок (' + esc(errLive.message) +
233
+ '). Живые данные — на <a href="https://dfo.spaceghosts.com/#vendors" target="_blank" rel="noopener">dfo.spaceghosts.com</a>.</p>';
234
+ });
235
  });
236
  }
237