로고조성현

카카오스토리 완전백업

역사의 집대성

우선 설정에 들어가서 아카이브를 다운로드해둔다. 그렇게 해야지만 사진이 백업된다.

그 다음 다음 코드를 콘솔에서 구동한다. 자동으로 맨 아래까지 스크롤해준다.

function scrollToBottomOfInfiniteScroll() {
  let lastHeight = 0
  let timer = setInterval(() => {
    window.scrollTo(0, document.documentElement.scrollHeight)

    let currentHeight = document.documentElement.scrollHeight
    if (currentHeight === lastHeight) {
      clearInterval(timer)
      console.log('Reached the bottom or new content is not loading.')
    } else {
      lastHeight = currentHeight
    }
  }, 2000) // 2000 milliseconds (or 2 seconds) between each scroll attempt
}

scrollToBottomOfInfiniteScroll()

그 다음 이를 실행한다.

async function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

async function clickAndWaitForFeed(elementToClick) {
  return new Promise((resolve) => {
    const feedObserver = new MutationObserver((mutations, observer) => {
      for (let mutation of mutations) {
        if (mutation.type === 'childList' && document.querySelector('.feed')) {
          observer.disconnect()
          resolve()
        }
      }
    })

    feedObserver.observe(document.body, { childList: true, subtree: true })

    elementToClick.click()
  })
}

async function downloadTextContent(filename, content) {
  const blob = new Blob([content], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)

  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.style.display = 'none'
  document.body.appendChild(a)

  a.click()

  URL.revokeObjectURL(url)
  document.body.removeChild(a)
}

async function waitForElement(selector) {
  return new Promise((resolve) => {
    const element = document.querySelector(selector)
    if (element) {
      resolve(element)
      return
    }

    const observer = new MutationObserver((mutations, observerInstance) => {
      const foundElement = document.querySelector(selector)
      if (foundElement) {
        observerInstance.disconnect()
        resolve(foundElement)
      }
    })

    observer.observe(document.body, { childList: true, subtree: true })
  })
}

async function processActivity(activity) {
  const linkPost = activity.querySelector('._linkPost')
  if (!linkPost) return

  await clickAndWaitForFeed(linkPost)
  await delay(5000) // Adjusted delay to 5 seconds

  const cover = await waitForElement('#cover')

  const btnShowFirstComment = cover.querySelector('._btnShowFirstComment')
  btnShowFirstComment?.click()

  await delay(5000) // Adjusted delay to 5 seconds

  const timeValue = cover.querySelector('.time').innerText
  downloadTextContent(`${timeValue}.txt`, cover.innerText)
}

async function main() {
  const activities = document.querySelectorAll('._activity')
  for (let activity of activities) {
    await processActivity(activity)
  }
}

main()