팁과 노하우 게시판

10추글

모바일 상단 메뉴

본문 페이지

[일반] 로아 플레이타임 + 결제정보 확인 코드(수정)

디그당
댓글: 206 개
조회: 79549
추천: 45
2025-05-06 00:20:29
- 좀 더 개선 -
디자인을 위해 코드 가독성 폭망

로아 플레이타임 + 결제 확인 코드

누구나 다 알겠지만, 둘을 합쳐 봄

LOST ARK의 결제만이 아닌
STOVE의 총 결제 내역 총합입니다 


사용법 
1. 로스트아크 공식 홈페이지 로그인

2. F12 눌러서 Console 탭 클릭

3. 코드 붙혀넣기 엔터

4. 만약 안되면(오류) allow pasting 엔터 후 붙혀넣기

[ 코드 입력 후 알림 창 뜨면 자동으로 내용의 텍스트가 복사 됩니다. ]



(() => {
  const getStoveCookie = (name) => {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    return parts.length === 2 ? parts.pop().split(";").shift() : null;
  };

  const formatCurrency = (amount) => {
    const numStr = String(amount);
    const units = ["", "천원", "만원", "십만원", "백만원", "천만원", "억원", "십억원", "백억원", "천억원"];

    if (numStr.length <= 3) {
      return numStr + units[0];
    }

    let result = "";
    let remainder = amount;

    if (numStr.length > 8) {
      const billions = Math.floor(remainder / 100000000);
      if (billions > 0) {
        result += billions + "";
        remainder = remainder % 100000000;
      }
    }

    if (numStr.length > 4) {
      const millions = Math.floor(remainder / 10000);
      if (millions > 0) {
        result += millions + "";
        remainder = remainder % 10000;
      }
    }

    if (remainder > 0) {
      const thousands = Math.floor(remainder / 1000);
      if (thousands > 0) {
        result += thousands + "";
        remainder = remainder % 1000;
      }
    }

    if (remainder > 0) {
      result += remainder + " ";
    }

    return result + "";
  };

  const loginUserToken = getStoveCookie("SUAT");

  fetch("https://api.onstove.com/game/v2.0/member/logs", {
    method: "GET",
    headers: {
      Authorization: `Bearer ${loginUserToken}`,
      "Content-Type": "application/json",
    },
  })
    .then((response) => {
      if (response.status === 200) {
        return response.json();
      } else {
        throw new Error("로그인 정보가 없습니다.");
      }
    })
    .then((data) => {
      const lostArkGame = data.value.find((game) => game.game_name === "LOST ARK");
      const playTimeMinutes = lostArkGame.play_time;

      const totalHours = Math.floor(playTimeMinutes / 60);
      const remainingMinutes = playTimeMinutes % 60;
      const totalDays = Math.floor(totalHours / 24);
      const remainingHours = totalHours % 24;
      const totalMonths = Math.floor(totalDays / 30);
      const totalYears = Math.floor(totalMonths / 12);
      const remainingMonths = totalMonths % 12;

      let lastNum = 1;
      let sum = 0;
      let regexp = /B(?=(d{3})+(?!d))/g;
      let chargeDateList = [];
      let chargeWayList = [];
      let cashList = [];
      let paymentMethods = {};
      let paymentCount = 0;
      let text = "";
      let years = [2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026];

      function getCashData(year, page) {
        return new Promise((resolve, reject) => {
          $.ajax({
            url: "/Cash/GetChargeList",
            type: "GET",
            data: { Page: page, StartDate: year + ".01.01", EndDate: year + ".12.31" },
            dataType: "html",
            success: resolve,
            error: reject,
          });
        });
      }

      function getPageCount(year) {
        return new Promise((resolve, reject) => {
          $.ajax({
            url: "/Cash/GetChargeList",
            type: "GET",
            data: { Page: 1, StartDate: year + ".01.01", EndDate: year + ".12.31" },
            dataType: "html",
            success: resolve,
            error: reject,
          });
        });
      }

      async function processAllYears() {
        for (let j = 0; j < years.length; j++) {
          try {
            const year = years[j];
            const pageData = await getPageCount(year);

            const pageNumElement = $(pageData).find(".pagination__last")[0];
            if (pageNumElement && pageNumElement.getAttribute("onClick")) {
              lastNum = pageNumElement.getAttribute("onClick").replace(/[^0-9]/g, "");
            } else {
              lastNum = 1;
            }

            for (let i = 1; i <= lastNum; i++) {
              const data = await getCashData(year, i);

              $(data)
                .find("td.list__price")
                .each(function () {
                  cashList.push(
                    $(this)
                      .text()
                      .replace(/[^0-9]/g, "")
                  );
                  paymentCount++;
                });

              $(data)
                .find("td.list__date")
                .each(function () {
                  chargeDateList.push($(this).text());
                });

              $(data)
                .find("td.list__way")
                .each(function () {
                  const method = $(this).text();
                  chargeWayList.push(method);

                  if (!paymentMethods[method]) {
                    paymentMethods[method] = 0;
                  }

                  const index = chargeWayList.length - 1;
                  if (index < cashList.length) {
                    paymentMethods[method] += Number(cashList[index]);
                  }
                });
            }
          } catch (error) {
            console.error(`Error processing year ${years[j]}:`, error);
          }
        }

        cashList.forEach(function (cash) {
          sum += Number(cash);
        });

        const formattedSum = formatCurrency(sum);

        let paymentMethodsAnalysis =
          "<h3 style='color: #333; margin: 20px 0 12px 0; font-size: 18px; font-weight: 600;'>결제 방법별 분석</h3><ul style='list-style-type: none; padding: 0; margin: 8px 0;'>";
        for (const [method, amount] of Object.entries(paymentMethods)) {
          if (amount > 0) {
            paymentMethodsAnalysis += "<li><strong>" + method + ":</strong> " + formatCurrency(amount) + "</li>";
          }
        }
        paymentMethodsAnalysis += "</ul>";

        const messageHTML = `
          <div style="margin-bottom: 20px;">
            <h3 style="color: #333; margin: 0 0 12px 0; font-size: 18px; font-weight: 600;">로스트아크 플레이 시간</h3>
            <p style="margin: 8px 0; font-size: 16px;">총 플레이 시간: ${totalHours}시간 ${remainingMinutes}분</p>
            <p style="margin: 8px 0; font-size: 16px;">총 일 수: ${totalDays}${remainingHours}시간</p>
            <p style="margin: 8px 0; font-size: 16px;">총 개월 수: ${totalMonths}개월</p>
            <p style="margin: 8px 0; font-size: 16px;">총 년 수: ${totalYears}${remainingMonths}개월</p>
          </div>
         
          <div>
            <h3 style="color: #333; margin: 0 0 12px 0; font-size: 18px; font-weight: 600;">로스트아크 결제 정보</h3>
            <p style="margin: 8px 0; font-size: 16px; font-weight: 500;">총 결제 금액: ${formattedSum}</p>
            <p style="margin: 8px 0; font-size: 16px;">총 결제 횟수: ${paymentCount}회</p>
            ${paymentMethodsAnalysis}
          </div>
        `;

        const message =
          `로스트아크 플레이 시간:
총 플레이 시간: ${totalHours}시간 ${remainingMinutes}
총 일 수: ${totalDays}${remainingHours}시간
총 개월 수: ${totalMonths}개월
총 년 수: ${totalYears}${remainingMonths}개월

로스트아크 결제 정보:
총 결제 금액: ${formattedSum}
총 결제 횟수: ${paymentCount}
결제 방법별 분석:
` +
          Object.entries(paymentMethods)
            .filter(([_, amount]) => amount > 0)
            .map(([method, amount]) => method + ": " + formatCurrency(amount))
            .join("n");

        const tempTextArea = document.createElement("textarea");
        tempTextArea.value = message;
        tempTextArea.style.position = "fixed";
        tempTextArea.style.left = "0";
        tempTextArea.style.top = "0";
        tempTextArea.style.opacity = "0";
        document.body.appendChild(tempTextArea);
        tempTextArea.select();
        document.execCommand("copy");
        document.body.removeChild(tempTextArea);

        const modal = document.createElement("div");
        modal.style.position = "fixed";
        modal.style.left = "0";
        modal.style.top = "0";
        modal.style.width = "100%";
        modal.style.height = "100%";
        modal.style.backgroundColor = "rgba(0,0,0,0.7)";
        modal.style.zIndex = "10000";
        modal.style.display = "flex";
        modal.style.justifyContent = "center";
        modal.style.alignItems = "center";

        const modalContent = document.createElement("div");
        modalContent.style.backgroundColor = "white";
        modalContent.style.padding = "25px";
        modalContent.style.borderRadius = "12px";
        modalContent.style.width = "550px";
        modalContent.style.maxWidth = "85%";
        modalContent.style.maxHeight = "85%";
        modalContent.style.overflowY = "auto";
        modalContent.style.fontFamily = "맑은 고딕, 돋움, sans-serif";
        modalContent.style.fontSize = "16px";
        modalContent.style.lineHeight = "1.5";
        modalContent.style.color = "#333";
        modalContent.style.boxShadow = "0 5px 20px rgba(0,0,0,0.2)";

        const modalTitle = document.createElement("h2");
        modalTitle.textContent = "로스트아크 통계";
        modalTitle.style.borderBottom = "1px solid #eee";
        modalTitle.style.paddingBottom = "15px";
        modalTitle.style.marginTop = "0";
        modalTitle.style.marginBottom = "20px";
        modalTitle.style.fontSize = "22px";
        modalTitle.style.fontWeight = "600";
        modalTitle.style.color = "#222";
        modalTitle.style.textAlign = "center";

        const modalBody = document.createElement("div");
        modalBody.innerHTML = messageHTML;
        modalBody.style.margin = "0";
        modalBody.style.lineHeight = "1.6";

        const closeButton = document.createElement("button");
        closeButton.textContent = "닫기";
        closeButton.style.padding = "10px 24px";
        closeButton.style.backgroundColor = "#4CAF50";
        closeButton.style.color = "white";
        closeButton.style.border = "none";
        closeButton.style.borderRadius = "6px";
        closeButton.style.cursor = "pointer";
        closeButton.style.float = "right";
        closeButton.style.marginTop = "20px";
        closeButton.style.fontSize = "16px";
        closeButton.style.fontWeight = "500";
        closeButton.style.transition = "background-color 0.2s";
        closeButton.onmouseover = function () {
          this.style.backgroundColor = "#3e8e41";
        };
        closeButton.onmouseout = function () {
          this.style.backgroundColor = "#4CAF50";
        };
        closeButton.onclick = function () {
          document.body.removeChild(modal);
        };

        modalContent.appendChild(modalTitle);
        modalContent.appendChild(modalBody);
        modalContent.appendChild(closeButton);
        modal.appendChild(modalContent);
        document.body.appendChild(modal);

        console.log("통계가 복사되었습니다. 필요시 붙여넣기 하시면 됩니다.");
      }

      processAllYears();
    })
    .catch((error) => {
      console.error(error);
      alert("에러가 발생했습니다: " + error.message);
    });
})();

모바일 게시판 하단버튼

댓글

새로고침
새로고침

모바일 게시판 하단버튼

지금 뜨는 인벤

더보기+

모바일 게시판 리스트

모바일 게시판 하단버튼

글쓰기

모바일 게시판 페이징

최근 HOT한 콘텐츠

  • 로아
  • 게임
  • IT
  • 유머
  • 연예
AD