neutron6663 / Shiki List Comparison

// ==UserScript==
// @name         Shiki List Comparison
// @namespace    https://shikimori.me/
// @version      1.0.3
// @description  Показывает какое аниме или какая манга, есть у вас в списке вместе с каким-то пользователем, зайдя в список аниме или манги в профиле пользователя.
// @match        *://shikimori.org/*
// @match        *://shikimori.one/*
// @match        *://shikimori.me/*
// @icon         https://shikimori.me/favicon.ico
// @author       neutron6663
// @updateURL    https://openuserjs.org/meta/neutron6663/Shiki_List_Comparison.meta.js
// @downloadURL  https://openuserjs.org/install/neutron6663/Shiki_List_Comparison.user.js
// @copyright    2023, neutron6663 (https://openuserjs.org/users/neutron6663)
// @license      MIT
// ==/UserScript==

function getUserId(myId = true) {
  let id;
  if (myId) {
    id = $('body').data('user').id;
  }
  else {
    if ($('#profiles_show').length) {
      id = $('#profiles_show .profile-head').data('userId');
    }
    else {
      const rate_url = $('.user_rate').data('rate_url');
      $.ajax({
        url: `https://shikimori.me/api/v2/user_rates/${rate_url.substring(rate_url.lastIndexOf('/')+1)}`,
        success: function (result) {
          if (result.isOk == false) console.log('Что-то пошло не так, при попытке получить id пользователя.');
          id = result.user_id;
        },
        async: false
      });
    }
  }
  return id;
}

function getList(userId) {
  let path = location.pathname.split('/');
  let titleType = path[3] == 'anime' ? 'Anime' : 'Manga';
  let allEntries = [];
  $.ajax({
    url: `https://shikimori.me/api/v2/user_rates?target_type=${titleType}&user_id=${userId}`,
    success: function (result) {
      if (result.isOk == false) console.log('Что-то пошло не так, при попытке получить список пользователя.');
      else {
        allEntries = result;
      }
    },
    async: false
  });
  return allEntries;
}

function compareList(aId, bId) {
  const aList = getList(aId);
  const bList = getList(bId);
  const comparedList = [];

  $.each(aList, function (index, aEntry) {
    const cEntry = bList.find(bEntry => bEntry.target_id == aEntry.target_id);
    if (!cEntry) return;
    cEntry.my_status = aEntry.status;
    comparedList.push(cEntry);
  });
  return comparedList;
}

function getVisibleEntries(list) {
  const visibleEntries = []
  $.each(list, function (index, entry) {
    const visibleEntryEl = $(".entries").find("[data-target_id='" + entry.target_id + "']")[0];
    if (!visibleEntryEl) return;
    entry.element = visibleEntryEl;
    visibleEntries.push(entry);
  });
  return visibleEntries;
}

function addVisibilityDifference(entry) {
  const element = $(entry.element);
  if (element.hasClass('compared-' + entry.my_status)) return;
  element.addClass('compared-' + entry.my_status);

  element.find('.rewatches').after($('<span>', {
    class: 'my-status',
    html: $('.b-options-floated.mylist').find(`[data-id=${entry.my_status}]`).text().split(String.fromCharCode(160))[0]
  }))
}

function property(key, value) {
  return `\t${key}: ${value};`;
}

function getCustomStyle(selectors, ...properties) {
  return selectors.join(', ') + ' {\n' + properties.join('\n') + '\n}'
}

function addCustomCss(id, ...styles) {
  $('#custom_css').before($('<style id="' + id + '">' + styles.join('\n\n') + '</style>'));
}

function getComparedStyle() {
  const styles = []
  styles.push(getCustomStyle(['.compared-planned .my-status', '.compared-watching .my-status', '.compared-rewatching .my-status', '.compared-completed .my-status', '.compared-on_hold .my-status', '.compared-dropped .my-status'],
      property('display', 'inline-block'),
      property('vertical-align', 'top'),
      property('padding', '0 6px'),
      property('margin', '0.0625rem 0 0 0.5rem'),
      property('border-radius', '2px'),
      property('box-shadow', 'inset 0 0 0 1px'),
      property('font-size', '11px'),
      property('white-space', 'nowrap'),
      property('text-transform', 'lowercase'),
      property('float', 'right')
    ),
    getCustomStyle(['.compared-planned .my-status'],
      property('color', '#ef8d50')
    ),
    getCustomStyle(['.compared-watching .my-status'],
      property('color', '#4f91e8')
    ),
    getCustomStyle(['.compared-rewatching .my-status'],
      property('color', '#4f91e8')
    ),
    getCustomStyle(['.compared-completed .my-status'],
      property('color', '#66bb6a')
    ),
    getCustomStyle(['.compared-on_hold .my-status'],
      property('color', '#549db3')
    ),
    getCustomStyle(['.compared-dropped .my-status'],
      property('color', '#ef5350')
    )
  );
  return styles;
}

function initialize() {
  if (!$('#user_rates_index').length || getUserId() == getUserId(false) || !getUserId()) return;
  const list = compareList(getUserId(), getUserId(false));

  $.each(getVisibleEntries(list), function (index, entry) {
    addVisibilityDifference(entry);
  });

  $('.list-groups').on("DOMNodeInserted", function (event) {
    if (!$(event.target).hasClass('entries') && !$(event.target).hasClass('list-lines')) return;
    $.each(getVisibleEntries(list), function (index, entry) {
      addVisibilityDifference(entry);
    });
  });

  addCustomCss('compared_style', ...getComparedStyle());

  if ($('style#custom_css').text().includes('shiki-theme.web.app//main.css')) {
    const shikiThemeByGrin3671 = () => {
      return getCustomStyle(['.compared-planned .my-status', '.compared-watching .my-status', '.compared-rewatching .my-status', '.compared-completed .my-status', '.compared-on_hold .my-status', '.compared-dropped .my-status'],
        property('display', 'inline-block'),
        property('vertical-align', 'top'),
        property('padding', '2px 6px'),
        property('margin', '0.0625rem 0 0 0.5rem'),
        property('border-radius', '2px'),
        property('box-shadow', 'inset 0 0 0 1px'),
        property('font-size', '12px'),
        property('font-weight', 'bold'),
        property('white-space', 'nowrap'),
        property('text-transform', 'capitalize'),
      );
    }
    addCustomCss('compared_style_shikiTheme', shikiThemeByGrin3671());
  }
}

function ready(fn) {
  document.addEventListener('page:load', fn);
  document.addEventListener('turbolinks:load', fn);
  if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") fn();
  else document.addEventListener('DOMContentLoaded', fn);
}

ready(initialize);