Greasy Fork is available in English.

Company Helper

description

// ==UserScript==
// @name         Company Helper
// @namespace    namespace
// @version      0.5.1
// @description  description
// @author       tos
// @match        *.torn.com/companies.php*
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// ==/UserScript==

const apiKey = 'YOUR_API_KEY'

const torn_api = async (args) => {
  const a = args.split('.')
  if (a.length!==3) throw(`Bad argument in torn_api(args, key): ${args}`)
  return new Promise((resolve, reject) => {
    GM_xmlhttpRequest ( {
      method: "POST",
      url: `https://api.torn.com/${a[0]}/${a[1]}?selections=${a[2]}&key=${apiKey}`,
      headers: {
        "Content-Type": "application/json"
      },
      onload: (response) => {
          try {
            const resjson = JSON.parse(response.responseText)
            resolve(resjson)
          } catch(err) {
            reject(err)
          }
      },
      onerror: (err) => {
        reject(err)
      }
    })
  })
}

GM_addStyle(`
  .last_action_icon {
    cursor: pointer;
    vertical-align: middle;
    display: inline-block;
    background-image: url(/images/v2/sidebar_icons_desktop_2017.png);
    background-repeat: no-repeat;
    background-position-y: -783px;
    width: 34px;
    height: 30px;
  }
  .last-action {
    cursor: pointer;
    width: 103px;
    padding-left: 10px;
    margin-top: -1px;
    position: relative;
    float: left;
    height: 33px;
    line-height: 33px;
    border-left: 1px solid #fff;
    border-right: 1px solid #ccc;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .la_pointer {
    cursor: pointer;
  }

  .employees_alert {
    background-color: #f8e0da;
    border-radius: 0px 5px 5px 0px;
    color: red;
    font-weight: bold;
    width: 60%;
  }
  .trains_alert {
    background-color: #d7e1cc;
    border-radius: 0px 5px 5px 0px;
    color: green;
    font-weight: bold;
    width: 60%;
  }
  .eff_alert {
    background: #f8e0da !important;
  }

  .employee_idle {
    color: #e39500;
  }
  .employee_away {
    color: red;
  }
`)

function company_details() {
  const detailsUL = document.querySelector('.company-stats-list.company-info')
  const total_employees = parseInt(detailsUL.querySelector('.total-employees').innerText)
  const limit_employees = parseInt(detailsUL.querySelector('.limit-employees').innerText)
  if (total_employees < limit_employees) detailsUL.children[0].children[3].classList.add('employees_alert')
  const trains = detailsUL.querySelector('.trains')
  const max_trains = parseInt(trains.nextSibling.nodeValue.replace('/', ''))
  let rating = 0
  for (const star of detailsUL.querySelector('.company-rating').children) star.classList.contains('active') ? rating += 1 : null
  if (parseInt(trains.innerText) + rating >= max_trains) trains.parentNode.classList.add('trains_alert')
  torn_api(`company..employees`).then((res) => {
    const employee = res.company_employees
    let maxEff = true
    for (const i in employee) if (employee[i].effectiveness < 5) maxEff = false
    if (!maxEff) document.querySelector('.company-tabs').children[1].classList.add('eff_alert')
  })
}

const toggle_last_action = (n) => {
  while (n && !n.querySelector('.stats')) {n = n.parentNode}
  const statsDIV = n.querySelector('.stats')
  const lastActionDIV = n.querySelector('.last-action')
  const employeeID = lastActionDIV.getAttribute('data-employeeID')
  statsDIV.classList.toggle('hide')
  lastActionDIV.classList.toggle('hide')
  if (lastActionDIV.classList.contains('hide')) lastActionDIV.innerHTML = '<img src="/images/v2/main/ajax-loader.gif">'
  else torn_api(`user.${employeeID}.profile`).then((res) => {
    lastActionDIV.innerHTML = res.last_action.relative
    if (res.last_action.relative.includes('day')) {
      lastActionDIV.classList.add('employee_idle')
      if (parseInt(res.last_action.relative.split(' ')[0]) > 2) lastActionDIV.classList.replace('employee_idle', 'employee_away')
    }
  })
}

const toggleLastActionALL = (statsTitle, employeeUL) => {
  if (statsTitle.innerText === 'Stats (M/I/E)') {
    statsTitle.childNodes[0].nodeValue = 'Last Action'
    for (const i of employeeUL.querySelectorAll('.stats')) i.classList.add('hide')
    for (const j of employeeUL.querySelectorAll('.last-action')) j.classList.remove('hide')
    for (const unloaded of employeeUL.querySelectorAll('.last-action img')) {
      const lastActionDIV = unloaded.parentNode
      const employeeID = lastActionDIV.getAttribute('data-employeeID')
      torn_api(`user.${employeeID}.profile`).then((res) => {
        lastActionDIV.innerHTML = res.last_action.relative
        if (res.last_action.relative.includes('day')) {
          lastActionDIV.classList.add('employee_idle')
          if (parseInt(res.last_action.relative.split(' ')[0]) > 2) lastActionDIV.classList.replace('employee_idle', 'employee_away')
        }
      })
    }
  }
  else {
    statsTitle.childNodes[0].nodeValue = 'Stats (M/I/E)'
    for (const i of employeeUL.querySelectorAll('.last-action')) i.classList.add('hide'), i.innerHTML = '<img src="/images/v2/main/ajax-loader.gif">'
    for (const j of employeeUL.querySelectorAll('.stats')) j.classList.remove('hide')
  }
}

const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
      if ( node.tagName && node.tagName === 'FORM') {
        switch (node.action) {
          case 'https://www.torn.com/companies.php?step=employees&update=true':
            const statsTitle = node.querySelector('.employee-list-title .stats')
            const employeeUL = node.querySelector('.employee-list')
            statsTitle.insertAdjacentHTML('beforeend', `<i class="last_action_icon right"></i>`)
            statsTitle.querySelector('.last_action_icon').addEventListener('click', () => { toggleLastActionALL(statsTitle, employeeUL) })
            for (const employeeLI of employeeUL.children) {
              const statsDIV = employeeLI.querySelector('.stats')
              const employeeID = employeeLI.getAttribute('data-user')
              statsDIV.classList.add('la_pointer')
              statsDIV.insertAdjacentHTML('afterend', `<div class="last-action hide" data-employeeID="${employeeID}"><img src="/images/v2/main/ajax-loader.gif"></div>`)
              const lastActionDIV = statsDIV.parentNode.querySelector('.last-action')
              statsDIV.addEventListener('click', (e) => {toggle_last_action(e.target)})
              lastActionDIV.addEventListener('click', (e) => {toggle_last_action(e.target)})
            }
            break
          default:
            console.log(node.action)
            break
        }
      }
    }
  }
});

const wrapper = document.querySelector('.company-wrap')
observer.observe(wrapper, { subtree: true, childList: true })
company_details()