chendler / Habitica: Party messages

// ==UserScript==
// @name         Habitica: Party messages
// @namespace    https://habitica.com
// @version      0.2
// @description  Habitica: Party messages
// @author       chendler
// @match        https://*.habitica.com/*
// @require      https://code.jquery.com/jquery-3.2.1.slim.min.js
// @license      MIT
// ==/UserScript==

// init interval id
var tInitID;

// My name
var me;
var members = [];

var wikiSearchURL = "http://habitica.wikia.com/wiki/Special:Search?query=";

$(document).ready(function() {
    $(document).on("click", tryToInit);
    tryToInit();

});

// Try inly if not trying now
var isTrying = false;
function tryToInit() {
    if(isTrying) return;
    isTrying = true;

    // set little delayso URL is changed if clicked on navigation
    setTimeout(function(){
        if(top.location.pathname !== "/party") return;
        //console.log("TRY TO INIT..", top.location.pathname);
        tInitID = setInterval(function(){
            console.log("-- Try to init..", top.location.pathname);
            var isAlreadyProcessed = $(".row.processed").length > 0;
            if(isAlreadyProcessed) {
                console.log("-- Already processed");
                window.clearInterval(tInitID);
                isTrying = false;
                return;
            }

            var isChatRow = $(".chat-row").length > 0;
            var isLeader = $(".title-details .leader").length > 0;
            var haveMessages = $(".chat-row .card-body .text.markdown > p").length > 0;
            if( isChatRow && isLeader && haveMessages) init();
        },1000);

    },3000);
}


function init() {
    isTrying = false;
    console.log("=== INIT ===");
    window.clearInterval(tInitID);

    // Leader
    me = $(".title-details .leader").text().replace(":","").trim();
    console.log("My name:", me);

    // Members without leader
    members = [];
    $(".party-members .character-name").each(function(){
        members.push($(this).text());
    });
    members.push(me);
    console.log("Members:", members);

    // Do stuff with chat messages
    chatMessages();

}

function chatMessages() {
    var $rows = $(".card-body .text.markdown > p");

    var daysClass = "today";
    var prevDaysClass = "";

    $rows.each(function(){
        var $msg = $(this);
        var $card = $msg.closest(".card");
        var $row = $card.closest(".row");
        var $rowWrap = $row.parent(); // whole wrapper of one mesage contents
        var s = $msg.text();

        $row.addClass("processed");
        $rowWrap.addClass("row-wrap");

        // Bold usernames
        $.each(members, function(i, val){
            s = s.replace(val, "<b class=username>"+val+"</b>");
        });

        // Time ago
        var timeAgo = $card.find(".time").text();
        if(timeAgo.indexOf("day ago") >= 0) daysClass = "yesterday";
        else if(timeAgo.indexOf("days ago") >= 0) daysClass = "days-ago";
        else if(daysClass != "today") daysClass = "old";
        $card.addClass(daysClass);
        $rowWrap.addClass(daysClass);
        if(prevDaysClass == "today" && daysClass != prevDaysClass) $rowWrap.before("<hr/>");
        prevDaysClass = daysClass;

        // Casts
        var rgx = new RegExp(/casts (.+?) for the party/gi);
        if( rgx.test(s) ) {
            $card.addClass("cast");
            s = s.replace(rgx, "casts <a href='"+wikiSearchURL+"$1' class=wiki target=_blank>$1</a> for the party");
        }

        // Found
        rgx = new RegExp(/found (\d+) (.+?)\./gi);
        if( rgx.test(s) ) {
            $card.addClass("found");
            s = s.replace(rgx, "found <b class='count count-$1'>$1</b> <a href='"+wikiSearchURL+"$2' class=wiki target=_blank>$2</a>.");
        }

        // Damage
        rgx = new RegExp(/\. (.+?) attacks party for (\d+\.\d+) damage\./i);
        if( rgx.test(s) ) {
            $card.addClass("boss");
            s = s.replace(rgx, ". <span class=damage>$1 attacks party for <b class=hp>$2</b> damage.</span>");
        }

        // Attack
        rgx = new RegExp(/^(.+?) attacks (.+?) for (\d+\.\d+) damage\./i);
        if( rgx.test(s) ) {
            $card.addClass("boss");
            s = s.replace(rgx, "<span class=attack>$1 attacks <a href='"+wikiSearchURL+"$2' class=wiki target=_blank>$2</a> for <b class=hp>$3</b> damage.</span><br/>");
        }

        // Start
        rgx = new RegExp(/Your quest, (.+?), has started\./i);
        if( rgx.test(s) ) {
            $card.addClass("start");
            s = s.replace(rgx, "<h4>Your quest, <a href='"+wikiSearchURL+"$1' class=wiki target=_blank>$1</a>, has started.</h4>");
        }

        // Victory: Boss
        rgx = new RegExp(/You defeated (.+?)! Questing party members receive the rewards of victory\./i);
        if( rgx.test(s) ) {
            $card.addClass("victory");
            s = s.replace(rgx, "<h4>You defeated <a href='"+wikiSearchURL+"$1' class=wiki target=_blank>$1</a>!</h4> <div class=desc><i>Questing party members receive the rewards of victory.</i></div>");
        }

        // Victory: Collect
        rgx = new RegExp(/All items found! Party has received their rewards\./i);
        if( s.indexOf("All items found! Party has received their rewards") >= 0 ) {
            $card.addClass("victory");
            s = "<h4>Victory! All items found!</h4> <div class=desc><i>Party has received their rewards.</i></div>";
        }



        // Assign new html
        $msg.html("<code>"+s+"</code>");
    });
}