neuroalpha 0.5.17 → 0.5.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2026 Roman A. Perepelkin. All rights reserved. Proprietary software.
1
+ // Copyright (c) 2026 Roman A. Perepelkin. All rights reserved. Proprietary software.
2
2
  import { saveCandles, loadCandles, candleRange, kvGet, kvSet } from '../db.js';
3
3
  import { DAY, MSK } from '../util.js';
4
4
 
@@ -119,16 +119,17 @@ export async function ensureCandles(symbol, interval, fromTs, tillTs, { signal,
119
119
  const mskDate = new Date(now + MSK);
120
120
  const mskDow = mskDate.getUTCDay();
121
121
  const mskHour = mskDate.getUTCHours();
122
- const isTradingHours = mskDow >= 1 && mskDow <= 5 && mskHour >= 9 && mskHour < 24;
123
- const checkCooldownMs = isTradingHours ? 8 * 60000 : 4 * 3600000;
124
- const dbIsAlreadyFresh = (now - range.max < 15 * 60000) || (!isTradingHours && now - range.max < 18 * 3600000);
122
+ const mskMins = mskHour * 60 + mskDate.getUTCMinutes();
123
+ const isTradingHours = mskDow >= 1 && mskDow <= 5 && mskMins >= 6 * 60 + 50 && mskHour < 24;
124
+ const checkCooldownMs = isTradingHours ? 4 * 60000 : 4 * 3600000;
125
+ const dbIsAlreadyFresh = (now - range.max < 10 * 60000) || (!isTradingHours && now - range.max < 18 * 3600000);
125
126
 
126
127
  if (!dbIsAlreadyFresh && range.max < Math.min(tillTs, now) - barMs(interval) && (now - lastCheck >= checkCooldownMs)) {
127
128
  // Записываем время проверки хвоста ВСЕГДА (даже если новых свечей у бумаги на бирже ещё не появилось),
128
129
  // чтобы не опрашивать MOEX ISS по всем 100 бумагам каждые 2 минуты!
129
130
  lastTailCheckAt.set(tailKey, now);
130
131
  kvSet(pKey, { v: 2, fromTs: Math.min(fromTs, probe?.v === 2 ? probe.fromTs : range.min), tailCheckedAt: now });
131
- await fetchCandles(symbol, interval, tsToDate(range.max), tillTs < now ? tsToDate(tillTs) : null, {
132
+ await fetchCandles(symbol, interval, tsToDate(range.max), tillTs < now - DAY ? tsToDate(tillTs) : null, {
132
133
  signal,
133
134
  onBatch: (page) => saveCandles(symbol, interval, page),
134
135
  });
package/server/db.js CHANGED
@@ -205,7 +205,7 @@ if (!db.prepare('SELECT id FROM users WHERE id = 1').get()) {
205
205
  } else {
206
206
  // Общеизвестный код привязки владельца заменяется на случайный (привязанные ранее чаты сохраняются)
207
207
  db.prepare("UPDATE users SET notify_code = ? WHERE id = 1 AND (notify_code IS NULL OR notify_code = '' OR UPPER(notify_code) = 'NA-OWNER1')").run(randomNotifyCode());
208
- db.prepare(`UPDATE users SET plan = 'owner' WHERE id = 1 AND role = 'admin' AND plan IN ('free', 'pro')`).run();
208
+ db.prepare(`UPDATE users SET plan = 'owner', plan_until = 0 WHERE id = 1 AND role = 'admin' AND plan <> 'owner'`).run();
209
209
  db.prepare("UPDATE users SET name = 'Пользователь' WHERE id = 1 AND name = 'Владелец платформы'").run();
210
210
  }
211
211
  db.exec('CREATE UNIQUE INDEX IF NOT EXISTS users_api_key ON users(api_key) WHERE api_key IS NOT NULL');
package/server/index.js CHANGED
@@ -128,9 +128,9 @@ app.get('/admin', (req, res) => {
128
128
  return res.sendFile(path.join(ROOT, 'public', 'admin.html'));
129
129
  });
130
130
  app.get('/', (req, res, next) => {
131
- // Неавторизованным гостям показывается лендинг со входом (витрина PaaS),
132
- // а авторизованным пользователям открывается их изолированный облачный терминал (или витрина при ?landing=1)
133
- if (!req.user || (process.env.CLOUD_MODE === '1' && req.query.landing === '1')) {
131
+ // На центральном сервере (IS_CENTRAL) у клиентов на главном домене работает витрина и Личный кабинет (с биллингом и переходом на их PaaS-машину),
132
+ // а локальный торговый терминал самого центра открывается только для администратора (или в dev/instance режиме)
133
+ if (!req.user || (process.env.CLOUD_MODE === '1' && req.query.landing === '1') || (IS_CENTRAL && (req.user.role !== 'admin' || req.query.payment_check === '1') && req.query.terminal !== '1')) {
134
134
  return res.sendFile(path.join(ROOT, 'public', 'landing.html'));
135
135
  }
136
136
  setAppCsp(res);