Skip to content

Instantly share code, notes, and snippets.

@ab-c-d
Last active June 26, 2022 05:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ab-c-d/5834dce004dbb400317314cb06a64c53 to your computer and use it in GitHub Desktop.
Save ab-c-d/5834dce004dbb400317314cb06a64c53 to your computer and use it in GitHub Desktop.
디시인사이드 디시콘 자동 추가 & 정렬 스크립트

디시인사이드 디시콘 자동 추가 & 정렬 스크립트

디시인사이드 계정에 자주 사용하는 디시콘을 일괄적으로 구매하고 특정 순서로 정렬하기 위한 스크립트이다.

사용법

  1. 브라우저에서 https://dccon.dcinside.com/ 주소를 연다.
  2. 개발자 도구를 열고 console을 연다. 단축키: Ctrl + Shift + J
  3. dccon.js 를 복붙한 후 엔터를 눌러 실행
  4. 아래 코드에서 디시콘 목록을 원하는 목록으로 바꾸어 입력한 후 엔터를 눌러 실행
// 디시콘 3개를 구매하는 예제 (정렬은 하지 않음)
DCCon.buy(["켈시 꼴받는콘2", "바들바들 블아동물콘", "찌그러진페페하이재킹"])
// 디시콘 3개를 주어진 순서대로 정렬하는 예제 (필요시 구매하며 다른 디시콘은 사용 안함으로 설정됨)
DCCon.buyAndSort(["켈시 꼴받는콘2", "바들바들 블아동물콘", "찌그러진페페하이재킹"])

주의

  • DCCon 함수의 인자로 주어진 순서로 디시콘이 정렬됨.
  • 디시콘 제작자들이 이름 중복을 피하기 위해 이름 중간에 보이지 않는 유니코드 문자를 삽입한 경우가 있음. 따라서 디시콘 이름을 직접 입력하지 말고 항상 디시콘 상세페이지에서 복사+붙여넣기 하는 것을 추천함.
const DCCon = (() => {
const MAX_RETRY_ATTEMPT = 10;
const domParser = new DOMParser();
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
};
function doAjax(data, url, type = 'POST') {
return new Promise((success, error) => {
$.ajax({ data: { ci_t: get_cookie('ci_c'), ...data }, type, url, cache: false, success, error });
});
}
async function getDetail(package_idx) {
try {
return await doAjax({ package_idx, code: '' }, '/index/package_detail');
} catch (e) {
return null;
}
}
async function getID(name) {
const searchHTML = await doAjax(undefined, '/hot/1/title/' + encodeURIComponent(name), 'GET');
const doc = domParser.parseFromString(searchHTML, "text/html");
for (let li of doc.querySelectorAll('li.div_package')) {
let package_idx = li.getAttribute('package_idx');
let title = li.getElementsByClassName('dcon_name')[0]?.textContent;
if (!name.startsWith(title)) continue;
const detail = await getDetail(package_idx);
if (!detail) continue;
const parsed = JSON.parse(detail);
if (parsed?.info?.title === name) {
return parsed.info.package_idx;
}
}
return null;
}
async function addByID(package_idx) {
let attempt = MAX_RETRY_ATTEMPT;
let lastError;
while (attempt--) {
try {
return await doAjax({ package_idx }, '/index/buy');
} catch (e) {
lastError = e;
await sleep(1000);
}
}
console.error(lastError);
throw new Error("디시콘을 구매할 수 없습니다.")
}
function setOrder(arr_idx) {
return doAjax({ arr_idx, 'list_opt': 'use' }, '/my/save_setting');
}
async function buyBulkByName(order) {
const arr_idx = [];
const promises = order.map(async (name, i) => {
var package_idx = await getID(name);
if (!package_idx) throw new Error(`디시콘을 찾을 수 없습니다.`);
arr_idx[i] = package_idx;
await addByID(package_idx);
console.log(name + " 구매 완료");
})
const op = await Promise.allSettled(promises);
for (let i = 0, l = op.length; i < l; i++) {
if (op[i].status === "rejected") {
console.error(order[i] + " " + op[i].reason);
}
}
return arr_idx;
}
async function buyAndSortBulkByName(order) {
const arr_idx = await buyBulkByName(order);
const sortApiResponse = await setOrder(arr_idx);
if (sortApiResponse !== 'ok') {
console.error(sortApiResponse);
}
}
function wrap(fn) {
return async function(...args) {
let now = performance.now();
await fn(...args);
console.log("완료, " + (performance.now() -now) + "ms 소요됨");
}
}
return {
buyAndSort: wrap(buyAndSortBulkByName),
buy: wrap(buyBulkByName)
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment