Facebook
From Lousy Capybara, 3 Years ago, written in JavaScript.
This paste is a reply to RevampedComment from LO - go back
Embed
Viewing differences between RevampedComment and Re: RevampedComment
// ==UserScript==
// @name        Arca.RevampedCommentSection
// @namespace   Arca.RevampedCommentSection
// @author      자바
// @description 아카라이브 댓글 목록 개선 프로젝트
// @version     1.0.3
// @include     https://arca.live/*
// @include     https://*.arca.live/*
// @run-at      document-ready
// @grant       GM_addStyle
// ==/UserScript==

GM_addStyle(/*css*/`
  .comment-wrapper.fold > .comment-wrapper {
    display: none;
  }

  .comment-wrapper.foldable > .comment-item .info-row {
    cursor: pointer;
  }

  .comment-wrapper.foldable > .comment-item .folder {
    font-family: monospace;
    font-weight: bold;
  }
  .comment-wrapper.foldable > .comment-item .folder:after {
    content: "[-]";
  }
  .comment-wrapper.fold > .comment-item .folder:after {
    content: "[+]";
  }
`)

/**
 * 댓글 요소에서 삭제 버튼을 찾습니다
 * @param {HTMLElement} comment
 * @returns {HTMLElement}
 */
function findDeleteAnchor (comment) {
  for (let anchor of comment.querySelectorAll('a')) {
    if (anchor.textContent.trim() === '삭제') {
      return anchor
    }
  }
}

/**
 * 타래 삭제 버튼을 눌렀을 때 실행될 메소드
 * @this {HTMLElement}
 * @param {MouseEvent} e
 */
function onDeleteClick (e) {
  e.preventDefault()

  // 삭제할 댓글 아이디 가져오기
  const parent = this.closest('.comment-wrapper')
  const comments = [ parent, ...parent.querySelectorAll('.comment-wrapper') ]

  // 정말 삭제할건지 물어보기
  if (!confirm(`정말 해당 댓글과 답글 ${comments.length - 1}개를 제거하시겠습니까?`)) {
    return
  }

  const promises = []
  const errors = []

  for (let comment of comments) {
    const anchor = findDeleteAnchor(comment)

    if (anchor) {
      promises.push(
        fetch(anchor.href, {
          method: 'POST',
          headers: {'Content-type': 'application/x-www-form-urlencoded'},
          body: `_csrf=${document.querySelector('input[name=_csrf]').value}`
        }).catch(e => errors.push(e))
      )
    }
  }

  return Promise.all(promises)
    .finally(() => {
      if (errors.length) {
        const error = errors.map((e, idx) => ` ${idx}: ${e.message}`).join('\n')
        alert(`댓글 삭제 중 ${errors.length}개의 오류가 발생했습니다\n${error}`)
      }

      location.reload()
    })
}

/**
 * 타래 접기 버튼을 눌렀을 때 실행될 메소드
 * @this {HTMLElement}
 * @param {MouseEvent} e 
 */
function onFolderClick (e) {
  if (!e.target.matches('a, button')) {
    const command = this.closest('.comment-wrapper')
    command.classList.toggle('fold')
  }
}

const deleteBtnTemplate = document.createElement('a')
deleteBtnTemplate.href = '#'
deleteBtnTemplate.innerHTML = `
  
  전체삭제
`

const folderBtnTemplate = document.createElement('span')
folderBtnTemplate.classList.add('folder')

// 답글이 있는 댓글만 모두 불러오기
for (let comment of document.querySelectorAll('.comment-wrapper')) {
  if (!comment.querySelector(':scope > .comment-wrapper')) {
    continue
  }

  // 삭제 권한이 있다면 전체 삭제 버튼 추가하기
  const anchor = findDeleteAnchor(comment)
  if (anchor) {
    const button = deleteBtnTemplate.cloneNode(true)
    button.addEventListener('click', onDeleteClick)

    anchor.parentElement.insertBefore(button, anchor)
    anchor.parentElement.insertBefore(
      document.createTextNode('\u00A0|\u00A0'), anchor)
  }
  
  // 댓글 접는 버튼 추가하기
  const folder = folderBtnTemplate.cloneNode(true)
  const info = comment.querySelector('.info-row')
  info.prepend(folder)
  info.addEventListener('click', onFolderClick)
  comment.classList.add('foldable')
  
  // 3개 이상 댓글이 있다면 접은 상태로 만들기
  if (comment.querySelectorAll('.comment-wrapper').length > 3) {
    folder.click()
  }
}

// 선택된 댓글이 있다면 모두 펼치기
if (location.hash) {
  for (let comment of document.querySelectorAll(`${location.hash}, ${location.hash} .comment-wrapper`)) {
    comment.classList.remove('fold')
  }
}