148 lines
6.0 KiB
JavaScript
148 lines
6.0 KiB
JavaScript
let allCountries = [];
|
||
let selectedCountries = [];
|
||
const $ = (id) => document.getElementById(id);
|
||
function send(type, payload = {}) {
|
||
return chrome.runtime.sendMessage({ type, payload }).then((res) => {
|
||
if (!res?.ok) throw new Error(res?.error || '操作失败');
|
||
return res;
|
||
});
|
||
}
|
||
function setStatus(text, isError = false) {
|
||
$('status').textContent = text;
|
||
$('status').style.color = isError ? '#fca5a5' : '#a7f3d0';
|
||
}
|
||
function normalizeCountry(country) {
|
||
const id = Math.floor(Number(country?.id));
|
||
return { id, label: String(country?.label || `Country #${id}`).trim() };
|
||
}
|
||
function sameCountry(a, b) { return Number(a?.id) === Number(b?.id); }
|
||
function renderSelected() {
|
||
const box = $('selected-countries');
|
||
box.innerHTML = '';
|
||
selectedCountries.forEach((country, index) => {
|
||
const chip = document.createElement('span');
|
||
chip.className = 'chip';
|
||
chip.textContent = `${index + 1}. ${country.label} #${country.id}`;
|
||
const close = document.createElement('button');
|
||
close.type = 'button';
|
||
close.textContent = '×';
|
||
close.addEventListener('click', () => { selectedCountries = selectedCountries.filter((x) => !sameCountry(x, country)); renderAll(); });
|
||
chip.appendChild(close);
|
||
box.appendChild(chip);
|
||
});
|
||
}
|
||
function renderCountryList() {
|
||
const keyword = $('country-search').value.trim().toLowerCase();
|
||
const list = $('country-list');
|
||
list.innerHTML = '';
|
||
allCountries
|
||
.filter((c) => !keyword || String(c.id).includes(keyword) || c.label.toLowerCase().includes(keyword))
|
||
.slice(0, 120)
|
||
.forEach((country) => {
|
||
const btn = document.createElement('button');
|
||
btn.type = 'button';
|
||
btn.className = 'country-item' + (selectedCountries.some((x) => sameCountry(x, country)) ? ' selected-item' : '');
|
||
btn.innerHTML = `<span>${country.label}</span><span class="country-id">#${country.id}</span>`;
|
||
btn.addEventListener('click', () => {
|
||
if (selectedCountries.some((x) => sameCountry(x, country))) {
|
||
selectedCountries = selectedCountries.filter((x) => !sameCountry(x, country));
|
||
} else {
|
||
selectedCountries.push(country);
|
||
}
|
||
renderAll();
|
||
});
|
||
list.appendChild(btn);
|
||
});
|
||
}
|
||
function renderAll() { renderSelected(); renderCountryList(); }
|
||
function collectSettings() {
|
||
return {
|
||
apiKey: $('api-key').value.trim(),
|
||
baseUrl: $('base-url').value.trim(),
|
||
serviceCode: $('service-code').value.trim(),
|
||
minPrice: $('min-price').value.trim(),
|
||
maxPrice: $('max-price').value.trim(),
|
||
countries: selectedCountries,
|
||
};
|
||
}
|
||
async function saveSettings() {
|
||
const res = await send('SAVE_SETTINGS', collectSettings());
|
||
selectedCountries = res.settings.countries.map(normalizeCountry);
|
||
renderAll();
|
||
setStatus('设置已保存');
|
||
}
|
||
async function fillCurrentTab(phoneNumber) {
|
||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||
if (!tab?.id) throw new Error('没有找到当前标签页。');
|
||
try {
|
||
await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['content.js'] });
|
||
} catch {}
|
||
const res = await chrome.tabs.sendMessage(tab.id, { type: 'FILL_PHONE', phoneNumber });
|
||
if (!res?.ok) throw new Error(res?.error || '填入页面失败。');
|
||
return res;
|
||
}
|
||
async function copyText(text) {
|
||
try { await navigator.clipboard.writeText(text); } catch {}
|
||
}
|
||
async function fetchAndFill(options = {}) {
|
||
$('fetch-fill').disabled = true;
|
||
try {
|
||
await saveSettings();
|
||
const releaseAction = options.releaseAction || 'cancel';
|
||
setStatus(releaseAction === 'ban' ? '正在释放被拒号码并按低价拿号...' : '正在取消上一个激活并按低价拿号...');
|
||
const res = await send('FETCH_NEXT_PHONE', { reason: options.reason || 'manual_replace', releaseAction });
|
||
const phone = res.activation.phoneNumber;
|
||
await copyText(phone);
|
||
setStatus('正在填入当前页面输入框...');
|
||
await fillCurrentTab(phone);
|
||
$('current-phone').textContent = phone;
|
||
$('current-id').textContent = res.activation.activationId;
|
||
setStatus(`已获取、已复制、已填入:${phone}`);
|
||
} catch (error) {
|
||
setStatus(error.message || String(error), true);
|
||
} finally {
|
||
$('fetch-fill').disabled = false;
|
||
}
|
||
}
|
||
async function cancelActive() {
|
||
try {
|
||
setStatus('正在取消当前激活...');
|
||
await send('CANCEL_ACTIVE');
|
||
$('current-phone').textContent = '无';
|
||
$('current-id').textContent = '无';
|
||
setStatus('当前激活已取消');
|
||
} catch (error) { setStatus(error.message || String(error), true); }
|
||
}
|
||
async function refreshCountries() {
|
||
try {
|
||
await saveSettings();
|
||
setStatus('正在刷新国家列表...');
|
||
const res = await send('FETCH_COUNTRIES');
|
||
allCountries = res.countries.map(normalizeCountry).filter((c) => c.id >= 0);
|
||
renderAll();
|
||
setStatus('国家列表已刷新');
|
||
} catch (error) { setStatus(error.message || String(error), true); }
|
||
}
|
||
async function init() {
|
||
const res = await send('GET_SETTINGS');
|
||
const settings = res.settings;
|
||
$('api-key').value = settings.apiKey || '';
|
||
$('base-url').value = settings.baseUrl || '';
|
||
$('service-code').value = settings.serviceCode || 'dr';
|
||
$('min-price').value = settings.minPrice || '';
|
||
$('max-price').value = settings.maxPrice || '';
|
||
selectedCountries = (settings.countries || []).map(normalizeCountry);
|
||
allCountries = (res.fallbackCountries || []).map(normalizeCountry);
|
||
if (settings.activeActivation) {
|
||
$('current-phone').textContent = settings.activeActivation.phoneNumber || '无';
|
||
$('current-id').textContent = settings.activeActivation.activationId || '无';
|
||
}
|
||
$('save').addEventListener('click', saveSettings);
|
||
$('fetch-fill').addEventListener('click', () => fetchAndFill({ reason: 'manual_replace', releaseAction: 'cancel' }));
|
||
$('cancel-active').addEventListener('click', cancelActive);
|
||
$('refresh-countries').addEventListener('click', refreshCountries);
|
||
$('country-search').addEventListener('input', renderCountryList);
|
||
renderAll();
|
||
}
|
||
init().catch((error) => setStatus(error.message || String(error), true));
|