Skeb Price Sorter

Adds a option to sort skeb users by price.

// ==UserScript==
// @name         Skeb Price Sorter
// @namespace    http://tampermonkey.net/
// @version      0.3.1
// @description  Adds a option to sort skeb users by price.
// @author       Zappo
// @match        https://*.skeb.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=skeb.jp
// @grant        GM_xmlhttpRequest
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    var token = localStorage.getItem('token');

    function has_price(element) {
        return element.querySelector('.sph-price');
    }

    function get_price(user, element, callback) {
        if (has_price(element)) {
            return;
        }
        GM.xmlHttpRequest({
            url: 'https://skeb.jp/api/users/' + user,
            headers: {
                'Authorization': 'Bearer ' + token
            },
            onload: function(response) {
                try {
                    var data = JSON.parse(response.responseText);
                    var price = data.skills.filter(skill => skill.genre === 'art')[0].default_amount;
                    response.context(price);
                } catch (error) {
                    console.log('Fetch price error: ' + error);
                }
            },
            context: callback
        });
    }

    function add_price_to_user_list(element, price) {
        var price_element = document.createElement('div');
        price_element.textContent = price;
        price_element.classList.add('title', 'is-7', 'sph-price');
        price_element.style.color = 'red';
        element.querySelector('.title').parentElement.querySelector('.image').append(price_element);
    }

    function add_price_to_profile_table(element, price) {
        var price_row = document.createElement('tr');
        price_row.classList.add('sph-price');
        var price_td1 = document.createElement('td');
        price_td1.textContent = 'Artwork (past price)';
        price_row.append(price_td1);
        var price_td2 = document.createElement('td');
        price_td2.textContent = price;
        price_row.append(price_td2);
        element.querySelector('table tbody').prepend(price_row);
    }

    function get_for_all() {
        Array.from(document.querySelectorAll("a[href^='/@'][aria-label]"))
            .filter(el => !has_price(el))
            .forEach(el => get_price(el.href.substring(el.href.indexOf('@') + 1), el, price => add_price_to_user_list(el, price)));
    }

    function get_current_user_price(table) {
        var user_name = window.location.pathname.replace('/@', '');
        get_price(user_name, table, price => add_price_to_profile_table(table, price));
    }

    function get_element_price(element) {
        try {
            return parseInt(element.querySelector('.sph-price').textContent);
        } catch (error) {
            return Infinity;
        }
    }

    function sort_users() {
        var element = document.querySelector('.columns.has-cards');
        if (!element) {
            return;
        }
        Array.from(element.children)
            .sort((a, b) => get_element_price(a) - get_element_price(b))
            .forEach((el, i) => (el.style.order = i));
    }

    function create_button(text, action) {
        var button = document.createElement('button');
        button.classList.add('button', 'is-primary', 'is-fullwidth', 'sph-buttom');
        button.textContent = text;
        button.onclick = action;
        return button;
    }

    function add_sort_buttons() {
        var element = document.querySelector('.creatorSort');
        if (!element || element.parentElement.querySelector('.sph-buttom')) {
            return;
        }
        element.parentElement.append(create_button('Get prices', get_for_all));
        element.parentElement.append(create_button('Sort users', sort_users));
    }

    function add_past_price_button() {
        if (!window.location.pathname.startsWith('/@')) {
            return;
        }
        var button = Array.from(document.querySelectorAll('.button'))
            .filter(el => el.textContent === 'Notify on seeking started' || el.textContent === 'Notification reserved')
            .filter(el => !el.parentElement.querySelector('.sph-buttom'));
        if (!button.length) {
            return;
        }
        button = button[0];
        button.parentElement.append(create_button('Get past price', () => get_current_user_price(button.parentElement.parentElement.parentElement)));
    }

    function add_button() {
        add_sort_buttons();
        add_past_price_button();
    }

    function add_observer() {
        var body = document.body;
        var observer = new MutationObserver(mutations => add_button());
        observer.observe(body, {childList: true, subtree: true});
    }

    add_observer();
})();