Creddit

Pridá autorov príspevkov k položkám v feede Reddit (v novom Reddit)

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name                 Creddit
// @name:af              Creddit
// @name:am              Creddit
// @name:ar              Creddit
// @name:az              Creddit
// @name:be              Creddit
// @name:bg              Creddit
// @name:bn              Creddit
// @name:bs              Creddit
// @name:ca              Creddit
// @name:cs              Creddit
// @name:cy              Creddit
// @name:da              Creddit
// @name:de              Creddit
// @name:el              Creddit
// @name:es              Creddit
// @name:et              Creddit
// @name:fa              Creddit
// @name:fi              Creddit
// @name:fil             Creddit
// @name:fr              Creddit
// @name:ga              Creddit
// @name:gl              Creddit
// @name:gu              Creddit
// @name:he              Creddit
// @name:hi              Creddit
// @name:hr              Creddit
// @name:hu              Creddit
// @name:hy              Creddit
// @name:id              Creddit
// @name:is              Creddit
// @name:it              Creddit
// @name:ja              Creddit
// @name:ka              Creddit
// @name:kk              Creddit
// @name:km              Creddit
// @name:kn              Creddit
// @name:ko              Creddit
// @name:ku              Creddit
// @name:lo              Creddit
// @name:lt              Creddit
// @name:lv              Creddit
// @name:mk              Creddit
// @name:ml              Creddit
// @name:mn              Creddit
// @name:mr              Creddit
// @name:ms              Creddit
// @name:mt              Creddit
// @name:nb              Creddit
// @name:ne              Creddit
// @name:nl              Creddit
// @name:nn              Creddit
// @name:or              Creddit
// @name:pa              Creddit
// @name:pl              Creddit
// @name:ps              Creddit
// @name:pt              Creddit
// @name:ro              Creddit
// @name:ru              Creddit
// @name:si              Creddit
// @name:sk              Creddit
// @name:sl              Creddit
// @name:sq              Creddit
// @name:sr              Creddit
// @name:sv              Creddit
// @name:sw              Creddit
// @name:ta              Creddit
// @name:te              Creddit
// @name:th              Creddit
// @name:tl              Creddit
// @name:tr              Creddit
// @name:uk              Creddit
// @name:ur              Creddit
// @name:uz              Creddit
// @name:vi              Creddit
// @name:xh              Creddit
// @name:yi              Creddit
// @name:zh-CN           Creddit
// @name:zh-TW           Creddit
// @name:zh-HK           Creddit
// @description          Adds post authors to items in Reddit feed (on new Reddit)
// @description:af       Voeg posouteurs by items in Reddit-feed (op nuwe Reddit)
// @description:am       ከReddit ፊደል ውስጥ የሚታዩ ዕቃዎች ጋር የልጅ ደራሽ ያክሉ (በአዲሱ Reddit)
// @description:ar       يضيف مؤلفي المنشورات إلى العناصر في تغذية Reddit (في Reddit الجديد)
// @description:az       Reddit feed-dəki elementlərə yazı müəlliflərini əlavə edir (yeni Reddit-də)
// @description:be       Дадае аўтараў пастоў да элементаў у стужцы Reddit (у новым Reddit)
// @description:bg       Добавя авторите на публикациите към елементите във фийда на Reddit (в новия Reddit)
// @description:bn       Reddit ফিডের আইটেমগুলিতে পোস্ট লেখকদের যোগ করে (নতুন Reddit-এ)
// @description:bs       Dodaje autore objava uz stavke u Reddit feedu (na novom Redditu)
// @description:ca       Afegeix els autors de les publicacions als elements del feed de Reddit (al nou Reddit)
// @description:cs       Přidá autory příspěvků k položkám v kanálu Reddit (v novém Redditu)
// @description:cy       Ychwanegu awduron swyddi at eitemau yn y ffrwd Reddit (ar Reddit newydd)
// @description:da       Tilføjer opslagets forfattere til elementer i Reddit-feedet (på nye Reddit)
// @description:de       Fügt Beitragsautoren zu Einträgen im Reddit-Feed hinzu (auf dem neuen Reddit)
// @description:el       Προσθέτει τους συγγραφείς των δημοσιεύσεων στα στοιχεία της ροής Reddit (στο νέο Reddit)
// @description:es       Añade autores de publicaciones a los elementos del feed de Reddit (en el nuevo Reddit)
// @description:et       Lisab postituste autorid Reddit-voo üksustele (uues Redditis)
// @description:fa       افزودن نویسندگان پست به آیتم‌ها در فید Reddit (در Reddit جدید)
// @description:fi       Lisää viestien kirjoittajat Reddit-syötteen kohtiin (uudessa Redditissä)
// @description:fil      Idinadagdag ang mga may-akda ng post sa mga item sa Reddit feed (sa bagong Reddit)
// @description:fr       Ajoute les auteurs des publications aux éléments du fil Reddit (sur le nouveau Reddit)
// @description:ga       Cuirtóirí poist le míreanna sa sruth Reddit (ar an Reddit nua)
// @description:gl       Engade os autores das publicacións aos elementos do feed de Reddit (no novo Reddit)
// @description:gu       Reddit ફીડમાં આઇટમોમાં પોસ્ટ લેખકો ઉમેરે છે (નવા Reddit પર)
// @description:he       מוסיף את מחברי הפוסטים לפריטים בפיד של Reddit (ברדיט החדש)
// @description:hi       Reddit फ़ीड में आइटम्स पर पोस्ट लेखकों को जोड़ता है (नए Reddit पर)
// @description:hr       Dodaje autore objava uz stavke u Reddit feedu (na novom Redditu)
// @description:hu       Hozzáadja a bejegyzések szerzőit a Reddit-hírcsatorna elemeihez (az új Redditen)
// @description:hy       Ավելացնում է հրապարակումների հեղինաներին Reddit հոսքի իրերներին (նոր Reddit-ում)
// @description:id       Menambahkan penulis posting ke item di feed Reddit (di Reddit baru)
// @description:is       Bætir við höfundum færslna á atriði í Reddit-fflæði (á nýja Reddit)
// @description:it       Aggiunge gli autori dei post agli elementi nel feed di Reddit (sul nuovo Reddit)
// @description:ja       Reddit フィードの項目に投稿の作成者を追加します(新しい Reddit)
// @description:ka       დაემატებინება პოსტების ავტორები Reddit-ის ნაკადში ნივთებს (ახალ Reddit-ში)
// @description:kk       Reddit таспасындағы элементтерге жазба авторларын қосады (жаңа Reddit-та)
// @description:km       បន្ថែមអ្នកនិពន្ធប៉ុស្តិ៍ទៅធាតុក្នុងផ្ទាំងព័ត៌មាន Reddit (លើ Reddit ថ្មី)
// @description:kn       Reddit ಫೀಡಿನ ಐಟಂಗಳಿಗೆ ಪೋಸ್ಟ್ ಲೇಖಕರನ್ನು ಸೇರಿಸುತ್ತದೆ (ಹೊಸ Reddit ನಲ್ಲಿ)
// @description:ko       Reddit 피드 항목에 게시물 작성자를 추가합니다 (새 Reddit에서)
// @description:ku       Nivîskarên postan zêde dike li tiştên feed-a Redditê (li Reddit-a nû)
// @description:lo       ເພີ່ມຜູ້ແຕ່ງຂຽນຂອງຂໍ້ຄວາມໃສ່ລາຍການໃນ feed ຂອງ Reddit (ໃນ Reddit ໃໝ່)
// @description:lt       Prideda įrašų autorius prie elementų Reddit sraute (naujajame Reddit)
// @description:lv       Pievieno ierakstu autorus Reddit plūsmā esošajiem vienumiem (jaunajā Reddit)
// @description:mk       Додава автори на објави на ставки во Reddit-ната фид (на новиот Reddit)
// @description:ml       Reddit ഫീഡിലുള്ള آیറ്റങ്ങളെ പോസ്റ്റ് എഴുത്തുകാരെ ചേർക്കുന്നു (പുതിയ Reddit ൽ)
// @description:mn       Reddit фийд дахь зүйлсэд нийтлэлийн зохиогчдыг нэмнэ (шинэ Reddit дээр)
// @description:mr       Reddit फीडमधील आयटम्समध्ये पोस्ट लेखकांची भर करते (नव्या Reddit वर)
// @description:ms       Menambah pengarang pos ke item dalam feed Reddit (di Reddit baru)
// @description:mt       Żid l-awturi tal-karigi mal-oġġetti fil-feed ta' Reddit (fil-Reddit il-ġdid)
// @description:nb       Legger til forfattere av innlegg på elementer i Reddit-feeden (på nye Reddit)
// @description:ne       Reddit फिडका सामानहरूमा पोस्ट लेखकहरू थप्छ (नयाँ Reddit मा)
// @description:nl       Voegt berichtauteurs toe aan items in de Reddit-feed (op het nieuwe Reddit)
// @description:nn       Legg til forfattarar av innlegg på element i Reddit-feed (på nye Reddit)
// @description:or       Reddit ଫିଡର ଆଇଟମଗୁଡିକରେ ପୋଷ୍ଟ ଲେଖକମାନେ ଯୋଗ କରେ (ନୂତନ Reddit ଉପରେ)
// @description:pa       Reddit ਫੀਡ ਵਿੱਚ ਆਈਟਮਾਂ 'ਤੇ ਪੋਸਟ ਲੇਖਕਾਂ ਨੂੰ ਜੋੜਦਾ ਹੈ (ਨਵੇਂ Reddit 'ਤੇ)
// @description:pl       Dodaje autorów postów do elementów w kanale Reddit (w nowym Reddit)
// @description:ps       په Reddit فید کې پوسټ لیکونکي توکو ته اضافه کوي (په نوي Reddit کې)
// @description:pt       Adiciona autores das publicações aos itens no feed do Reddit (no novo Reddit)
// @description:ro       Adaugă autorii postărilor la elementele din feed-ul Reddit (pe noul Reddit)
// @description:ru       Добавляет авторов постов к элементам в ленте Reddit (в новом Reddit)
// @description:si       Reddit ප්‍රීත්‍යාහාරයේ අයිතමවලට පශ්චාත් ලේඛකයන් එකතු කරයි (නව Reddit හි)
// @description:sk       Pridá autorov príspevkov k položkám v feede Reddit (v novom Reddit)
// @description:sl       Doda avtorje objav k elementom v Reddit viru (na novem Redditu)
// @description:sq       Shton autorët e postimeve te artikujt në feed-in e Reddit (në Reddit-in e ri)
// @description:sr       Dodaje autore objava stavkama u Reddit feedu (na novom Redditu)
// @description:sv       Lägger till inläggsförfattare på objekt i Reddit-flödet (på nya Reddit)
// @description:sw       Inaongezea waandishi wa machapisho kwa vipengele kwenye feed ya Reddit (kwenye Reddit mpya)
// @description:ta       Reddit ஃபீடில் உள்ள உருப்படிகளுக்கு இடுகை எழுத்தாளர்களை சேர்க்கிறது (புதிய Reddit இல்)
// @description:te       Reddit ఫీడ్‌లో అంశాలకు పోస్ట్ రచయిత్రులను జోడిస్తుంది (కొత్త Reddit లో)
// @description:th       เพิ่มผู้เขียนโพสต์ไปยังรายการในฟีด Reddit (บน Reddit ใหม่)
// @description:tl       Idinadagdag ang mga may-akda ng post sa mga item sa Reddit feed (sa bagong Reddit)
// @description:tr       Reddit akışındaki öğelere gönderi yazarlarını ekler (yeni Reddit'te)
// @description:uk       Додає авторів дописів до елементів у стрічці Reddit (на новому Reddit)
// @description:ur       Reddit فیڈ میں آئٹمز میں پوسٹ مصنفین شامل کرتا ہے (نئے Reddit پر)
// @description:uz       Reddit lentasidagı elementlarga post mualliflarini qo‘shadi (yangi Redditda)
// @description:vi       Thêm tác giả bài viết vào các mục trong nguồn Reddit (trên Reddit mới)
// @description:xh       Yongeza ababhali beenyathe kumalungu kwi-Reddit feed (ku-Reddit entsha)
// @description:yi       לייגט פּאָסטן אויסטאָרן צו אַייטעמס אין Reddit פֿיד (אויף ניו Reddit)
// @description:zh-CN    在 Reddit 订阅源的条目中添加帖子作者(在新版 Reddit)
// @description:zh-TW    在 Reddit 動態中的項目添加貼文作者(在新版 Reddit)
// @description:zh-HK    在 Reddit 動態的項目中添加帖子作者(在新版 Reddit)
// @namespace            github.com/JasonAMelancon
// @version              13
// @author               Jason Melancon
// @license              GNU AGPLv3
// @match                http*://www.reddit.com/*
// @grant                none
// @supportURL           https://greasyfork.org/en/scripts/545054-creddit/feedback
// @homepageURL          https://greasyfork.org/en/scripts/545054-creddit/
// ==/UserScript==

(function() {
    'use strict';

//-- script begins here --//

const DEBUG = false;
// The msg is in a lambda expression body so that string interpolation only happens if we
// actually print the message (lazy evaluation).
function debugLog(lambdifiedMsg) {
    if (DEBUG) console.log(lambdifiedMsg());
}

const scriptName = GM_info.script.name;
const FEED = "shreddit-feed"; // Reddit's custom element name
const POST = "shreddit-post"; // Reddit's custom element name
const VIEW_CONTEXT = "view-context"; // Reddit's custom attribute name
const AGGREGATE_FEED = "AggregateFeed"; // Reddit's post element attribute value; indicates need to run script

const CREDITED = "is-credited"; // my custom attribute for the post element

//== This is the main part of the script. ==//

function runScript() {
    const feeds = document.getElementsByTagName(FEED);
    if (feeds.length > 1) { // I have no idea whether this is or will ever be necessary
        console.log(`[${scriptName}] Multiple Reddit feed nodes present`);
    }
    const feed = feeds[0];

    const articleCollection = feed.querySelectorAll("article");
    debugLog(() => `[${scriptName}] ${articleCollection.length} initial articles`);
    // Get the first few articles in the feed when the page loads, and add the author.
    articleCollection.forEach(putCreditInArticle);

    // Watch the page for new articles that appear when scrolling.
    const dynamicScroll = new MutationObserver(mutations => {
        debugLog(() => `[${scriptName}] ${mutations.length} new mutation objects`);
        for (let mutation of mutations) {
            const newArticleArray = Array.from(mutation.addedNodes).filter(node => node.nodeName === "ARTICLE");
            debugLog(() => `[${scriptName}] ${newArticleArray.length} new articles`);
            if (newArticleArray.length == 0) continue;
            // Add the author to the new articles as they appear.
            newArticleArray.forEach(putCreditInArticle);
        }
    });
    dynamicScroll.observe(feed, { childList: true, subtree: false, attributes: false, characterData: false });

    // Handle articles, whether on page load or dynamic scroll
    function putCreditInArticle(article) {
        const post = article.querySelector(POST);
        if (!post) return;
        if (!isCredited(post)) {
            creditAuthor(post);
            markCredited(post);
        }
    }

    // Put the author of a single article on the top line, next to the subreddit and post age.
    function creditAuthor(post) {
        const subreddit = post.getAttribute("subreddit-name");

        // Posts to a followed u/user have no true r/subreddit;
        // these already have the author credit inherently.
        const selfPost = !subreddit;
        if (selfPost) return; // no need for another byline

        const author = post.getAttribute("author");
        const creditBar = post.querySelector("[id*='credit-bar']");
        const separator = creditBar.querySelector(".created-separator");
        creditBar.appendChild(separator.cloneNode(/*deep = */true));
        const byLineClass = separator.nextElementSibling.getAttribute("class");
        const byLine = creditBar.appendChild(document.createElement("span"));
        byLine.setAttribute("class", byLineClass);
        byLine.textContent = "by ";
        byLine.insertAdjacentHTML("afterend", authorNameCard()); // handles deleted accounts

        // This code enables the author "hover card" with some info from the profile page.
        // Returns HTML copied and pasted almost verbatim from inside a subreddit.
        function authorNameCard() { return `
          <span slot="authorName" class="flex">
            <div class="inline-flex items-center max-w-full">
              <faceplate-hovercard enter-delay="500" leave-delay="150" position="bottom-start"
                                   data-id="user-hover-card" label="${author} details" mouse-only="" appearance="neutral">
                <faceplate-tracker source="post_credit_bar" action="click" noun="user_profile" class="visible">
                  <a rpl="" class="author-name whitespace-nowrap text-neutral-content visited:text-neutral-content-weak font-semibold
                                   focus-visible:-outline-offset-1 a cursor-pointer no-visited no-underline hover:no-underline"
                            href="/user/${author}/" aria-haspopup="dialog" aria-expanded="false">
                    ${author}
                  </a>
                </faceplate-tracker>
                <div slot="content">
                  <faceplate-partial src="/svc/shreddit/user-hover-card/${author}?subredditName=${subreddit}" loading="programmatic">
                    <div class="w-5xl h-4xl flex items-center justify-center">
                      <faceplate-progress value="20" class="animate-spin"></faceplate-progress>
                    </div>
                  </faceplate-partial>
                </div>
              </faceplate-hovercard>
            </div>
          </span>`;
        }
    }

    // When scrolling down far enough, Reddit unloads posts from the top of the page,
    // presumably to save memory. In general, Reddit unloads posts you scroll away from
    // and loads or reloads posts you scroll toward. Without checking to make sure the
    // post hasn't already been credited, this can cause this script to credit the post
    // multiple times when the MutationObserver notices a credited post reappear in the
    // feed.
    //
    // Therefore, check first.
    function isCredited(post) {
        debugLog(() => `[${scriptName}] credited check: ${post.hasAttribute(CREDITED)}`);
        return post.hasAttribute(CREDITED);
    }

    // Marks a post as already credited.
    function markCredited(post) {
        post.setAttribute(CREDITED, "");
    }
}

//== This is the part of the script that deals with the PITA way Reddit does scripted navigation. ==//

// Detect feed page on initial load or subsequent XHR/AJAX load by checking the view-context attribute
// of the first post.
//
// This script can run on any page that's designated by Reddit as an "aggregate feed," meaning a feed
// with posts taken from more than one subreddit. Examples would be r/popular, r/all, /new/, etc.
function runScriptIfNecessary() {
    const isAggregateFeed = document.querySelector(POST)?.getAttribute(VIEW_CONTEXT) == AGGREGATE_FEED;
    debugLog(() => `[${scriptName}] This page ${isAggregateFeed ? "contains" : "does not contain"} an aggregate feed`);

    if (isAggregateFeed) {
        runScript();
    }
}

runScriptIfNecessary();

// Run the script when using the site nav (fake AJAX navigation) to get to the feed. This apparently
// can be bouncy and fire multiple times and lead to repeated console debug messages. This code does
// contain a debouncing measure, but even without this the problem is not severe, since before
// modifying any post's DOM we always check if we've done it already.
{
    let lastObservation = 0;
    new MutationObserver(() => {
        let now = Date.now();
        if (now - lastObservation > 300) { // debounce
            const title = document.querySelector("title").textContent;
            debugLog(() => `[${scriptName}] Page <title> change detected (indicating navigation to a new page);\n` +
                           `[${scriptName}] <title> is now "${title}" at time ${now}`);

            runScriptIfNecessary();
            lastObservation = now;
        }
    }).observe(document.querySelector("title"), { childList: true });
}

//-- script ends here --//

})();