diff --git a/totamjung/js/background.js b/totamjung/js/background.js index 9f64ddc4..0fa6d800 100644 --- a/totamjung/js/background.js +++ b/totamjung/js/background.js @@ -27,6 +27,27 @@ const isValidQueryNo = num => { return false; } +const getRandomDefenseResult = async (searchQuery) => { + try { + const response = await fetch(`https://solved.ac/api/v3/search/problem?query=${searchQuery}&sort=random`); + + if (!response.ok) { + return {result: 'FETCH_FAILED', statusCode: response.status}; + } + + const responseText = await response.text(); + const chosenProblem = JSON.parse(responseText).items[0]; + + if (!chosenProblem) { + return {result: 'NO_SEARCH_RESULT'}; + } + + return {result: 'OK', chosenProblem: chosenProblem}; + } catch (error) { + return {result: 'SYSTEM_CRASHED'}; + } +}; + chrome.runtime.onInstalled.addListener(details => { if (details.reason === 'install') { setData('algorithm', [1, 2]); @@ -94,18 +115,28 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { } }); } - else if (message.msg === 'getDefenseQuery') { + else if (message.msg === 'getDefenseResult') { const no = message.no; + let searchQuery; chrome.storage.sync.get('query', loaded => { loaded = loaded.query; - - if (loaded && no === -1 && loaded.selectedNo && !loaded[loaded.selectedNo].isEmpty) - sendResponse({ 'result': 'OK', 'query': loaded[loaded.selectedNo].query }); - else if (loaded && loaded[no] && !loaded[no].isEmpty) - sendResponse({ 'result': 'OK', 'query': loaded[no].query }); - else - sendResponse({ 'result': 'FAIL' }); + + if (loaded && no === -1 && loaded.selectedNo && !loaded[loaded.selectedNo].isEmpty) { + searchQuery = loaded[loaded.selectedNo].query; + } else if (loaded && loaded[no] && !loaded[no].isEmpty) { + searchQuery = loaded[no].query; + } else { + sendResponse({ result: 'NO_QUERY' }); + return true; + } + + searchQuery = encodeURIComponent(searchQuery); + + getRandomDefenseResult(searchQuery) + .then(requestResult => { + sendResponse(requestResult); + }); }); } else if (message.msg === 'logQueryHistory') { diff --git a/totamjung/js/widget.js b/totamjung/js/widget.js index 149efe75..369fe527 100644 --- a/totamjung/js/widget.js +++ b/totamjung/js/widget.js @@ -302,59 +302,62 @@ function createRandomButtonListener() { function doRandomDefense(key) { const diceImagePath = chrome.runtime.getURL('images/dice.png'); - chrome.runtime.sendMessage({ msg: 'getDefenseQuery', no: key }, (res) => { - res.query = encodeURIComponent(res.query); - - if (res.result === 'FAIL') { - if (key === -1) { // 직접 버튼을 눌러 랜디를 돌린 경우에만 메시지 표시 - showPopup('해당 슬롯이 아직 비어 있습니다.
[설정]에서 선택하신 슬롯에 추첨을 만들어 주세요!', diceImagePath); + chrome.runtime.sendMessage({ msg: 'getDefenseResult', no: key }, (res) => { + if (res.result === 'FETCH_FAILED') { + switch (res.statusCode) { + case 400: + showPopup('잘못된 쿼리를 입력하셨습니다.
쿼리 확인 후 다시 시도해 주시겠어요?', diceImagePath); + break; + case 429: + showPopup('너무 많은 추첨을 돌렸습니다.
잠시 후 다시 시도해 주시겠어요?', diceImagePath); + break; + case 500: + case 503: + showPopup('API 서버에 문제가 생겨, 문제 정보를 받아오지 못 했습니다.
잠시 후 다시 시도해 주시겠어요?', diceImagePath); + default: + showPopup(`문제가 발생했습니다. 응답 코드는 ${res.statusCode} 입니다.
계속해서 문제가 발생하면 개발자에게 문의해 주세요.`, diceImagePath) } + + isRandomBusy = false; return; } - - const xhr = new XMLHttpRequest(); - xhr.open('GET', `https://solved.ac/api/v3/search/problem?query=${res.query}&sort=random`); - xhr.send(); - - xhr.onload = () => { - if (xhr.status === 400) { - showPopup('잘못된 쿼리를 입력하셨습니다.
쿼리 확인 후 다시 시도해 주시겠어요?', diceImagePath); - isRandomBusy = false; - return; - } - - if (xhr.status === 429) { - showPopup('너무 많은 추첨을 돌렸습니다.
잠시 후 다시 시도해 주시겠어요?', diceImagePath); - isRandomBusy = false; - return; - } - - if (xhr.status === 500 || xhr.status === 503) { - showPopup('서버에 문제가 생겨, 문제 정보를 받아오지 못 했습니다.
잠시 후 다시 시도해 주시겠어요?', diceImagePath); - isRandomBusy = false; - return; - } - - const chosen = JSON.parse(xhr.responseText).items[0]; - if (chosen) { - - chrome.runtime.sendMessage({ - msg: 'logQueryHistory', - data: { - no: chosen.problemId, - tier: ((chosen.isLevelLocked && chosen.level === 0) ? 31 : chosen.level), - title: chosen.titleKo, - date: getFullDate() - } - }); - - location.href = `https://acmicpc.net/problem/${chosen.problemId}`; - } - else { - showPopup('검색된 문제가 없습니다.
쿼리 확인 후 다시 시도해 주시겠어요?', diceImagePath); - isRandomBusy = false; + + if (res.result === 'SYSTEM_CRASHED') { + showPopup(`알 수 없는 문제가 발생했습니다.
계속해서 문제가 발생하면 개발자에게 문의해 주세요.`, diceImagePath); + + isRandomBusy = false; + return; + } + + if (res.result === 'NO_SEARCH_RESULT') { + showPopup('검색된 문제가 없습니다.
쿼리 확인 후 다시 시도해 주시겠어요?', diceImagePath); + + isRandomBusy = false; + return; + } + + if (res.result === 'NO_QUERY') { + if (key === -1) { // 직접 버튼을 눌러 랜디를 돌린 경우에만 메시지 표시 + showPopup('해당 슬롯이 아직 비어 있습니다.
[설정]에서 선택하신 슬롯에 추첨을 만들어 주세요!', diceImagePath); } + + isRandomBusy = false; + return; } + + const chosenProblem = res.chosenProblem; + + chrome.runtime.sendMessage({ + msg: 'logQueryHistory', + data: { + no: chosenProblem.problemId, + tier: ((chosenProblem.isLevelLocked && chosenProblem.level === 0) ? 31 : chosenProblem.level), + title: chosenProblem.titleKo, + date: getFullDate() + } + }); + + location.href = `https://acmicpc.net/problem/${chosenProblem.problemId}` }); } @@ -562,6 +565,7 @@ onkeydown = onkeyup = (e) => { isPressed[e.key] = e.type === 'keydown'; if (!isNaN(e.key) && isPressed['Alt'] && !isRandomBusy) { isRandomBusy = true; + doRandomDefense(e.key); } } \ No newline at end of file diff --git a/totamjung/manifest.json b/totamjung/manifest.json index f4319817..b8d86e71 100644 --- a/totamjung/manifest.json +++ b/totamjung/manifest.json @@ -1,11 +1,14 @@ { "name": "토탐정", "description": "[BOJ-Extension] 알고리즘 분류 가리개 & 랜덤 디펜스, 토탐정!", - "version": "1.1.1.2", + "version": "1.1.1.3", "manifest_version": 3, "permissions": [ "storage" ], + "host_permissions": [ + "https://solved.ac/api/v3/search/*" + ], "background": { "service_worker": "js/background.js" },