FANDOM


(approving, but changing "en" to "fr")
(basic attempt at translating French of the description line. Anyone with better French, feel free to slide in something better. :) :))
Line 78: Line 78:
 
},
 
},
 
fr: {
 
fr: {
description: "[https://discordapp.com/ Discord] is a free application for public discussions outside Fandom. " +
+
description: "[https://discordapp.com/ Discord] est une application gratuite pour des débats publics en dehors de FANDOM " +
"[[wikipedia:Discord (software)|Get more in Wikipedia]]",
+
"[[wikipedia:Discord (software)|Découvrez plus sur wikipedia]]",
 
online: "En ligne:",
 
online: "En ligne:",
 
join: "Joindre",
 
join: "Joindre",

Revision as of 01:34, February 2, 2018

/* Name:    DiscordModule 1.0.52
 * Author:  Сибирский Смотритель (Siberian Specules)
 * Idea:    Your Own Waifu
 * Testers: TrJVoRoN
*/
 
/*global require */
require(['jquery', 'mw', 'wikia.ui.factory', 'BannerNotification', 'wikia.window'], 
function ($, mw, uiFactory, BannerNotification, window) {
'use strict';
 
var cfg = mw.config.get([
    'skin',
    'wgPageName',
    'wgUserLanguage',
    'wgUserName',
    'wgUserGroups'
]);
 
if (
    (!$('#WikiaRail').length && cfg.skin !== "wikia" && cfg.skin !== "oasis") &&
    !$('.discord-container').length &&
    cfg.wgPageName !== "MediaWiki:Custom-Discord-Module-Settings"
) {
    return;
}
 
// Translations
function translate(text) {
    var i18n = {
        be: {
            description: "[https://discordapp.com/ Discord] – дармовы дадатак для публічнага камунікавання па-за Фэндома. " +
                         "[[wikipedia:be:Discord|Падрабязней у Вікіпедыі]]",
            online: "У сеціве:",
            join: "Увайсці",
            onlinelist: "Карыстачы анлайн",
            instruction: "Каб атрымаць ID сервера, трэба прайсці:<br/>" +
                         "Налады сервера > Віджэт > ID Сервера<br/>" +
                         "Тамсама трэба ўключыць віджэт і выбраць канал, калі хочаце, каб людзі прыходзілі на сервер.",
            descriptionForm: "Апісанне",
            supportsWikitext: "падтрымвае вікі-тэкст",
            placeholder: "Па змаўчанні будуць выведзена інфармацыя пра Дыскорд",
            useSvg: "Скарыстаць уласную выяву (патрабуюцца змены CSS)",
            flags: "Іншыя параметры",
            showForAnonym: "Не паказваць ананімам",
            showServerName: "Не паказваць імя сервера",
            showGuideline: "Не паказваць апісанне",
            railPosition: "Пазіцыянаваць знізу рэйла",
            generateHTML: "Згенераваць HTML",
            saveSettings: "Захаваць",
            reset: "Скінуць",
            successChange: 'Змены захаваны',
            errorChange: 'Абмыла захавання'
        },
        en: {
            description: "[https://discordapp.com/ Discord] is a free application for public discussions outside Fandom. " +
                         "[[wikipedia:Discord (software)|Get more in Wikipedia]]",
            online: "Online:",
            join: "Join",
            onlinelist: "Users online",
            instruction: "To get server ID you need to go this path (need administrator rights):<br/>" +
                         "Server settings > Widget > Server ID<br/>" +
                         "Also here you need to turn on widget and choose the channel to invite if you want users to be coming on your server.",
            descriptionForm: "Module description",
            supportsWikitext: "supports wikitext",
            placeholder: "Information about Discord by default",
            useSvg: "Use custom image (CSS change required)",
            flags: "Other parameters",
            showGuideline: "Do not show custom description",
            showForAnonym: "Do not show for anonyms",
            showServerName: "Do not show server name",
            railPosition: "Position below the rail",
            generateHTML: "Generate HTML",
            saveSettings: "Save",
            reset: "Reset",
            successChange: 'Successfully saved',
            errorChange: 'An error occurred'
        },
        fr: {
            description: "[https://discordapp.com/ Discord] est une application gratuite pour des débats publics en dehors de FANDOM " +
                         "[[wikipedia:Discord (software)|Découvrez plus sur wikipedia]]",
            online: "En ligne:",
            join: "Joindre",
            onlinelist: "Utilisateurs en ligne",
            instruction: "Pour recevoir l\'identifiant du serveur, utiliser cette route (vous avez besoin des permissions administrateur):<br/>" +
                         "Paramètres du serveur > Widget > Identifiant du serveur (ID)<br/>" +
                         "Vous avez aussi besoin d'activer le widget pour le serveur et choisir le salon dans lequel vous voulez votre invitation.",
            descriptionForm: "Description du module",
            supportsWikitext: "supporte le wikitext",
            placeholder: "Information à propos de Discord par défaut",
            useSvg: "Utiliser un image customisé (a besoin d'une modification au CSS)",
            flags: "Autres paramètres",
            showGuideline: "Ne montrez pas description customisé",
            showForAnonym: "Ne montez pas pour anonyms",
            showServerName: "Ne montrez pas le nom du serveur",
            railPosition: "Position sous la barre latérale",
            generateHTML: "Genérer le HTML",
            saveSettings: "Sauver",
            reset: "Réinitialiser",
            successChange: 'Sauvé avec succès',
            errorChange: 'Un erreur s\'est produit',
        },
        pl: {
            description: "[https://discordapp.com/ Discord] jest aplikacją używaną do komunikacji poza FANDOMem. " +
                         "[[wikipedia:pl:Discord|Dowiedz się więcej]] (Wikipedia)",
            online: "Online:",
            join: "Dołącz",
            onlinelist: "Użytkownicy online",
            instruction: "Aby uzyskać ID serwera wejdź tutaj (wymaga uprawnień administratora):<br/>" +
                         "Ustawienia serwera > Widget > ID serwera<br/>" +
                         "W tym miejscu możesz również włączyć widget Discorda i wybrać kanał, na który będą dołączać użytkownicy.",
            descriptionForm: "Opis modułu",
            supportsWikitext: "wspiera wikitekst",
            placeholder: "Domyślnie krótka informacja na temat Discorda",
            useSvg: "Użyj własnego obrazu (wymaga zmian w CSS)",
            flags: "Inne ustawienia",
            showGuideline: "Nie pokazuj niestandardowego opisu",
            showForAnonym: "Nie pokazuj niezalogowanym",
            showServerName: "Nie pokazuj nazwy serwera",
            railPosition: "Umieść pod koniec prawej kolumny",
            generateHTML: "Wygeneruj kod HTML",
            saveSettings: "Zapisz",
            reset: "Wyczyść",
            successChange: 'Pomyślnie zapisano',
            errorChange: 'Wystąpił błąd'
        },
        ru: {
            description: "[https://discordapp.com/ Discord] – бесплатное приложение для публичного общения вне Фэндома. " +
                         "[[wikipedia:ru:Discord|Подробнее в Википедии]]",
            online: "В сети:",
            join: "Войти",
            onlinelist: "Пользователи онлайн",
            instruction: "Чтобы получить ID сервера, нужно пройти:<br/>" +
                         "Настройки сервера > Виджет > ID Сервера<br/>" +
                         "Там же надо включить виджет и выбрать канал, если хотите, чтобы люди приходили на сервер.",
            descriptionForm: "Описание",
            supportsWikitext: "поддерживает викитекст",
            placeholder: "По умолчанию будут выведена информация о Дискорде",
            useSvg: "Использовать собственное изображение (требуются изменения CSS)",
            flags: "Другие параметры",
            showForAnonym: "Не показывать анонимам",
            showServerName: "Не показывать имя сервера",
            showGuideline: "Не показывать описание",
            railPosition: "Позиционировать снизу рельсы",
            generateHTML: "Сгенерировать HTML",
            saveSettings: "Сохранить",
            reset: "Сбросить",
            successChange: 'Изменения сохранены',
            errorChange: 'Ошибка сохранения'
        },
        uk: {
            description: "[https://discordapp.com/ Discord] – безкоштовний додаток для публічного спілкування поза Фендому. " +
                         "[[wikipedia:uk:Discord|Докладніше у Вікіпедії]]",
            online: "В мережі:",
            join: "Увійти",
            onlinelist: "Користувачі онлайн",
            instruction: "Аби отримати ID сервера, потрібно пройти:<br/>" +
                         "Налаштування сервера > Віджет > ID Сервера<br/>" +
                         "Там же треба включити віджет й обрати канал, якщо хочете, щоб люди приходили на сервер.",
            descriptionForm: "Опис",
            supportsWikitext: "підтримує вікі-текст",
            placeholder: "За замовчуванням буде виведено інформацію про Дискорд",
            useSvg: "Використовувати власне зображення (потрібні зміни CSS)",
            flags: "Інші параметри",
            showForAnonym: "Не показувати анонімам",
            showServerName: "Не показувати ім\'я сервера",
            showGuideline: "Не показувати опис",
            railPosition: "Позиціонувати знизу рейлу",
            generateHTML: "Згенерувати HTML",
            saveSettings: "Зберегти",
            reset: "Скинути",
            successChange: 'Зміни збережені',
            errorChange: 'Помилка збереження'
        }
    };
 
    var lang = cfg.wgUserLanguage;
    var translateList = typeof i18n[lang] !== 'undefined' ? i18n[lang] : i18n.en;
 
    for (var k in translateList) {
        text = text.replace(new RegExp("\\(" + k + "\\)", "gi"), translateList[k] || i18n.en[k]);
    }
 
    return text;
}
 
var defaultSettings = {
    id: '',
    customDescription: "",
    railPosition: "prepend",
    showGuideline: true,
    showForAnonym: true,
    showServerName: true,
    useSvg: true
};
 
// Settings from MediaWiki
function init(callback) {
    var settings = {};
    $.ajax({
        url: '/index.php',
        type: 'GET',
        data: {
            action: "raw",
            title: "MediaWiki:Custom-Discord-Module-Settings",
        },
        success: function(settings) {
            if (typeof settings.missing === 'undefined')
                settings = JSON.parse(settings);
            else
                settings = window.DiscordModuleSettings || {};
 
            callback(settings);
        },
        error: function() {
            callback({});
        }
    });
}
 
// Discord Guild Data
function getData(settings, container) {
    var id = typeof container.selector.data("id") !== 'undefined' ? 
        container.selector.data("id") : settings.id;
    var discordJSON = "https://discordapp.com/api/servers/" + id + "/embed.json";
    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4 && request.status == 200) {
            try {
                var data = JSON.parse(request.responseText);
                if (typeof data.name === undefined)
                    container.showError("Configuration Error: wrong server ID");
 
                buildModule(data, settings, container);
            } catch (e) {
                container.showError(e);
            }
        } else if (request.readyState == 4) {
            container.showError("Configuration Error");
        }
    };
    request.open("GET", discordJSON, true);
    request.send();
}
 
// Generate block with guild info and join link
function buildModule(data, settings, container) {
    settings = $.extend({}, defaultSettings, settings, container.getData());
    if (
        typeof settings.showForAnonym !== "boolean" || 
        typeof settings.showServerName !== "boolean" || 
        typeof settings.showGuideline !== "boolean" || 
        typeof settings.useSvg !== "boolean" || 
        typeof settings.customDescription !== "string"
    ) {
        return container.showError("Configuration Error: wrong type");
    }
 
    if (settings.showForAnonym && typeof cfg.wgUserName === 'undefined')
        return;
 
    function loadModule(description) {
        var image = !settings.useSvg ? 
        '<div class="discord-icon"></div>' : 
        '<svg xmlns="http://www.w3.org/2000/svg" class="discord-svg" width="20" height="20" viewBox="0 0 240 245">' + 
            '<path d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/>' +
            '<path d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/>' +
        '</svg>';
 
        var $module = $('<div class="discord-content">' +
            '<h2 class="discord-header has-icon">' +
                image + 
                (settings.showServerName ? data.name : 'Discord') + 
            '</h2>' +
            (description || '') +
            '<div class="discord-connect">' +
                (data.instant_invite ? 
                '<a class="discord-join wds-is-squished wds-button wds-is-secondary">(join)</a>' : 
                '') +
                '<a class="discord-online">(online) <span class="discord-counter">?</span></a>' +
            '</div>' +
        '</div>');
 
        $module.find('.discord-join').attr('onclick', "window.open('" + data.instant_invite + "','_blank')");
        $module.find('.discord-counter').text(data.members.length);
        $module.html(translate( $module[0].innerHTML ));
 
        var $members = $('<ul class="discord-list"></ul>');
        data.members.forEach(function (v) {
            var $member = $('<li>', {
                'class': 'discord-member discord-member-' + v.username.replace(/\s/g, '_')
            }).append(
                $('<div>', { 'class': 'discord-avatar' }).append(
                    $('<img>')
                )
            );
            $member.append(v.username + (v.bot ? '<span class="discord-bot">BOT</span>' : ''));
            $member.find('.discord-avatar').addClass("discord-" + v.status);
            $member.find('img').attr("src", v.avatar_url);
 
            $members.append($member);
        });
 
        $module.find('.discord-online').click(function(e) {
            e.preventDefault();
            uiFactory.init(['modal']).then(function(uiModal) {
                uiModal.createComponent({
                    type: 'default',
                    vars: {
                        id: 'discord-list-modal',
                        title: translate('(onlinelist)'),
                        content: $members.html(),
                        size: 'small'
                    }
                }, function(modal) {
                    modal.$element.keydown(function(e) {
                        if (e.which == 27) {
                            e.preventDefault();
                            modal.trigger("close");
                        }
                    });
                    modal.bind("reset", function(e) {
                        e.preventDefault();
                        modal.trigger("close");
                    });
                    modal.show();
                });
            });
        });
 
        container.fill($module, settings.railPosition);
    }
 
    if (settings.showGuideline) {
        var description = '<p class="discord-guideline">' +
                        (settings.customDescription || translate("(description)")) +
                    '</p>';
        parseWikitext(description, loadModule);
    } else {
        loadModule(false);
    }
}
 
// Settings form
function visualSettings(settings) {
    var $form = $(translate('<div class="discord-settings">' +
        '<form id="ds-id">' +
            '<label for="ds-form-id">ID:</label>' +
            '<input id="ds-form-id" name="id"/>' +
            '<div class="ds-id-instruction">(instruction)</div>' +
        '</form>' +
        '<form id="ds-description">' +
            '<div class="ds-header">(descriptionForm) <small>((supportsWikitext))</small></div>' +
            '<textarea id="ds-description-input" name="customDescription" placeholder="(placeholder)"></textarea>' +
        '</form>' +
        '<form id="ds-flags">' +
            '<div class="ds-header">(flags)</div>' +
            '<label class="ds-flag">' +
                '<input type="checkbox" name="useSvg"/>' +
                '<span class="ds-label">(useSvg)</span>' +
            '</label>' +
            '<label class="ds-flag">' +
                '<input type="checkbox" name="showForAnonym"/>' +
                '<span class="ds-label">(showForAnonym)</span>' +
            '</label>' +
            '<label class="ds-flag">' +
                '<input type="checkbox" name="showServerName"/>' +
                '<span class="ds-label">(showServerName)</span>' +
            '</label>' +
            '<label class="ds-flag">' +
                '<input type="checkbox" name="showGuideline"/>' +
                '<span class="ds-label">(showGuideline)</span>' +
            '</label>' +
        '</form>' +
        '<form id="ds-buttons">' +
            (cfg.wgUserGroups.indexOf('sysop') !== -1 ? 
            '<a class="wds-button wds-is-squished ds-save">(saveSettings)</a>' : 
            '') +
            '<a class="wds-is-secondary wds-button wds-is-squished ds-reset">(reset)</a>' +
            '<a class="wds-is-secondary wds-button wds-is-squished ds-html">(generateHTML)</a>' +
        '</form>' +
        '<textarea class="ds-generated" style="display: none;"></textarea>' +
    '</div>'));
 
    s2v(settings, $form);
    $form.find('.ds-save').click(function () {
        $.ajax({
            url: '/api.php',
            type: 'POST',
            data: {
                action: "edit",
                title: "MediaWiki:Custom-Discord-Module-Settings",
                token: mw.user.tokens.get('editToken'),
                text: JSON.stringify(v2s($form)),
                summary: "Editing settings",
                recreate: true
            },
            success: function() {
                new BannerNotification(translate('(successChange)'), 'confirm').show();
            },
            error: function(e) {
                new BannerNotification(translate('(errorChange)'), 'error').show();
                console.error(e);
            }
        });
    });
 
    $form.find('.ds-reset').click(function() {
        s2v(settings, $form);
    });
 
    $form.find('.ds-html').click(function () {
        var data = v2s($form);
        Object.keys(data).map(function(key) {
            data["data-" + key.replace(/([A-Z])/g, '-$1')] = data[key];
            delete data[key];
        });
 
        $form.find('.ds-generated').val(
            $('<div/>').append(
                $('<div class="discord-container"> </div>').attr( data )
            ).html()
        ).show();
    });
 
    $('#mw-content-text').before($form);
}
 
// Settings to visual
function s2v(settings, selector) { 
    selector.find('#ds-form-id').val( getAttr("id") );
    selector.find('#ds-description-input').val( getAttr("customDescription") );
 
    ["showForAnonym", "showGuideline", "useSvg", "showServerName"]
    .forEach(function(v) {
        checkIf( !getAttr(v), v );
    });
 
    function getAttr(attr) {
		if (typeof settings[attr] !== 'undefined')
			return settings[attr];
        return defaultSettings[attr];
    }
 
    function checkIf(condition, checkbox) {
        var $checkbox = selector.find('[name="' + checkbox + '"]');
        if (condition)
            $checkbox.prop('checked', true);
        else
            $checkbox.prop('checked', false);
    }
}
 
// Visual to settings
function v2s(selector) { 
    return selector.find("#ds-id, #ds-description, #ds-flags")
        .serializeArray()
        .map(function(v) {
            if (
                v.value === "on" &&
                ["showForAnonym", "showGuideline", "useSvg", "showServerName"]
                .indexOf(v.name) != -1
            ) { 
                v.value = false;
            }
 
            return [v.name, v.value];
        })
        .reduce(function(obj, pair) {
            obj[pair[0]] = pair[1];
            return obj;
        }, {});
}
 
// Container's object: rail section or block in content
function Container(type, selector) {
    this.type = type;
    if (type == "box") {
        this.selector = $(selector).addClass("rail-module");
    } else {
        var newSelector = $('<div class="discord-module rail-module"></div>');
        $(selector).prepend(newSelector);
        this.selector = newSelector;
    }
    this.fill(this.preload);
}
 
Container.prototype.preload = $(
'<div class="discord-preload">' + 
    '<svg xmlns="http://www.w3.org/2000/svg" class="wds-spinner wds-spinner__block" width="45" height="45" viewBox="0 0 45 45">' +
        '<g transform="translate(22.5, 22.5)">' +		
            '<circle class="wds-spinner__stroke" fill="none" stroke-linecap="round" stroke-width="5" stroke-dasharray="125.66370614359172" stroke-dashoffset="125.66370614359172" r="20"></circle>' +
        '</g>' +
    '</svg>' +
'</div>');
 
Container.prototype.getData = function() {
    if (this.type === "rail") return {};
    return this.selector.data();
};
 
Container.prototype.fill = function(content) {
    this.selector.html(content);
};
 
Container.prototype.showError = function(text) {
    this.fill(
        '<div class="discord-error">' + 
            text + '<br/>' + 
            '<a href="?action=purge">Reload?</a>' + 
        '</div>', 
    'prepend');
};
 
// Wikitext parser
function parseWikitext(text, callback) {
    $.ajax({
        url: '/api.php',
        type: 'GET',
        data: {
            action: "parse",
            contentmodel: "wikitext",
            text: text,
            format: 'json'
        },
        success: function(data) {
            callback(data.parse.text['*']);
        }
    });
}
 
// Run
init(function(settings) {
    window.importArticle({
        type: 'style',
        article: 'u:dev:MediaWiki:DiscordModule/style.css'
    });
 
    if ( $('#WikiaRail').length ) {
        getData( settings, new Container('rail', '#WikiaRail') );
    }
 
    if ( $('.discord-container').length ) {
        $('.discord-container').each(function() {
            getData( settings, new Container('box', $(this)) );
        });
    }
 
    if ( cfg.wgPageName === "MediaWiki:Custom-Discord-Module-Settings" ) {
        visualSettings(settings);
    }
});
 
});
Community content is available under CC-BY-SA unless otherwise noted.