User: как в этом коде уменьшить кол-во вызовов checkCorruptUrl
  var tmdb_proxy = {
    name: 'TMDB Proxy',
    version: '1.0.1',
    description: 'Проксирование постеров и API сайта TMDB',
    path_image: 'https://apn.ndst.pw/v1?url=https://image.tmdb.org/',
    path_api: 'https://apn.ndst.pw/v1?url=https://api.themoviedb.org/3/',
    stb_path_image: 'https://stream.ndst.pw/tmdb/img/',
    stb_path_api: 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/tmdb/api/3/'
  };
  var lastApiUrl = null;
  var lastImageUrl = null;
  //https:// - 8
  function filter_url(u, base) {
    var s = u.slice(0, base.length);
    var e = u.slice(base.length).replace(/\/+/g, '/');
    return s + e;
  }
  function checkCorruptUrl(base, url, type) {
    var stb;
    if (type === "api") {
      stb = tmdb_proxy.stb_path_api;
    } else if (type === "img") {
      stb = tmdb_proxy.stb_path_image;
    } else {
      stb = base;
    }
    var chekUrl = base + url;
    var xhrC = new XMLHttpRequest();
    xhrC.open('GET', chekUrl, true);
    xhrC.timeout = 2000;
    xhrC.onreadystatechange = function () {
      if (xhrC.readyState === 4) {
        var finalUrl;
        if (xhrC.status >= 200 && xhrC.status < 300) {
          finalUrl = base;
        } else {
          finalUrl =  stb;
        }
        if (type === "api") {
          lastApiUrl = finalUrl;
        } else if (type === "img") {
          lastImageUrl = finalUrl;
        }
      }
    };
    xhrC.ontimeout = function () {
      if (type === "api") {
        lastApiUrl = stb;
      } else if (type === "img") {
        lastImageUrl = stb;
      }
    };
    xhrC.send();
  }

  Lampa.TMDB.image = function (url) {
    var base = filter_url(tmdb_proxy.stb_path_image + url, tmdb_proxy.stb_path_image);
    if (url.indexOf("kinopoiskapiunofficial.tech") !== -1) {
      return url.replace('t/p/w500/', '');
    }
    checkCorruptUrl(tmdb_proxy.path_image, url, "img");
    return (lastImageUrl ? filter_url(lastImageUrl + url, lastImageUrl) : base)
  };

  Lampa.TMDB.api = function (url) {
    var base = filter_url(tmdb_proxy.stb_path_api + url, tmdb_proxy.stb_path_api);
    if (url.indexOf("apn.ndst.pw") !== -1) {
      var urlStartIndex = url.indexOf('?url=') + '?url='.length;
      var streamUrl = decodeURIComponent(url.substring(urlStartIndex));
      if (streamUrl && streamUrl.indexOf("https://stream.ndst.pw/ndi/aisearch") === 0) {
        var params = streamUrl.split('?')[1];
        if (params) {
          var paramPairs = params.split('&');
          var newParams = [];
          for (var i = 0; i < paramPairs.length; i++) {
            var pair = paramPairs[i];
            var equalIndex = pair.indexOf('=');
            if (equalIndex !== -1) {
              var paramName = decodeURIComponent(pair.substring(0, equalIndex));
              var paramValue = decodeURIComponent(pair.substring(equalIndex + 1));
              if (paramName === 'deviceid' || paramName === 'query') {
                newParams.push(paramName + '=' + paramValue);
              }
            }
          }
          var finalUrl = 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/ndi/aisearch?' + newParams.join('&');
          return finalUrl;
        }
      }
    }
    checkCorruptUrl(tmdb_proxy.path_api, url, "api");
    return (lastApiUrl ? filter_url(lastApiUrl + url, lastApiUrl) : base)
  };

  Lampa.Settings.listener.follow('open', function (e) {
    if (e.name == 'tmdb') {
      e.body.find('[data-parent="proxy"]').remove();
    }
  });
  console.log('TMDB-Proxy', 'started, enabled:', Lampa.Storage.field('proxy_tmdb'));
Assistant: Чтобы уменьшить количество вызовов функции `checkCorruptUrl`, вы можете использовать кеширование, а также оптимизировать логику вызовов. Например, можно проверять URL на наличие специфичных условий перед вызовом, чтобы избежать лишних запросов, если некоторые условия уже выполнены. Вы можете использовать флаги (например, `isImageChecked` и `isApiChecked`), чтобы отслеживать, был ли уже сделан запрос для проверки URL. Вот как это можно сделать:

```javascript
var tmdb_proxy = {
  name: 'TMDB Proxy',
  version: '1.0.1',
  description: 'Проксирование постеров и API сайта TMDB',
  path_image: 'https://apn.ndst.pw/v1?url=https://image.tmdb.org/',
  path_api: 'https://apn.ndst.pw/v1?url=https://api.themoviedb.org/3/',
  stb_path_image: 'https://stream.ndst.pw/tmdb/img/',
  stb_path_api: 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/tmdb/api/3/'
};
var lastApiUrl = null;
var lastImageUrl = null;
var isImageChecked = false; // флаг для проверки изображений
var isApiChecked = false; // флаг для проверки API

function filter_url(u, base) {
  var s = u.slice(0, base.length);
  var e = u.slice(base.length).replace(/\/+/g, '/');
  return s + e;
}

function checkCorruptUrl(base, url, type) {
  var stb;
  if (type === "api") {
    stb = tmdb_proxy.stb_path_api;
  } else if (type === "img") {
    stb = tmdb_proxy.stb_path_image;
  } else {
    stb = base;
  }
  var chekUrl = base + url;
  var xhrC = new XMLHttpRequest();
  xhrC.open('GET', chekUrl, true);
  xhrC.timeout = 2000;
  xhrC.onreadystatechange = function () {
    if (xhrC.readyState === 4) {
      var finalUrl;
      if (xhrC.status >= 200 && xhrC.status < 300) {
        finalUrl = base;
      } else {
        finalUrl = stb;
      }
      if (type === "api") {
        lastApiUrl = finalUrl;
        isApiChecked = true; // установка флага проверки API
      } else if (type === "img") {
        lastImageUrl = finalUrl;
        isImageChecked = true; // установка флага проверки изображений
      }
    }
  };
  xhrC.ontimeout = function () {
    if (type === "api") {
      lastApiUrl = stb;
      isApiChecked = true; // установка флага при таймауте
    } else if (type === "img") {
      lastImageUrl = stb;
      isImageChecked = true; // установка флага при таймауте
    }
  };
  xhrC.send();
}

Lampa.TMDB.image = function (url) {
  var base = filter_url(tmdb_proxy.stb_path_image + url, tmdb_proxy.stb_path_image);
  if (url.indexOf("kinopoiskapiunofficial.tech") !== -1) {
    return url.replace('t/p/w500/', '');
  }

  if (!isImageChecked) {
    checkCorruptUrl(tmdb_proxy.path_image, url, "img");
  }

  return (lastImageUrl ? filter_url(lastImageUrl + url, lastImageUrl) : base);
};

Lampa.TMDB.api = function (url) {
  var base = filter_url(tmdb_proxy.stb_path_api + url, tmdb_proxy.stb_path_api);
  if (url.indexOf("apn.ndst.pw") !== -1) {
    var urlStartIndex = url.indexOf('?url=') + '?url='.length;
    var streamUrl = decodeURIComponent(url.substring(urlStartIndex));
    if (streamUrl && streamUrl.indexOf("https://stream.ndst.pw/ndi/aisearch") === 0) {
      var params = streamUrl.split('?')[1];
      if (params) {
        var paramPairs = params.split('&');
        var newParams = [];
        for (var i = 0; i < paramPairs.length; i++) {
          var pair = paramPairs[i];
          var equalIndex = pair.indexOf('=');
          if (equalIndex !== -1) {
            var paramName = decodeURIComponent(pair.substring(0, equalIndex));
            var paramValue = decodeURIComponent(pair.substring(equalIndex + 1));
            if (paramName === 'deviceid' || paramName === 'query') {
              newParams.push(paramName + '=' + paramValue);
            }
          }
        }
        var finalUrl = 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/ndi/aisearch?' + newParams.join('&');
        return finalUrl;
      }
    }
  }

  if (!isApiChecked) {
    checkCorruptUrl(tmdb_proxy.path_api, url, "api");
  }

  return (lastApiUrl ? filter_url(lastApiUrl + url, lastApiUrl) : base);
};

Lampa.Settings.listener.follow('open', function (e) {
  if (e.name == 'tmdb') {
    e.body.find('[data-parent="proxy"]').remove();
  }
});

console.log('TMDB-Proxy', 'started, enabled:', Lampa.Storage.field('proxy_tmdb'));
```

### Объяснение изменений:
1. **Флаги проверки**: Я добавил два флага (`isImageChecked` и `isApiChecked`), чтобы отслеживать, было ли уже выполнено обращение к `checkCorruptUrl` для изображений и API.
2. **Логика вызова**: Я добавил условие для вызовов `checkCorruptUrl`, чтобы они выполнялись только в том случае, если они ещё не были выполнены.

Таким образом, если один и тот же метод вызывается несколько раз подряд с одинаковыми параметрами, вы избежите лишних сетевых запросов, что повысит производительность вашего кода.
User: а для isImageChecked и isApiChecked можем сделать какой-то таймаут в 500мс к примеру чтобы проверять актуальность проверки
Assistant: , вы можете реализовать таймаут для проверки актуальности флагов `isImageChecked` и `isApiChecked`. Этот подход позволит вам повторно вызывать `checkCorruptUrl`, если прошло определенное время (например, 500 мс), с момента последнего вызова проверки. 

Вот как вы можете это сделать:

1. Используйте `setTimeout` для сброса флагов через 500 мс после успешной проверки.
2. Вызывайте `checkCorruptUrl`, если флаги устарели.

Вот обновленный код с таймаутом для флагов:

```javascript
var tmdb_proxy = {
  name: 'TMDB Proxy',
  version: '1.0.1',
  description: 'Проксирование постеров и API сайта TMDB',
  path_image: 'https://apn.ndst.pw/v1?url=https://image.tmdb.org/',
  path_api: 'https://apn.ndst.pw/v1?url=https://api.themoviedb.org/3/',
  stb_path_image: 'https://stream.ndst.pw/tmdb/img/',
  stb_path_api: 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/tmdb/api/3/'
};
var lastApiUrl = null;
var lastImageUrl = null;
var isImageChecked = false; // флаг для проверки изображений
var isApiChecked = false; // флаг для проверки API
var imageCheckTimeout; // таймаут для сброса флага проверки изображений
var apiCheckTimeout; // таймаут для сброса флага проверки API

function filter_url(u, base) {
  var s = u.slice(0, base.length);
  var e = u.slice(base.length).replace(/\/+/g, '/');
  return s + e;
}

function checkCorruptUrl(base, url, type) {
  var stb;
  if (type === "api") {
    stb = tmdb_proxy.stb_path_api;
  } else if (type === "img") {
    stb = tmdb_proxy.stb_path_image;
  } else {
    stb = base;
  }
  var chekUrl = base + url;
  var xhrC = new XMLHttpRequest();
  xhrC.open('GET', chekUrl, true);
  xhrC.timeout = 2000;
  xhrC.onreadystatechange = function () {
    if (xhrC.readyState === 4) {
      var finalUrl;
      if (xhrC.status >= 200 && xhrC.status < 300) {
        finalUrl = base;
      } else {
        finalUrl = stb;
      }
      if (type === "api") {
        lastApiUrl = finalUrl;
        isApiChecked = true; // установка флага проверки API
        resetApiCheck(); // сброс таймаута проверки API
      } else if (type === "img") {
        lastImageUrl = finalUrl;
        isImageChecked = true; // установка флага проверки изображений
        resetImageCheck(); // сброс таймаута проверки изображений
      }
    }
  };
  xhrC.ontimeout = function () {
    if (type === "api") {
      lastApiUrl = stb;
      isApiChecked = true; // установка флага при таймауте
      resetApiCheck(); // сброс таймаута проверки API
    } else if (type === "img") {
      lastImageUrl = stb;
      isImageChecked = true; // установка флага при таймауте
      resetImageCheck(); // сброс таймаута проверки изображений
    }
  };
  xhrC.send();
}

function resetImageCheck() {
  clearTimeout(imageCheckTimeout);
  imageCheckTimeout = setTimeout(() => {
    isImageChecked = false; // сброс флага проверки изображений после 500 мс
  }, 500);
}

function resetApiCheck() {
  clearTimeout(apiCheckTimeout);
  apiCheckTimeout = setTimeout(() => {
    isApiChecked = false; // сброс флага проверки API после 500 мс
  }, 500);
}

Lampa.TMDB.image = function (url) {
  var base = filter_url(tmdb_proxy.stb_path_image + url, tmdb_proxy.stb_path_image);
  if (url.indexOf("kinopoiskapiunofficial.tech") !== -1) {
    return url.replace('t/p/w500/', '');
  }

  // Вызов проверки изображений или повторная проверка после таймаута
  if (!isImageChecked) {
    checkCorruptUrl(tmdb_proxy.path_image, url, "img");
  }

  return (lastImageUrl ? filter_url(lastImageUrl + url, lastImageUrl) : base);
};

Lampa.TMDB.api = function (url) {
  var base = filter_url(tmdb_proxy.stb_path_api + url, tmdb_proxy.stb_path_api);
  if (url.indexOf("apn.ndst.pw") !== -1) {
    var urlStartIndex = url.indexOf('?url=') + '?url='.length;
    var streamUrl = decodeURIComponent(url.substring(urlStartIndex));
    if (streamUrl && streamUrl.indexOf("https://stream.ndst.pw/ndi/aisearch") === 0) {
      var params = streamUrl.split('?')[1];
      if (params) {
        var paramPairs = params.split('&');
        var newParams = [];
        for (var i = 0; i < paramPairs.length; i++) {
          var pair = paramPairs[i];
          var equalIndex = pair.indexOf('=');
          if (equalIndex !== -1) {
            var paramName = decodeURIComponent(pair.substring(0, equalIndex));
            var paramValue = decodeURIComponent(pair.substring(equalIndex + 1));
            if (paramName === 'deviceid' || paramName === 'query') {
              newParams.push(paramName + '=' + paramValue);
            }
          }
        }
        var finalUrl = 'https://apn.ndst.pw/v1?url=https://stream.ndst.pw/ndi/aisearch?' + newParams.join('&');
        return finalUrl;
      }
    }
  }

  // Вызов проверки API или повторная проверка после таймаута
  if (!isApiChecked) {
    checkCorruptUrl(tmdb_proxy.path_api, url, "api");
  }

  return (lastApiUrl ? filter_url(lastApiUrl + url, lastApiUrl) : base);
};

Lampa.Settings.listener.follow('open', function (e) {
  if (e.name == 'tmdb') {
    e.body.find('[data-parent="proxy"]').remove();
  }
});

console.log('TMDB-Proxy', 'started, enabled:', Lampa.Storage.field('proxy_tmdb'));
```

### Объяснение изменений:
1. **Таймаут для сброса флагов**:
   - Я добавил функции `resetImageCheck` и `resetApiCheck`, которые устанавливают таймаут для сброса соответствующих флагов через 500 мс после успешной проверки URL.
   - Используются переменные `imageCheckTimeout` и `apiCheckTimeout` для отслеживания активных таймаутов.

2. **Проверка на устаревание**:
   - При вызове функций `Lampa.TMDB.image` и `Lampa.TMDB.api` проверяется значение флагов; если надо, делается новый запрос `checkCorruptUrl`.

Это сделает ваш код более гибким и позволит более эффективно управлять проверками.
User: мы можем что-то еще сделать?
Assistant: