by David_Goggins
当前为
// ==UserScript==
// @name Скрипт для КФ (биографии)
// @namespace https://forum.blackrussia.online/
// @version 1.2.4
// @description by David_Goggins
// @author David_Goggins
// @match https://forum.blackrussia.online/threads/*
// @include https://forum.blackrussia.online/threads/*
// @match https://forum.blackrussia.online/forums*
// @include https://forum.blackrussia.online/forums
// @grant none
// @license MIT
// @collaborator Kuk
// @icon https://avatars.mds.yandex.net/i?id=e7371f38fb4d7fe174b4362d628c7f74-4988204-images-thumbs&n=13
// @copyright 2021, Kuk (https://openuserjs.org/users/Kuk)
// ==/UserScript==
// ==UserScript==
// @name Goggins (RP-Биографии)
// @namespace https://forum.blackrussia.online/
// @version 25.8
// @description Удалены приветствие и разделитель. Заголовок модального окна отцентрирован и без двоеточия.
// @author David_Goggins / Artem_Gogol (Финальное Объединение)
// @match https://forum.blackrussia.online/threads/*
// @grant none
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @require https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js
// ==/UserScript==
(function() {
'use strict';
// --- КОНСТАНТЫ ПРЕФИКСОВ (ИЗ КОДА 1/2) ---
const VAJNO_PREFIX = 1;
const NARASSSMOTRENII_PREFIX = 2;
const BEZPREFIXA_PREFIX = 3;
const OTKAZANO_PREFIX = 4;
const REALIZOVANNO_PREFIX = 5;
const RESHENO_PREFIX = 6;
const ZAKRITO_PREFIX = 7;
const ODOBRENO_PREFIX = 8;
const RASSMORTENO_PREFIX = 9;
const KOMANDEPROEKTA_PREFIX = 10;
const SPECADMINY_PREFIX = 11;
const GLAVNOMYADMINY_PREFIX = 12;
const TEXSPECY_PREFIX = 13;
const OJIDANIE_PREFIX = 14;
const PROVERENOKONTRKACH_PREFIX = 15;
// --- ССЫЛКИ НА БАННЕРЫ (ДИЗАЙН ИЗ КОДА 1) ---
const APPROVED_BANNER_URL = 'https://i.postimg.cc/sgkL5vvb/1618083711121.png';
const NEW_BANNER_BBCODE = '[B][CENTER][url=https://postimages.org/][img]' + APPROVED_BANNER_URL + '[/img][/url][/CENTER][/B]';
const FOOTER_LINKS =
'[RIGHT][B][COLOR=#ff0000]Полезные ссылки.[/COLOR][/B]\n' +
"[SIZE=3][FONT=georgia]Заявление на пост Агента Поддержки - [URL]https://forum.blackrussia.online/forums/%D0%90%D0%B3%D0%B5%D0%BD%D1%82%D1%8B-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B8.3173/[/URL]\n" +
"Заявление на пост Лидера - [URL]https://forum.blackrussia.online/forums/%D0%9B%D0%B8%D0%B4%D0%B5%D1%80%D1%8B.3174/[/URL][/FONT][/SIZE][/RIGHT]";
// --- ФУНКЦИИ ГЕНЕРАЦИИ КОНТЕНТА (ДИЗАЙН ИЗ КОДА 1) ---
// RP-Био Отказы
function generateRejectionContent(reasonText) {
return (
NEW_BANNER_BBCODE + "\n\n" +
"[B][CENTER][COLOR=#ff0000]Доброго времени суток уважаемый {{ user.name }}[/COLOR][/CENTER][/B]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Ваша RolePlay биография была проверена, но есть моменты для доработки![/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Статус: [COLOR=#FF0000]❌ Отказано.[/COLOR][/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=4][COLOR=#000000]Убедительная просьба ознакомиться [URL='https://forum.blackrussia.online/threads/Правила-составления-rp-биографии.13425782/']с правилами написания RolePlay биографий.[/URL][/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Причина отказа: [COLOR=#FF0000]" + reasonText + "[/COLOR][/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Анализируйте ошибки![/COLOR][/SIZE][/CENTER]\n\n" +
NEW_BANNER_BBCODE
);
}
// RP-Биографии: Одобрено
const approvalContent =
NEW_BANNER_BBCODE + "\n\n" +
"[B][CENTER][COLOR=#ff0000]Доброго времени суток уважаемый {{ user.name }}[/COLOR][/CENTER][/B]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Ваша RolePlay биография была проверена и получает статус: [COLOR=#00FF00]✔️ Одобрено.[/COLOR][/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Приятной игры![/COLOR][/SIZE][/CENTER]\n\n" +
NEW_BANNER_BBCODE + "\n\n" +
FOOTER_LINKS;
// RP-Биографии: На доработке
const reworkContent =
NEW_BANNER_BBCODE + "\n\n" +
"[B][CENTER][COLOR=#ff0000]Доброго времени суток уважаемый {{ user.name }}[/COLOR][/CENTER][/B]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Ваша RolePlay биография была проверена, но есть моменты для доработки![/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Статус: [COLOR=#FFC000]🟡 На доработке.[/COLOR][/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=4][COLOR=#000000]Вам даётся 24 часа на дополнение/исправление вашей RolePlay биографии.[/COLOR][/SIZE][/CENTER]\n\n" +
"[CENTER][SIZE=5][COLOR=#000000]Приятной игры![/COLOR][/SIZE][/CENTER]\n\n" +
NEW_BANNER_BBCODE;
// --- МАССИВ ШАБЛОНОВ RP-БИОГРАФИЙ (БЕЗ ПРИВЕТСТВИЯ И РАЗДЕЛИТЕЛЯ) ---
const buttons = [
// Удалено: { title: 'ПРИВЕТСТВИЕ', ... }
// Удалено: { title: '______________________________________RP БИОГРАФИИ_____________________________________' },
{ title: '✔️ БИОГРАФИЯ - ОДОБРЕНО', content: approvalContent, prefix: ODOBRENO_PREFIX, status: true },
{ title: '🟡 БИОГРАФИЯ - ДОРАБОТКА (24Ч)', content: reworkContent, prefix: NARASSSMOTRENII_PREFIX, status: true },
{ title: '❌ НЕ ДОРАБОТАЛ', content: generateRejectionContent("Вы не доработали RP биографию за данные вам 24 часа."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ БИОГРАФИЯ НЕ ПО ФОРМЕ', content: generateRejectionContent("Биография составлена не по форме."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ ЗАГОЛОВОК НЕ ПО ФОРМЕ', content: generateRejectionContent("Заголовок темы составлен не по форме.<br>Заполните его в формате: Биография | Nick_Name"), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ КОПИПАСТ', content: generateRejectionContent("Ваша биография скопирована.<br>Постарайтесь изложить свою идею."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ ОРФОГРАФИЯ', content: generateRejectionContent("Слишком много орфографических ошибок.<br>Проверьте свой текст на наличие ошибок в правописании."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ ПУНКТУАЦИЯ', content: generateRejectionContent("Слишком много пунктуационных ошибок.<br>В вашей биографии неправильно раставлены знаки препинания, либо они вовсе отсутсвуют."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ НАРУШЕНИЕ ПРАВИЛ ИГРЫ', content: generateRejectionContent("Запрещено указывать факторы, позволяющие игроку нарушать правила игры."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ МЕНЕЕ 200 СЛОВ', content: generateRejectionContent("Слишком мало RP информации.<br>Минимальный объем информации из жизни вашего персонажа 200 слов."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ БОЛЕЕ 600 СЛОВ', content: generateRejectionContent("Избыток RP информации.<br>Максимальный объем информации из жизни вашего персонажа 600 слов."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ НЕ ТОТ ШРИФТ/РАЗМЕР', content: generateRejectionContent("Нарушен шрифт текста и/или его размер.<br>Ваша биография должно быть написана шрифтами Verdana или Times New Roman с минимальным размером 15."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ СВЕРХСПОСОБНОСТИ', content: generateRejectionContent("Запрещено придавать персонажу нереалистичные свойства."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ НЕТ ВИДЕО- ФОТОФРАГМЕНТОВ', content: generateRejectionContent("В биографии должна присутствовать хотя бы одна фотография, поясняющая вашу биографию/вашего персонажа.<br>Например, это может быть фотография вашего персонажа."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ НАРУШЕНИЕ ПОЛИТИКИ/ЭКСТРЕМИЗМ', content: generateRejectionContent("Ваша биография включает в себя запрещённую тематику.<br>Запрещено упоминание различных группировок, психотропных и подобных веществ, экстремитских и националистических лозунгов."), prefix: OTKAZANO_PREFIX, status: true },
{ title: '❌ ОБЩИЙ ОТКАЗ (СВОЙ ВАРИАНТ)', content: generateRejectionContent("..."), prefix: OTKAZANO_PREFIX, status: false },
];
// --- СЧЕТЧИКИ (ОСТАВЛЕНЫ) ---
var titles = document.getElementsByClassName('structItem-title');
var count_ojidanie = 0;
var count_ga = 0;
var count_na_rassmotrenii = 0;
var count_sa = 0;
for (var i = 0; i < titles.length; i++) {
var prefix_ojidanie = titles[i].querySelector('.labelLink .label--silver');
if (prefix_ojidanie && prefix_ojidanie.textContent.trim() === 'Ожидание') {
count_ojidanie++;
}
var prefix_ga = titles[i].querySelector('.label.label--red');
if (prefix_ga && prefix_ga.textContent.trim() === 'Главному администратору') {
count_ga++;
}
var prefix_na_rassmotrenii = titles[i].querySelector('.label.label--orange');
if (prefix_na_rassmotrenii && prefix_na_rassmotrenii.textContent.trim() === 'На рассмотрении') {
count_na_rassmotrenii++;
}
var prefix_sa = titles[i].querySelector('.label.label--accent');
if (prefix_sa && prefix_sa.textContent.trim() === 'Специальному администратору') {
count_sa++;
}
}
function getColor(count) {
if (count < 7) {
return 'lime';
} else if (count >= 7 && count < 15) {
return 'orange';
} else {
return 'red';
}
}
var headers = document.getElementsByClassName('block-minorHeader uix_threadListSeparator');
if (headers.length > 0) {
var firstHeader = headers[0];
var secondHeader = headers[1];
var countElementGA = document.createElement('span');
countElementGA.style.marginLeft = '10px';
countElementGA.style.fontSize = '1.4rem';
countElementGA.style.color = getColor(count_ga);
countElementGA.textContent = 'Глав.Админу: ' + count_ga + ' ||';
var countElementNaRassmotrenii = document.createElement('span');
countElementNaRassmotrenii.style.marginLeft = '10px';
countElementNaRassmotrenii.style.fontSize = '1.4rem';
countElementNaRassmotrenii.style.color = getColor(count_na_rassmotrenii);
countElementNaRassmotrenii.textContent = 'На рассмотрении: ' + count_na_rassmotrenii + ' ||';
var countElementSA = document.createElement('span');
countElementSA.style.marginLeft = '10px';
countElementSA.style.fontSize = '1.4rem';
countElementSA.style.color = getColor(count_sa);
countElementSA.textContent = 'Спец.Админу: ' + count_sa;
var arrowIcon = firstHeader.querySelector('.uix_threadCollapseTrigger');
if (arrowIcon) {
firstHeader.insertBefore(countElementGA, arrowIcon);
firstHeader.insertBefore(countElementNaRassmotrenii, arrowIcon);
firstHeader.insertBefore(countElementSA, arrowIcon);
} else {
firstHeader.appendChild(countElementGA);
firstHeader.appendChild(countElementNaRassmotrenii);
firstHeader.appendChild(countElementSA);
}
var countElementOjidanie = document.createElement('span');
countElementOjidanie.style.marginLeft = '10px';
countElementOjidanie.style.fontSize = '1.4rem';
countElementOjidanie.style.color = getColor(count_ojidanie);
countElementOjidanie.textContent = 'Ожидание: ' + count_ojidanie;
if (secondHeader) {
arrowIcon = secondHeader.querySelector('.uix_threadCollapseTrigger');
if (arrowIcon) {
secondHeader.insertBefore(countElementOjidanie, arrowIcon);
} else {
secondHeader.appendChild(countElementOjidanie);
}
}
}
// --- ФУНКЦИОНАЛ ИЗ КОДА 2 ---
function getFormData(data) {
const formData = new FormData();
Object.entries(data).forEach(i => formData.append(i[0], i[1]));
return formData;
}
function editThreadData(prefix, pin = false) {
const threadTitle = $('.p-title-value')[0].lastChild.textContent.trim();
if (typeof XF === 'undefined' || !XF.config || !XF.config.csrf) {
console.error('Ошибка: Не найдены переменные XF. Невозможно сменить префикс.');
return;
}
const data = {
prefix_id: prefix,
title: threadTitle,
_xfToken: XF.config.csrf,
_xfRequestUri: document.URL.split(XF.config.url.fullBase)[1],
_xfWithData: 1,
_xfResponseType: 'json',
};
if (pin === true) {
data.sticky = 1;
}
fetch(`${document.URL}edit`, {
method: 'POST',
body: getFormData(data),
}).then(() => location.reload()).catch(error => console.error('Ошибка при смене префикса:', error));
}
function getThreadData() {
const usernameElement = $('a.username')[0];
if (!usernameElement) {
return { user: { id: 'Unknown', name: 'Уважаемый пользователь', mention: 'Уважаемый пользователь' } };
}
const authorID = usernameElement.attributes['data-user-id']?.nodeValue || 'UnknownID';
const authorName = $(usernameElement).text().trim() || 'Уважаемый пользователь';
const hours = new Date().getHours();
return {
user: {
id: authorID,
name: authorName,
mention: `[USER=${authorID}]${authorName}[/USER]`,
},
greeting: () =>
4 < hours && hours <= 11
? 'Доброе утро'
: 11 < hours && hours <= 15
? 'Добрый день'
: 15 < hours && hours <= 21
? 'Добрый вечер'
: 'Доброй ночи',
};
}
// Кнопка с прозрачным фоном (для сохранения стиля главной кнопки)
function addButton(name, id) {
$('.button--icon--reply').before(
`<button type="button" class="button rippleButton" id="${id}" style="background: transparent !important; background-image: none !important; margin: 10px; border: none; border-radius: 10px; color: white !important;">${name}</button>`,
);
}
// ИСПРАВЛЕННАЯ ФУНКЦИЯ: Сетка кнопок и прозрачные разделители (Grid)
function buttonsMarkup(buttons) {
// Устанавливаем отступы между кнопками и используем flex/grid для расположения
return `<div class="select_answer" style="display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 5px; color: white;">
${buttons.map(
(btn, i) => {
if (btn.content === undefined) {
// Разделители: прозрачный фон, белый текст, занимают всю ширину
return `<div style="text-align: center; font-weight: bold; padding: 10px 0; color: white; background-color: transparent; margin: 5px 0; flex-basis: 100%; border: none;">${btn.title.replace(/_/g, '').replace(/-/g, '').trim()}</div>`;
} else {
// Кнопки-шаблоны: равномерная ширина для 3-4 столбцов (как на скриншоте)
return `<button id="answers-${i}" class="button--primary button rippleButton" style="
margin: 5px;
flex: 1 1 calc(33.33% - 5px);
min-width: 150px;
text-align: center;
background-color: rgba(255, 255, 255, 0.1) !important;
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
">
<span class="button-text">${btn.title}</span>
</button>`;
}
}
).join('')}
</div>`;
}
// Функция вставки контента и автоотправки (Логика из Кода 2)
function pasteContent(id, data = {}, send = false) {
if (buttons[id].content === undefined) return;
const template = Handlebars.compile(buttons[id].content);
if ($('.fr-element.fr-view p').text().trim() === '') $('.fr-element.fr-view p').empty();
$('span.fr-placeholder').empty();
const contentToPaste = template(data).replace(/\n/g, '<br>');
$('div.fr-element.fr-view p').append(contentToPaste);
// ЗАКРЫТИЕ ОКНА: (как в Коде 2)
$('a.overlay-titleCloser').trigger('click');
if (send === true) {
editThreadData(buttons[id].prefix, false);
setTimeout(() => {
$('.button--icon.button--icon--reply.rippleButton').trigger('click');
}, 100);
}
}
// --- ЗАПУСК СКРИПТА ---
$(document).ready(() => {
if (typeof Handlebars === 'undefined') {
$('body').append('<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>');
}
if (typeof XF === 'undefined' || typeof jQuery === 'undefined' || typeof XF.alert === 'undefined') {
return;
}
const threadData = getThreadData();
const mainButtonId = 'goggins_rp_bio_templates';
// Добавляем ТОЛЬКО ОДНУ кнопку шаблонов (с прозрачным фоном)
addButton('Шаблоны RP Биографий', mainButtonId);
// Обработчик для основной кнопки шаблонов
$(`button#${mainButtonId}`).click(() => {
// 1. Изменяем заголовок и открываем модальное окно
const customTitle = 'Выберите шаблон RP Биографии';
XF.alert(buttonsMarkup(buttons), null, customTitle);
// 2. Стиль для заголовка модального окна: по центру и без двоеточия (XF.alert добавляет двоеточие, его трудно удалить, но мы его центрируем)
const $modalTitle = $('.overlay-title:contains("' + customTitle + '")');
if ($modalTitle.length) {
$modalTitle.text(customTitle); // Удаление двоеточия (XF.alert добавляет его после текста)
$modalTitle.css({
'text-align': 'center',
'background-color': 'transparent',
'color': 'white'
});
}
// 3. КОД ДЛЯ ПРОЗРАЧНОСТИ ФОНА МОДАЛЬНОГО ОКНА:
$('.overlay-content').css({
'background-color': 'rgba(29, 31, 33, 0.85)', // Очень темный, полупрозрачный
'color': 'white'
});
$('.overlay-container').css({
'background-color': 'transparent',
});
// Привязываем обработчики кликов к кнопкам внутри модального окна (Логика из Кода 2)
buttons.forEach((btn, id) => {
if (btn.content === undefined) return;
$(document).off('click', `#answers-${id}`);
$(document).on('click', `#answers-${id}`, function() {
const send = buttons[id].status;
pasteContent(id, threadData, send);
});
});
});
// --- СЧЕТЧИКИ ---
// (Оставлены для совместимости)
var titles = document.getElementsByClassName('structItem-title');
var count_ojidanie = 0;
var count_ga = 0;
var count_na_rassmotrenii = 0;
var count_sa = 0;
for (var i = 0; i < titles.length; i++) {
var prefix_ojidanie = titles[i].querySelector('.labelLink .label--silver');
if (prefix_ojidanie && prefix_ojidanie.textContent.trim() === 'Ожидание') {
count_ojidanie++;
}
var prefix_ga = titles[i].querySelector('.label.label--red');
if (prefix_ga && prefix_ga.textContent.trim() === 'Главному администратору') {
count_ga++;
}
var prefix_na_rassmotrenii = titles[i].querySelector('.label.label--orange');
if (prefix_na_rassmotrenii && prefix_na_rassmotrenii.textContent.trim() === 'На рассмотрении') {
count_na_rassmotrenii++;
}
var prefix_sa = titles[i].querySelector('.label.label--accent');
if (prefix_sa && prefix_sa.textContent.trim() === 'Специальному администратору') {
count_sa++;
}
}
function getColor(count) {
if (count < 7) {
return 'lime';
} else if (count >= 7 && count < 15) {
return 'orange';
} else {
return 'red';
}
}
var headers = document.getElementsByClassName('block-minorHeader uix_threadListSeparator');
if (headers.length > 0) {
var firstHeader = headers[0];
var secondHeader = headers[1];
var countElementGA = document.createElement('span');
countElementGA.style.marginLeft = '10px';
countElementGA.style.fontSize = '1.4rem';
countElementGA.style.color = getColor(count_ga);
countElementGA.textContent = 'Глав.Админу: ' + count_ga + ' ||';
var countElementNaRassmotrenii = document.createElement('span');
countElementNaRassmotrenii.style.marginLeft = '10px';
countElementNaRassmotrenii.style.fontSize = '1.4rem';
countElementNaRassmotrenii.style.color = getColor(count_na_rassmotrenii);
countElementNaRassmotrenii.textContent = 'На рассмотрении: ' + count_na_rassmotrenii + ' ||';
var countElementSA = document.createElement('span');
countElementSA.style.marginLeft = '10px';
countElementSA.style.fontSize = '1.4rem';
countElementSA.style.color = getColor(count_sa);
countElementSA.textContent = 'Спец.Админу: ' + count_sa;
var arrowIcon = firstHeader.querySelector('.uix_threadCollapseTrigger');
if (arrowIcon) {
firstHeader.insertBefore(countElementGA, arrowIcon);
firstHeader.insertBefore(countElementNaRassmotrenii, arrowIcon);
firstHeader.insertBefore(countElementSA, arrowIcon);
} else {
firstHeader.appendChild(countElementGA);
firstHeader.appendChild(countElementNaRassmotrenii);
firstHeader.appendChild(countElementSA);
}
var countElementOjidanie = document.createElement('span');
countElementOjidanie.style.marginLeft = '10px';
countElementOjidanie.style.fontSize = '1.4rem';
countElementOjidanie.style.color = getColor(count_ojidanie);
countElementOjidanie.textContent = 'Ожидание: ' + count_ojidanie;
if (secondHeader) {
arrowIcon = secondHeader.querySelector('.uix_threadCollapseTrigger');
if (arrowIcon) {
secondHeader.insertBefore(countElementOjidanie, arrowIcon);
} else {
secondHeader.appendChild(countElementOjidanie);
}
}
}
});
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址