Обновление всех файлов с ESLint
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env", "@babel/preset-typescript"],
|
||||||
|
"plugins": ["@babel/plugin-transform-optional-chaining"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "google"],
|
||||||
|
"parser": "@babel/eslint-parser",
|
||||||
|
"globals": {
|
||||||
|
"window": true,
|
||||||
|
"$": true,
|
||||||
|
"jQuery": true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-undef": "off",
|
||||||
|
"getter-return": "off",
|
||||||
|
"indent": "off",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"new-cap": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -161,14 +161,14 @@ window.AprilJokes.settings = {
|
|||||||
variants: {
|
variants: {
|
||||||
adj: {
|
adj: {
|
||||||
...window.AprilJokes.settings.stupid_title.variants.adj,
|
...window.AprilJokes.settings.stupid_title.variants.adj,
|
||||||
...BuildStupdiTitleVariant(true, "скромный, шутливый, !грубый"),
|
...BuildStupidTitleVariant(true, "скромный, шутливый, !грубый"),
|
||||||
...BuildStupdiTitleVariant(false, "скромная, шутливая, !грубая"),
|
...BuildStupidTitleVariant(false, "скромная, шутливая, !грубая"),
|
||||||
},
|
},
|
||||||
noun: { ...window.AprilJokes.settings.stupid_title.variants.noun },
|
noun: {...window.AprilJokes.settings.stupid_title.variants.noun},
|
||||||
verb: { ...window.AprilJokes.settings.stupid_title.variants.verb },
|
verb: {...window.AprilJokes.settings.stupid_title.variants.verb},
|
||||||
place: { ...window.AprilJokes.settings.stupid_title.variants.place },
|
place: {...window.AprilJokes.settings.stupid_title.variants.place},
|
||||||
adv: { ...window.AprilJokes.settings.stupid_title.variants.adv },
|
adv: {...window.AprilJokes.settings.stupid_title.variants.adv},
|
||||||
p: { ...window.AprilJokes.settings.stupid_title.variants.p },
|
p: {...window.AprilJokes.settings.stupid_title.variants.p},
|
||||||
},
|
},
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+456
-207
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"name": "mybb-april-fools",
|
"name": "mybb-april-fools",
|
||||||
"description": "Система первоапрельских розыгрышей для форумов MyBB",
|
"description": "Система первоапрельских розыгрышей для форумов MyBB",
|
||||||
"homepage": "https://forumd.ru/viewtopic.php?id=7372",
|
"homepage": "https://forumd.ru/viewtopic.php?id=7372",
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"license": "https://forumd.ru/viewtopic.php?id=5751#rule",
|
"license": "https://forumd.ru/viewtopic.php?id=5751#rule",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.21.0",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.21.3",
|
"@babel/core": "^7.24.3",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.21.0",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/jquery": "^3.5.16",
|
"@types/jquery": "^3.5.16",
|
||||||
@@ -46,6 +46,8 @@
|
|||||||
"watch": "webpack --watch"
|
"watch": "webpack --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/eslint-parser": "^7.24.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
||||||
"cursor-effects": "^1.0.11",
|
"cursor-effects": "^1.0.11",
|
||||||
"jquery": "^3.6.4",
|
"jquery": "^3.6.4",
|
||||||
"webpack-utf8-bom": "^1.4.0"
|
"webpack-utf8-bom": "^1.4.0"
|
||||||
|
|||||||
+19
-8
@@ -1,14 +1,25 @@
|
|||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получение всех элементов, являющимися TextNode.
|
* Получение всех элементов, являющимися TextNode.
|
||||||
* Используется некоторыми шутками для уменьшения влияния на существующее DOM-дерево.
|
* Используется некоторыми шутками для уменьшения
|
||||||
|
* влияния на существующее DOM-дерево.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement | JQuery<HTMLElement> | JQuery.Selector} root
|
||||||
|
* Элемет, у которого необходимо найти текстовые ноды
|
||||||
|
*
|
||||||
|
* @return {JQuery<HTMLElement | Text | Comment | Document>}
|
||||||
*/
|
*/
|
||||||
export function getTextNodes(
|
export function getTextNodes(
|
||||||
root: any
|
root: HTMLElement | JQuery<HTMLElement> | JQuery.Selector,
|
||||||
): JQuery<HTMLElement | Text | Comment | Document> {
|
)
|
||||||
return $(root)
|
: JQuery<HTMLElement | Text | Comment | Document> {
|
||||||
.find("*")
|
// Это очень странный код, но надо успокоить ESLint
|
||||||
.contents()
|
const $root = (typeof root === 'string') ? $(root) : $(root);
|
||||||
.filter((_, node) => node.nodeType === Node.TEXT_NODE);
|
|
||||||
|
return $root.
|
||||||
|
find('*').
|
||||||
|
contents().
|
||||||
|
filter((_, node) => node.nodeType === Node.TEXT_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +1,70 @@
|
|||||||
import {
|
import {
|
||||||
StupidTitleVariants,
|
StupidTitleVariants,
|
||||||
BuildStupdiTitleVariant,
|
BuildStupidTitleVariant,
|
||||||
} from "../jokes/stupid_title";
|
} from '../jokes/stupid_title';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Метод, генерирующий стандартный список слов
|
||||||
|
* @param {StupidTitleVariants} vars
|
||||||
|
*/
|
||||||
export function StupidTitleDefaultVariants(vars: StupidTitleVariants) {
|
export function StupidTitleDefaultVariants(vars: StupidTitleVariants) {
|
||||||
vars.adj = {
|
vars.adj = {
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
true,
|
true,
|
||||||
"адекватный,$адский,активный,алчный,%ангельский,банальный,безнадёжный,$бесполезный,былой,верный,виртуальный,вкусный,воспитанный,выгодный,выходной,гигантский,$глупый,гордый,грамотный,громадный,грубый,далекий,двуличный,деятельный,доброжелательный,$жалкий,жёсткий,жестокий,$жирный,заинтересованный,запасной,застенчивый,знакомый,иностранный,истинный,конструктивный,креативный,ласковый,любимый,мелочный,^мирный,мстительный,небесный,невозможный,независимый,низкий,нужный,объективный,обыкновенный,опрятный,^оригинальный,особенный,острый,откровенный,открытый,пестрый,повседневный,подземный,пожилой,показательный,последний,посторонний,провинциальный,пышный,робкий,родной,самовлюблённый,северный,седой,семейный,серьёзный,сногсшибательный,^солнечный,спокойный,суровый,терпеливый,уверенный в себе,ударный,^удачливый,формальный,хладнокровный,целый,чистый,чрезвычайный,чужой,южный"
|
// eslint-disable-next-line max-len
|
||||||
|
'адекватный,$адский,активный,алчный,%ангельский,банальный,безнадёжный,$бесполезный,былой,верный,виртуальный,вкусный,воспитанный,выгодный,выходной,гигантский,$глупый,гордый,грамотный,громадный,грубый,далекий,двуличный,деятельный,доброжелательный,$жалкий,жёсткий,жестокий,$жирный,заинтересованный,запасной,застенчивый,знакомый,иностранный,истинный,конструктивный,креативный,ласковый,любимый,мелочный,^мирный,мстительный,небесный,невозможный,независимый,низкий,нужный,объективный,обыкновенный,опрятный,^оригинальный,особенный,острый,откровенный,открытый,пестрый,повседневный,подземный,пожилой,показательный,последний,посторонний,провинциальный,пышный,робкий,родной,самовлюблённый,северный,седой,семейный,серьёзный,сногсшибательный,^солнечный,спокойный,суровый,терпеливый,уверенный в себе,ударный,^удачливый,формальный,хладнокровный,целый,чистый,чрезвычайный,чужой,южный'
|
||||||
),
|
),
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
false,
|
false,
|
||||||
"адекватная,$адская,активная,алчная,%ангельская,банальная,безнадёжная,$бесполезная,былая,верная,виртуальная,вкусная,воспитанная,выгодная,выходная,гигантская,$глупая,гордая,грамотная,громадная,грубая,далекая,двуличная,деятельная,доброжелательная,$жалкая,жёсткая,жестокая,$жирная,заинтересованная,запасная,застенчивая,знакомая,иностранная,истинная,конструктивная,креативная,ласковая,любимая,мелочная,^мирная,мстительная,небесная,невозможная,независимая,низкая,нужная,объективная,обыкновенная,опрятная,^оригинальная,особенная,острая,откровенная,открытая,пестрая,повседневная,подземная,пожилая,показательная,последняя,посторонняя,провинциальная,пышная,робкая,родная,самовлюблённая,северная,седая,семейная,серьезная,сногсшибательная,^солнечная,спокаяная,суровая,терпеливая,уверенная в себе,ударная,^удачливая,формальная,хладнокровная,целая,чистая,чрезвычайная,чужая,южная"
|
// eslint-disable-next-line max-len
|
||||||
|
'адекватная,$адская,активная,алчная,%ангельская,банальная,безнадёжная,$бесполезная,былая,верная,виртуальная,вкусная,воспитанная,выгодная,выходная,гигантская,$глупая,гордая,грамотная,громадная,грубая,далекая,двуличная,деятельная,доброжелательная,$жалкая,жёсткая,жестокая,$жирная,заинтересованная,запасная,застенчивая,знакомая,иностранная,истинная,конструктивная,креативная,ласковая,любимая,мелочная,^мирная,мстительная,небесная,невозможная,независимая,низкая,нужная,объективная,обыкновенная,опрятная,^оригинальная,особенная,острая,откровенная,открытая,пестрая,повседневная,подземная,пожилая,показательная,последняя,посторонняя,провинциальная,пышная,робкая,родная,самовлюблённая,северная,седая,семейная,серьезная,сногсшибательная,^солнечная,спокаяная,суровая,терпеливая,уверенная в себе,ударная,^удачливая,формальная,хладнокровная,целая,чистая,чрезвычайная,чужая,южная'
|
||||||
),
|
),
|
||||||
...vars.adj,
|
...vars.adj,
|
||||||
};
|
};
|
||||||
vars.noun = {
|
vars.noun = {
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
true,
|
true,
|
||||||
"актёр,$балбес,бард,басурманин,борец,бродяга,бруталище,волк,дворф,%дед,%дедушка,джентльмен,диван,динозавр,дракон,ёж,%ёжик,жук,зайц,$злоумышленник,зомби,карасик,кентавр,кит,кот,кролик,кулак,лев,ледник,лесоруб,%мальчег,мальчик,манекен,массажист,мачо,монах,монстр,наследник,ниндзя,носорог,одиночка,организм,орёл,отец,принц,проказник,пузырь,$раб,рыцарь,спортсмен,сурикат,сын,%сынок,тигр,товарищ,хоббит,эльф"
|
// eslint-disable-next-line max-len
|
||||||
|
'актёр,$балбес,бард,басурманин,борец,бродяга,бруталище,волк,дворф,%дед,%дедушка,джентльмен,диван,динозавр,дракон,ёж,%ёжик,жук,зайц,$злоумышленник,зомби,карасик,кентавр,кит,кот,кролик,кулак,лев,ледник,лесоруб,%мальчег,мальчик,манекен,массажист,мачо,монах,монстр,наследник,ниндзя,носорог,одиночка,организм,орёл,отец,принц,проказник,пузырь,$раб,рыцарь,спортсмен,сурикат,сын,%сынок,тигр,товарищ,хоббит,эльф'
|
||||||
),
|
),
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
false,
|
false,
|
||||||
"актриса,акула,$бабка,бабочка,%бабушка,бактерия,белочка,бусинка,валькирия,$ведьма,волторна,волчица,горгулья,дворфиха,девочка,деревяшка,детка,%деффачка,%дочка,дочь,заноза,$злоумышленница,знаменитость,каруселька,килька,конфетка,косточка,кошка,красотка,крышка,леди,$личинка,львица,мать,машина,милашка,монашка,мышь,наследница,орлица,панда,пиранья,принцесса,простуда,$рабыня,русалочка,рыбка,рыбка,скамеечка,спортсменка,тигрица,травка,черепашка,чертовка,эльфийка"
|
// eslint-disable-next-line max-len
|
||||||
|
'актриса,акула,$бабка,бабочка,%бабушка,бактерия,белочка,бусинка,валькирия,$ведьма,волторна,волчица,горгулья,дворфиха,девочка,деревяшка,детка,%деффачка,%дочка,дочь,заноза,$злоумышленница,знаменитость,каруселька,килька,конфетка,косточка,кошка,красотка,крышка,леди,$личинка,львица,мать,машина,милашка,монашка,мышь,наследница,орлица,панда,пиранья,принцесса,простуда,$рабыня,русалочка,рыбка,рыбка,скамеечка,спортсменка,тигрица,травка,черепашка,чертовка,эльфийка'
|
||||||
),
|
),
|
||||||
...vars.noun,
|
...vars.noun,
|
||||||
};
|
};
|
||||||
vars.verb = {
|
vars.verb = {
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
null,
|
null,
|
||||||
"бежит,берёт и делает,болеет,встаёт,говорит,думает,забывает,замирает,заходит,идёт,%имеет план и придерживается его,ловит,меняется,молчит,нарушает,оглядывается,орёт,освобождает,отвечает,отказаться куда-то идти,отказывается,отказывается вставать,отказывается что-то делать,оформляет,плывёт,поглядывает,поздравляет,поздравляет,получает,прибывает,приказывает,просыпается,прощает,работает,радуется,скрывается,снимает,снимает,снимается в сериале,снимается в фильме,собирается,соединяет,спрашивает,тянет,указывает,учит,читает,что-то скрывает,чувствует опасность,шепчет"
|
// eslint-disable-next-line max-len
|
||||||
|
'бежит,берёт и делает,болеет,встаёт,говорит,думает,забывает,замирает,заходит,идёт,%имеет план и придерживается его,ловит,меняется,молчит,нарушает,оглядывается,орёт,освобождает,отвечает,отказаться куда-то идти,отказывается,отказывается вставать,отказывается что-то делать,оформляет,плывёт,поглядывает,поздравляет,поздравляет,получает,прибывает,приказывает,просыпается,прощает,работает,радуется,скрывается,снимает,снимает,снимается в сериале,снимается в фильме,собирается,соединяет,спрашивает,тянет,указывает,учит,читает,что-то скрывает,чувствует опасность,шепчет'
|
||||||
),
|
),
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
true,
|
true,
|
||||||
"взял и сделал,додумался,женился,женится,заработался,не спал,не успел,обиделся,познал дзен,присел,проснулся,скрылся,смог,успел"
|
// eslint-disable-next-line max-len
|
||||||
|
'взял и сделал,додумался,женился,женится,заработался,не спал,не успел,обиделся,познал дзен,присел,проснулся,скрылся,смог,успел'
|
||||||
),
|
),
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
false,
|
false,
|
||||||
"взяла и сделала,выходит замуж,вышла замуж,додумалась,заработалась,не спала,не успела,обиделась,познала дзен,присела,проснулась,скрылась,смогла,успела"
|
// eslint-disable-next-line max-len
|
||||||
|
'взяла и сделала,выходит замуж,вышла замуж,додумалась,заработалась,не спала,не успела,обиделась,познала дзен,присела,проснулась,скрылась,смогла,успела'
|
||||||
),
|
),
|
||||||
...vars.verb,
|
...vars.verb,
|
||||||
};
|
};
|
||||||
vars.place = {
|
vars.place = {
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
null,
|
null,
|
||||||
"в джунглях,в квартире,в космосе,в лесу,в очереди,в пустыне,в театре,%в тёплой и уютной квартире,в филармонии,где-то,на заснеженной вершине,на конференции,на пляже,на форуме,под водой,под дождём,%под проливным дождём"
|
// eslint-disable-next-line max-len
|
||||||
|
'в джунглях,в квартире,в космосе,в лесу,в очереди,в пустыне,в театре,%в тёплой и уютной квартире,в филармонии,где-то,на заснеженной вершине,на конференции,на пляже,на форуме,под водой,под дождём,%под проливным дождём'
|
||||||
),
|
),
|
||||||
...vars.place,
|
...vars.place,
|
||||||
};
|
};
|
||||||
vars.adv = {
|
vars.adv = {
|
||||||
...BuildStupdiTitleVariant(
|
...BuildStupidTitleVariant(
|
||||||
null,
|
null,
|
||||||
"безрассудно,быстро,внезапно,вновь,$грубо,грустно,медленно,%молниеносно,немедленно,опять,осмысленно,позже,предсказуемо,расчётливо,регулярно,счастливо,уже,уныло"
|
// eslint-disable-next-line max-len
|
||||||
|
'безрассудно,быстро,внезапно,вновь,$грубо,грустно,медленно,%молниеносно,немедленно,опять,осмысленно,позже,предсказуемо,расчётливо,регулярно,счастливо,уже,уныло'
|
||||||
),
|
),
|
||||||
...vars.adv,
|
...vars.adv,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
}
|
}
|
||||||
.april-fools__joke:before {
|
.april-fools__joke:before {
|
||||||
display: block;
|
display: block;
|
||||||
content: "";
|
|
||||||
flex: 0 0 2ch;
|
flex: 0 0 2ch;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
content: "✔";
|
content: "✔";
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
style="display: none"
|
style="display: none"
|
||||||
/>
|
/>
|
||||||
<label class="april-fools__joke" for="april-fools__joke-${joke.id}">
|
<label class="april-fools__joke" for="april-fools__joke-${joke.id}">
|
||||||
<p class="april-fools__joke-title">${joke.title}</p>
|
<span class="april-fools__joke-title">${joke.title}</span>
|
||||||
<p class="april-fools__joke-description">${joke.description}</p>
|
<span class="april-fools__joke-description">${joke.description}</span>
|
||||||
<p class="april-fools__joke-chance">${joke.settings.chance}%</p>
|
<span class="april-fools__joke-chance">${joke.settings.chance}%</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+9
-8
@@ -47,7 +47,7 @@ export abstract class Joke<T extends JokeSettings> {
|
|||||||
/**
|
/**
|
||||||
* Запись новых настроек
|
* Запись новых настроек
|
||||||
*
|
*
|
||||||
* @param settings
|
* @param {JokeSettings} settings
|
||||||
*/
|
*/
|
||||||
set settings(settings: T) {
|
set settings(settings: T) {
|
||||||
for (const entry of Object.entries(settings)) {
|
for (const entry of Object.entries(settings)) {
|
||||||
@@ -55,17 +55,18 @@ export abstract class Joke<T extends JokeSettings> {
|
|||||||
const value = entry[1];
|
const value = entry[1];
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case "name":
|
case 'name':
|
||||||
case "title":
|
case 'title':
|
||||||
this.title = value;
|
this.title = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "description":
|
case 'description':
|
||||||
this.description = value;
|
this.description = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
(<any>this._settings)[id] = value;
|
// eslint-disable-next-line
|
||||||
|
(this._settings as any)[id] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +75,7 @@ export abstract class Joke<T extends JokeSettings> {
|
|||||||
* Проверка вероятности
|
* Проверка вероятности
|
||||||
*
|
*
|
||||||
* @param {number} chance Вероятность срабатывания
|
* @param {number} chance Вероятность срабатывания
|
||||||
* @returns {boolean} Флаг срабатывания (true - сработало)
|
* @return {boolean} Флаг срабатывания (true - сработало)
|
||||||
*/
|
*/
|
||||||
check(chance: number): boolean {
|
check(chance: number): boolean {
|
||||||
return Math.random() < 0.01 * chance;
|
return Math.random() < 0.01 * chance;
|
||||||
@@ -96,7 +97,7 @@ export abstract class Joke<T extends JokeSettings> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Переключить блокировку шутки
|
* Переключить блокировку шутки
|
||||||
* @param value Новое значение
|
* @param {boolean | null} [value] Новое значение
|
||||||
*/
|
*/
|
||||||
toggle(value: boolean | null = null) {
|
toggle(value: boolean | null = null) {
|
||||||
this.settings.enabled = value === null ? !this.settings.enabled : value;
|
this.settings.enabled = value === null ? !this.settings.enabled : value;
|
||||||
@@ -111,7 +112,7 @@ export abstract class Joke<T extends JokeSettings> {
|
|||||||
/**
|
/**
|
||||||
* Объект, описывающий шутку, которая может быть остановлена
|
* Объект, описывающий шутку, которая может быть остановлена
|
||||||
*/
|
*/
|
||||||
export abstract class StopableJoke<T extends JokeSettings> extends Joke<T> {
|
export abstract class StoppableJoke<T extends JokeSettings> extends Joke<T> {
|
||||||
/**
|
/**
|
||||||
* Остановка шутки, если возможно
|
* Остановка шутки, если возможно
|
||||||
*/
|
*/
|
||||||
|
|||||||
+121
-97
@@ -1,6 +1,6 @@
|
|||||||
import { stat } from "fs";
|
import './types/mybb.d.ts';
|
||||||
import { Joke, JokeSettings, StopableJoke } from "./joke";
|
import {Joke, JokeSettings, StoppableJoke} from './joke';
|
||||||
import { JokerUI } from "./ui";
|
import {JokerUI} from './ui';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Блок обработки перво-апрельских шуток
|
* Блок обработки перво-апрельских шуток
|
||||||
@@ -9,58 +9,14 @@ import { JokerUI } from "./ui";
|
|||||||
*/
|
*/
|
||||||
export class JokerClass {
|
export class JokerClass {
|
||||||
ui: JokerUI = new JokerUI(this);
|
ui: JokerUI = new JokerUI(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверка вероятности
|
* Общие настройки системы
|
||||||
*
|
|
||||||
* @param {number} chance Вероятность срабатывания
|
|
||||||
* @returns {boolean} Флаг срабатывания (true - сработало)
|
|
||||||
*/
|
*/
|
||||||
check(chance: number): boolean {
|
core_settings = new CoreSettings();
|
||||||
return Math.random() < 0.01 * chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Добавление шутки
|
* Перечисление всех шуток
|
||||||
*
|
|
||||||
* @param joke Объект шутки
|
|
||||||
*/
|
*/
|
||||||
add(joke: Joke<any>): void {
|
jokes: JokeMap = {};
|
||||||
this.jokes[joke.id] = joke;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Регистрация новой шутки
|
|
||||||
*
|
|
||||||
* @param id Идентификатор шутки
|
|
||||||
* @param handler Метод, выполняющий шутку
|
|
||||||
* @param settings Объект настроек шутки
|
|
||||||
*/
|
|
||||||
addCustom(
|
|
||||||
id: string,
|
|
||||||
handler: Function,
|
|
||||||
settings: JokeSettings | null = null
|
|
||||||
): Joke<JokeSettings> {
|
|
||||||
const joke = new (class extends Joke<JokeSettings> {
|
|
||||||
id = id;
|
|
||||||
|
|
||||||
title = "Пользовательская шутка";
|
|
||||||
|
|
||||||
description = "Для шутки не определено описание";
|
|
||||||
|
|
||||||
_settings = new JokeSettings();
|
|
||||||
|
|
||||||
start() {
|
|
||||||
handler.call(this, this.settings);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
joke.settings = settings;
|
|
||||||
|
|
||||||
this.add(joke);
|
|
||||||
|
|
||||||
return joke;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получение полного списка настроек
|
* Получение полного списка настроек
|
||||||
@@ -68,7 +24,7 @@ export class JokerClass {
|
|||||||
get settings(): SettingsMap {
|
get settings(): SettingsMap {
|
||||||
const result: SettingsMap = {};
|
const result: SettingsMap = {};
|
||||||
|
|
||||||
result["core"] = this.core_settings;
|
result['core'] = this.core_settings;
|
||||||
|
|
||||||
for (const entries of Object.entries(this.jokes)) {
|
for (const entries of Object.entries(this.jokes)) {
|
||||||
const id = entries[0];
|
const id = entries[0];
|
||||||
@@ -83,19 +39,75 @@ export class JokerClass {
|
|||||||
/**
|
/**
|
||||||
* Запись новых настроек
|
* Запись новых настроек
|
||||||
*
|
*
|
||||||
* @param settings
|
* @param {SettingsMap} settings
|
||||||
*/
|
*/
|
||||||
set settings(settings: SettingsMap) {
|
set settings(settings: SettingsMap) {
|
||||||
for (const entry of Object.entries(settings)) {
|
for (const entry of Object.entries(settings)) {
|
||||||
const id = entry[0];
|
const id = entry[0];
|
||||||
const jokeSettings = entry[1];
|
const jokeSettings = entry[1];
|
||||||
const targetSettings =
|
const targetSettings =
|
||||||
id === "core" ? this.core_settings : this.jokes[id].settings;
|
id === 'core' ? this.core_settings : this.jokes[id].settings;
|
||||||
|
|
||||||
Object.assign(targetSettings, jokeSettings);
|
Object.assign(targetSettings, jokeSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверка вероятности
|
||||||
|
*
|
||||||
|
* @param {number} chance Вероятность срабатывания
|
||||||
|
* @return {boolean} Флаг срабатывания (true - сработало)
|
||||||
|
*/
|
||||||
|
check(chance: number): boolean {
|
||||||
|
return Math.random() < 0.01 * chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавление шутки
|
||||||
|
*
|
||||||
|
* @param {Joke} joke Объект шутки
|
||||||
|
*/
|
||||||
|
add(joke: Joke<JokeSettings>): void {
|
||||||
|
this.jokes[joke.id] = joke;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрация новой шутки
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор шутки
|
||||||
|
* @param {JokeHandler} handler Метод, выполняющий шутку
|
||||||
|
* @param {JokeSettings | null} [settings] Объект настроек шутки
|
||||||
|
* @return {Joke<JokeSettings>} Объект шутки
|
||||||
|
*/
|
||||||
|
addCustom(
|
||||||
|
id: string,
|
||||||
|
handler: JokeHandler,
|
||||||
|
settings: JokeSettings | null = null,
|
||||||
|
): Joke<JokeSettings> {
|
||||||
|
const joke = new (class extends Joke<JokeSettings> {
|
||||||
|
id = id;
|
||||||
|
|
||||||
|
title = 'Пользовательская шутка';
|
||||||
|
|
||||||
|
description = 'Для шутки не определено описание';
|
||||||
|
|
||||||
|
_settings = new JokeSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Метод запуска шутки
|
||||||
|
*/
|
||||||
|
start() {
|
||||||
|
handler.call(this, this.settings);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
joke.settings = settings;
|
||||||
|
|
||||||
|
this.add(joke);
|
||||||
|
|
||||||
|
return joke;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Разблокировать систему
|
* Разблокировать систему
|
||||||
*/
|
*/
|
||||||
@@ -130,12 +142,15 @@ export class JokerClass {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Переключение шутки
|
* Переключение шутки
|
||||||
|
*
|
||||||
|
* @param {string} jokeId ID шутки для переключения
|
||||||
|
* @param {boolean} state Новое состояние
|
||||||
*/
|
*/
|
||||||
toggleJoke(joke_id: string, state: boolean) {
|
toggleJoke(jokeId: string, state: boolean) {
|
||||||
const joke = this.jokes[joke_id];
|
const joke = this.jokes[jokeId];
|
||||||
joke.settings.enabled = state;
|
joke.settings.enabled = state;
|
||||||
|
|
||||||
if (joke instanceof StopableJoke && !state) {
|
if (joke instanceof StoppableJoke && !state) {
|
||||||
joke.stop();
|
joke.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,23 +161,23 @@ export class JokerClass {
|
|||||||
* Сохранение пользовательских настроек
|
* Сохранение пользовательских настроек
|
||||||
*/
|
*/
|
||||||
saveUserStates() {
|
saveUserStates() {
|
||||||
const states: any = {};
|
const states: { [key in string]: boolean } = {};
|
||||||
|
|
||||||
for (const key of Object.keys(this.jokes)) {
|
for (const key of Object.keys(this.jokes)) {
|
||||||
states[key] = this.jokes[key].settings.enabled;
|
states[key] = this.jokes[key].settings.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(
|
fetch(
|
||||||
"/api.php?" +
|
'/api.php?' +
|
||||||
$.param({
|
$.param({
|
||||||
method: "storage.set",
|
method: 'storage.set',
|
||||||
user_id: (<any>window).UserID,
|
user_id: window.UserID,
|
||||||
key: "april-fools",
|
key: 'april-fools',
|
||||||
token: (<any>window).ForumAPITicket,
|
token: window.ForumAPITicket,
|
||||||
value: JSON.stringify(states),
|
value: JSON.stringify(states),
|
||||||
timer: 24 * 60,
|
timer: 24 * 60,
|
||||||
})
|
}),
|
||||||
);
|
).then((_) => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,12 +185,12 @@ export class JokerClass {
|
|||||||
*/
|
*/
|
||||||
async loadUserStates() {
|
async loadUserStates() {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
"/api.php?" +
|
'/api.php?' +
|
||||||
$.param({
|
$.param({
|
||||||
method: "storage.get",
|
method: 'storage.get',
|
||||||
user_id: (<any>window).UserID,
|
user_id: window.UserID,
|
||||||
key: "april-fools",
|
key: 'april-fools',
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
|
|
||||||
@@ -183,22 +198,25 @@ export class JokerClass {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = JSON.parse(json.response.storage.data["april-fools"]);
|
const data = JSON.parse(json.response.storage.data['april-fools']);
|
||||||
|
|
||||||
for (const key of Object.keys(this.jokes)) {
|
for (const key of Object.keys(this.jokes)) {
|
||||||
this.jokes[key].settings.enabled = data[key];
|
this.jokes[key].settings.enabled = data[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отчистка настроек пользователя
|
||||||
|
*/
|
||||||
async clearUserStates() {
|
async clearUserStates() {
|
||||||
await fetch(
|
await fetch(
|
||||||
"/api.php?" +
|
'/api.php?' +
|
||||||
$.param({
|
$.param({
|
||||||
method: "storage.delete",
|
method: 'storage.delete',
|
||||||
user_id: (<any>window).UserID,
|
user_id: window.UserID,
|
||||||
key: "april-fools",
|
key: 'april-fools',
|
||||||
token: (<any>window).ForumAPITicket,
|
token: window.ForumAPITicket,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -207,17 +225,15 @@ export class JokerClass {
|
|||||||
/**
|
/**
|
||||||
* Запуск шутки
|
* Запуск шутки
|
||||||
*
|
*
|
||||||
* @param id
|
* @param {string} jokeId ID шутки для запуска
|
||||||
* @param {boolean} forced
|
* @param {boolean} [forced] Принудительный запуск
|
||||||
*/
|
*/
|
||||||
start(id: string, forced: boolean = false) {
|
start(jokeId: string, forced: boolean = false) {
|
||||||
if (!(id in this.jokes)) return;
|
if (!(jokeId in this.jokes)) return;
|
||||||
|
|
||||||
const joke = this.jokes[id];
|
const joke = this.jokes[jokeId];
|
||||||
|
|
||||||
if (
|
if (!forced && (!joke.settings.enabled || !this.check(joke.settings.chance))
|
||||||
!forced &&
|
|
||||||
(!joke.settings.enabled || !this.check(joke.settings.chance))
|
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -227,6 +243,8 @@ export class JokerClass {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Запуск всех шуток
|
* Запуск всех шуток
|
||||||
|
*
|
||||||
|
* @param {boolean} [forced] Принудительный запуск
|
||||||
*/
|
*/
|
||||||
startAll(forced: boolean = false): void {
|
startAll(forced: boolean = false): void {
|
||||||
for (const key of Object.keys(this.jokes)) {
|
for (const key of Object.keys(this.jokes)) {
|
||||||
@@ -234,12 +252,17 @@ export class JokerClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Стандартная проверка 1 апреля
|
||||||
|
*
|
||||||
|
* @return {boolean} Флаг, должна ли запускаться система
|
||||||
|
*/
|
||||||
regularCheck(): boolean {
|
regularCheck(): boolean {
|
||||||
if (!this.core_settings.enabled) {
|
if (!this.core_settings.enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.core_settings.testers.indexOf((<any>window).UserID) >= 0) {
|
if (this.core_settings.testers.indexOf(window.UserID) >= 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,6 +277,9 @@ export class JokerClass {
|
|||||||
return this.check(this.core_settings.chance);
|
return this.check(this.core_settings.chance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Стандартный запуск 1 апреля
|
||||||
|
*/
|
||||||
async regularStart() {
|
async regularStart() {
|
||||||
if (!this.regularCheck()) {
|
if (!this.regularCheck()) {
|
||||||
return;
|
return;
|
||||||
@@ -263,23 +289,15 @@ export class JokerClass {
|
|||||||
this.ui.show();
|
this.ui.show();
|
||||||
this.startAll();
|
this.startAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Общие настройки системы
|
|
||||||
*/
|
|
||||||
core_settings = new CoreSettings();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Перечисление всех шуток
|
|
||||||
*/
|
|
||||||
jokes: JokeMap = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JokeHandler = () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Объект хранения шуток
|
* Объект хранения шуток
|
||||||
*/
|
*/
|
||||||
interface JokeMap {
|
interface JokeMap {
|
||||||
[key: string]: Joke<any>;
|
[key: string]: Joke< JokeSettings>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,9 +307,15 @@ interface SettingsMap {
|
|||||||
[key: string]: JokeSettings;
|
[key: string]: JokeSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общие правила системы
|
||||||
|
*/
|
||||||
class CoreSettings implements JokeSettings {
|
class CoreSettings implements JokeSettings {
|
||||||
chance = 100;
|
chance = 100;
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Список пользователей-тестировщиков
|
||||||
|
*/
|
||||||
testers: number[] = [];
|
testers: number[] = [];
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-12
@@ -1,6 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
import { JokerClass } from "../joker";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Карнавал**
|
* **Карнавал**
|
||||||
@@ -10,14 +9,17 @@ import { JokerClass } from "../joker";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class CarnivalJoke extends Joke<CarnivalJokeSettings> {
|
export class CarnivalJoke extends Joke<CarnivalJokeSettings> {
|
||||||
id = "carnival";
|
id = 'carnival';
|
||||||
|
|
||||||
title = "Карнавал";
|
title = 'Карнавал';
|
||||||
|
|
||||||
description = "Аватарки приобретают интересные цвета";
|
description = 'Аватарки приобретают интересные цвета';
|
||||||
|
|
||||||
_settings = new CarnivalJokeSettings();
|
_settings = new CarnivalJokeSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
$(this.settings.selector).each((_, elem) => {
|
$(this.settings.selector).each((_, elem) => {
|
||||||
const filters: string[] = [];
|
const filters: string[] = [];
|
||||||
@@ -29,19 +31,22 @@ export class CarnivalJoke extends Joke<CarnivalJokeSettings> {
|
|||||||
|
|
||||||
filters.push(
|
filters.push(
|
||||||
entry[0].replace(
|
entry[0].replace(
|
||||||
"{0}",
|
'{0}',
|
||||||
Math.round(Math.random() * entry[1]).toString()
|
Math.round(Math.random() * entry[1]).toString()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.length > 0) {
|
if (filters.length > 0) {
|
||||||
$(elem).css({ filter: filters.join(" ") });
|
$(elem).css({filter: filters.join(' ')});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Карнавал"
|
||||||
|
*/
|
||||||
export class CarnivalJokeSettings implements JokeSettings {
|
export class CarnivalJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@@ -61,10 +66,10 @@ export class CarnivalJokeSettings implements JokeSettings {
|
|||||||
* Список фильтров и диапозона случайных параметров
|
* Список фильтров и диапозона случайных параметров
|
||||||
*/
|
*/
|
||||||
variants: CarnivalJokeFilters = {
|
variants: CarnivalJokeFilters = {
|
||||||
"sepia({0}%)": 100,
|
'sepia({0}%)': 100,
|
||||||
"saturate({0}%)": 100,
|
'saturate({0}%)': 100,
|
||||||
"hue-rotate({0}deg)": 360,
|
'hue-rotate({0}deg)': 360,
|
||||||
"invert({0}%)": 100,
|
'invert({0}%)': 100,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Мама, Я сОшЛа С уМа!**
|
* **Мама, Я сОшЛа С уМа!**
|
||||||
@@ -9,21 +9,24 @@ import $ from "jquery";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class CrazyLettersJoke extends Joke<CrazyLettersJokeSettings> {
|
export class CrazyLettersJoke extends Joke<CrazyLettersJokeSettings> {
|
||||||
id = "crazy_letters";
|
id = 'crazy_letters';
|
||||||
|
|
||||||
title = "Мама, Я сОшЛа С уМа!";
|
title = 'Мама, Я сОшЛа С уМа!';
|
||||||
|
|
||||||
description = "иМеНа ЗаБоРчИкОм";
|
description = 'иМеНа ЗаБоРчИкОм';
|
||||||
|
|
||||||
_settings = new CrazyLettersJokeSettings();
|
_settings = new CrazyLettersJokeSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
$(this.settings.selector).each((_, elem) => {
|
$(this.settings.selector).each((_, elem) => {
|
||||||
let text = $(this).text();
|
const text = $(elem).text();
|
||||||
let result = "";
|
let result = '';
|
||||||
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
for (let i = 0; i < text.length; i++) {
|
||||||
result += text[i][i % 2 ? "toLowerCase" : "toUpperCase"]();
|
result += text[i][i % 2 ? 'toLowerCase' : 'toUpperCase']();
|
||||||
}
|
}
|
||||||
|
|
||||||
$(this).text(result);
|
$(this).text(result);
|
||||||
@@ -31,6 +34,9 @@ export class CrazyLettersJoke extends Joke<CrazyLettersJokeSettings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Мама, Я сОшЛа С уМа!"
|
||||||
|
*/
|
||||||
export class CrazyLettersJokeSettings implements JokeSettings {
|
export class CrazyLettersJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@@ -39,5 +45,5 @@ export class CrazyLettersJokeSettings implements JokeSettings {
|
|||||||
/**
|
/**
|
||||||
* Селектор всех элементов, которые будут затронуты
|
* Селектор всех элементов, которые будут затронуты
|
||||||
*/
|
*/
|
||||||
selector: string = ".pa-author a";
|
selector: string = '.pa-author a';
|
||||||
}
|
}
|
||||||
|
|||||||
+99
-67
@@ -1,8 +1,8 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
|
||||||
import $ from "jquery";
|
import {JokeSettings, StoppableJoke} from '../joke';
|
||||||
import { Interface } from "readline";
|
|
||||||
// import * as cursor_effects from "cursor-effects";
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const cursor_effects = require("cursor-effects");
|
import * as CursorEffectsLib from 'cursor-effects';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Красивый курсор**
|
* **Красивый курсор**
|
||||||
@@ -12,16 +12,17 @@ const cursor_effects = require("cursor-effects");
|
|||||||
* @author Tim Holman
|
* @author Tim Holman
|
||||||
* @link https://tholman.com/cursor-effects/
|
* @link https://tholman.com/cursor-effects/
|
||||||
*/
|
*/
|
||||||
export class CursorEffectsJoke extends StopableJoke<CursorEffectsJokeSettings> {
|
export class CursorEffectsJoke extends
|
||||||
id = "cursor_effects";
|
StoppableJoke<CursorEffectsJokeSettings> {
|
||||||
|
id = 'cursor_effects';
|
||||||
|
|
||||||
title = "Красивый курсор";
|
title = 'Красивый курсор';
|
||||||
|
|
||||||
description = "Эффекты, следующие за курсором";
|
description = 'Эффекты, следующие за курсором';
|
||||||
|
|
||||||
_settings = new CursorEffectsJokeSettings();
|
_settings = new CursorEffectsJokeSettings();
|
||||||
|
|
||||||
active_cursor_effect: any;
|
active_cursor_effect: CursorEffectsLib.CursorEffectResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Разблокировать все варианты курсоров
|
* Разблокировать все варианты курсоров
|
||||||
@@ -41,11 +42,21 @@ export class CursorEffectsJoke extends StopableJoke<CursorEffectsJokeSettings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение веса отдельного эффекта
|
||||||
|
* @param {CursorEffectsEnum} effect Тип эффекта
|
||||||
|
* @return {number} Значение веса
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private weight(effect: CursorEffectsEnum): number {
|
private weight(effect: CursorEffectsEnum): number {
|
||||||
const s = this.settings.effects[effect];
|
const s = this.settings.effects[effect];
|
||||||
return s.enabled ? s.weight : 0;
|
return s.enabled ? s.weight : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение случайного эффекта
|
||||||
|
* @return {CursorEffectsEnum}
|
||||||
|
*/
|
||||||
getRandomEffect(): CursorEffectsEnum {
|
getRandomEffect(): CursorEffectsEnum {
|
||||||
const elements = Object.values(CursorEffectsEnum).map(
|
const elements = Object.values(CursorEffectsEnum).map(
|
||||||
(e) => <CursorEffectsEnum>e
|
(e) => <CursorEffectsEnum>e
|
||||||
@@ -64,9 +75,12 @@ export class CursorEffectsJoke extends StopableJoke<CursorEffectsJokeSettings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Тебя быть тут не должно...");
|
throw new Error('Тебя быть тут не должно...');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
const effect = this.getRandomEffect();
|
const effect = this.getRandomEffect();
|
||||||
const settings = this.settings.effects[effect];
|
const settings = this.settings.effects[effect];
|
||||||
@@ -74,65 +88,77 @@ export class CursorEffectsJoke extends StopableJoke<CursorEffectsJokeSettings> {
|
|||||||
this.active_cursor_effect = resolveCursorEffectsEnum(effect, settings);
|
this.active_cursor_effect = resolveCursorEffectsEnum(effect, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Остановка шутки
|
||||||
|
*/
|
||||||
stop(): void {
|
stop(): void {
|
||||||
this.active_cursor_effect.destroy();
|
this.active_cursor_effect.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CursorEffectsEnum {
|
enum CursorEffectsEnum {
|
||||||
Rainbow = "rainbow",
|
Rainbow = 'rainbow',
|
||||||
FairyDust = "fairy_dust",
|
FairyDust = 'fairy_dust',
|
||||||
SpringyEmoji = "springy_emoji",
|
SpringyEmoji = 'springy_emoji',
|
||||||
Emoji = "emoji",
|
Emoji = 'emoji',
|
||||||
Ghost = "ghost",
|
Ghost = 'ghost',
|
||||||
Trailing = "trailing",
|
Trailing = 'trailing',
|
||||||
TextFlag = "text_flag",
|
TextFlag = 'text_flag',
|
||||||
FollowingDot = "following_dot",
|
FollowingDot = 'following_dot',
|
||||||
Bubbles = "bubbles",
|
Bubbles = 'bubbles',
|
||||||
Snowflake = "snowflake",
|
Snowflake = 'snowflake',
|
||||||
Clock = "clock",
|
Clock = 'clock',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение эффекта
|
||||||
|
* @param {CursorEffectsEnum | string} effect Тип эффекта
|
||||||
|
* @param {CursorEffectsSetting} options Настройки эффекта
|
||||||
|
* @return {CursorEffectsLib.CursorEffectResult}
|
||||||
|
*/
|
||||||
function resolveCursorEffectsEnum(
|
function resolveCursorEffectsEnum(
|
||||||
effect: CursorEffectsEnum | string,
|
effect: CursorEffectsEnum | string,
|
||||||
options: CursorEffectsSetting
|
options: CursorEffectsSetting
|
||||||
): any {
|
): CursorEffectsLib.CursorEffectResult {
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case CursorEffectsEnum.Rainbow:
|
case CursorEffectsEnum.Rainbow:
|
||||||
return cursor_effects.rainbowCursor(options);
|
return CursorEffectsLib.rainbowCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.FairyDust:
|
case CursorEffectsEnum.FairyDust:
|
||||||
return cursor_effects.fairyDustCursor(options);
|
return CursorEffectsLib.fairyDustCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.SpringyEmoji:
|
case CursorEffectsEnum.SpringyEmoji:
|
||||||
return cursor_effects.springyEmojiCursor(options);
|
return CursorEffectsLib.springyEmojiCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Emoji:
|
case CursorEffectsEnum.Emoji:
|
||||||
return cursor_effects.emojiCursor(options);
|
return CursorEffectsLib.emojiCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Ghost:
|
case CursorEffectsEnum.Ghost:
|
||||||
return cursor_effects.ghostCursor(options);
|
return CursorEffectsLib.ghostCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Trailing:
|
case CursorEffectsEnum.Trailing:
|
||||||
return cursor_effects.trailingCursor(options);
|
return CursorEffectsLib.trailingCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.TextFlag:
|
case CursorEffectsEnum.TextFlag:
|
||||||
return cursor_effects.textFlag(options);
|
return CursorEffectsLib.textFlag(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.FollowingDot:
|
case CursorEffectsEnum.FollowingDot:
|
||||||
return cursor_effects.followingDotCursor(options);
|
return CursorEffectsLib.followingDotCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Bubbles:
|
case CursorEffectsEnum.Bubbles:
|
||||||
return cursor_effects.bubbleCursor(options);
|
return CursorEffectsLib.bubbleCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Snowflake:
|
case CursorEffectsEnum.Snowflake:
|
||||||
return cursor_effects.snowflakeCursor(options);
|
return CursorEffectsLib.snowflakeCursor(options);
|
||||||
|
|
||||||
case CursorEffectsEnum.Clock:
|
case CursorEffectsEnum.Clock:
|
||||||
return cursor_effects.clockCursor(options);
|
return CursorEffectsLib.clockCursor(options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Красивый курсор"
|
||||||
|
*/
|
||||||
export class CursorEffectsJokeSettings implements JokeSettings {
|
export class CursorEffectsJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@@ -143,7 +169,7 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Радужный след за курсором
|
* Радужный след за курсором
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Rainbow]:
|
[CursorEffectsEnum.Rainbow]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Длина полосы
|
* Длина полосы
|
||||||
*/
|
*/
|
||||||
@@ -158,13 +184,13 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Цвета полос (сверху вниз)
|
* Цвета полос (сверху вниз)
|
||||||
*/
|
*/
|
||||||
colors: string[] = [
|
colors: string[] = [
|
||||||
"#9400D3",
|
'#9400D3',
|
||||||
"#4B0082",
|
'#4B0082',
|
||||||
"#0000FF",
|
'#0000FF',
|
||||||
"#00FF00",
|
'#00FF00',
|
||||||
"#FFFF00",
|
'#FFFF00',
|
||||||
"#FF7F00",
|
'#FF7F00',
|
||||||
"#FF0000",
|
'#FF0000',
|
||||||
];
|
];
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
@@ -172,44 +198,44 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Цепочка из эмодзи "на резинке" под курсором
|
* Цепочка из эмодзи "на резинке" под курсором
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.SpringyEmoji]:
|
[CursorEffectsEnum.SpringyEmoji]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Висящий эмодзи
|
* Висящий эмодзи
|
||||||
*/
|
*/
|
||||||
emoji: string = "🤪";
|
emoji: string = '🤪';
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Падающие от курсора эмодзи
|
* Падающие от курсора эмодзи
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Emoji]: new (class extends DefaultCursorEffectsSetting {
|
[CursorEffectsEnum.Emoji]: new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Падающие эмодзи
|
* Падающие эмодзи
|
||||||
*/
|
*/
|
||||||
emoji: string[] = ["🔥", "🐬", "🦆"];
|
emoji: string[] = ['🔥', '🐬', '🦆'];
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Падающие от курсора пылинки
|
* Падающие от курсора пылинки
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.FairyDust]:
|
[CursorEffectsEnum.FairyDust]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Цвет пылинок
|
* Цвет пылинок
|
||||||
*/
|
*/
|
||||||
colors: string[] = ["#ff0000", "#00ff00", "#0000ff"];
|
colors: string[] = ['#ff0000', '#00ff00', '#0000ff'];
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* След "зависших" курсоров
|
* След "зависших" курсоров
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Ghost]: new DefaultCursorEffectsSetting(),
|
[CursorEffectsEnum.Ghost]: new CursorEffectsSetting(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* След курсоров "на резинке"
|
* След курсоров "на резинке"
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Trailing]:
|
[CursorEffectsEnum.Trailing]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Количество элементов
|
* Количество элементов
|
||||||
*/
|
*/
|
||||||
@@ -231,21 +257,21 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Текст, развивающийся флагом от курсора
|
* Текст, развивающийся флагом от курсора
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.TextFlag]:
|
[CursorEffectsEnum.TextFlag]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Отображаемый текст
|
* Отображаемый текст
|
||||||
*/
|
*/
|
||||||
text: string = "С днём смеха!";
|
text: string = 'С днём смеха!';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Цвет текста
|
* Цвет текста
|
||||||
*/
|
*/
|
||||||
color: string = "#000000";
|
color: string = '#000000';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Шрифт текста
|
* Шрифт текста
|
||||||
*/
|
*/
|
||||||
font: string = "monospace";
|
font: string = 'monospace';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Размер текста
|
* Размер текста
|
||||||
@@ -267,17 +293,17 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Точка, преследующая курсор
|
* Точка, преследующая курсор
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.FollowingDot]:
|
[CursorEffectsEnum.FollowingDot]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Цвет догоняющей точки
|
* Цвет догоняющей точки
|
||||||
*/
|
*/
|
||||||
color: string = "#323232a6";
|
color: string = '#323232a6';
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Пузырьки от курсора
|
* Пузырьки от курсора
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Bubbles]: new DefaultCursorEffectsSetting(),
|
[CursorEffectsEnum.Bubbles]: new CursorEffectsSetting(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Снежинки, летящие от курсора
|
* Снежинки, летящие от курсора
|
||||||
@@ -285,47 +311,53 @@ export class CursorEffectsJokeSettings implements JokeSettings {
|
|||||||
* Отключено, потому что сейчас не зима :D
|
* Отключено, потому что сейчас не зима :D
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Snowflake]:
|
[CursorEffectsEnum.Snowflake]:
|
||||||
new (class extends DefaultCursorEffectsSetting {
|
new (class extends CursorEffectsSetting {
|
||||||
weight: number = 0;
|
weight: number = 0;
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Циферблат вокруг курсора
|
* Циферблат вокруг курсора
|
||||||
*/
|
*/
|
||||||
[CursorEffectsEnum.Clock]: new (class extends DefaultCursorEffectsSetting {
|
[CursorEffectsEnum.Clock]: new (class extends CursorEffectsSetting {
|
||||||
/**
|
/**
|
||||||
* Цвет даты
|
* Цвет даты
|
||||||
*/
|
*/
|
||||||
dateColor: string = "blue";
|
dateColor: string = 'blue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Цвет циферблата
|
* Цвет циферблата
|
||||||
*/
|
*/
|
||||||
faceColor: string = "black";
|
faceColor: string = 'black';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Цвет секундной стрелки
|
* Цвет секундной стрелки
|
||||||
*/
|
*/
|
||||||
secondsColor: string = "red";
|
secondsColor: string = 'red';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Цвет минутной стрелки
|
* Цвет минутной стрелки
|
||||||
*/
|
*/
|
||||||
minutesColor: string = "black";
|
minutesColor: string = 'black';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Цвет часовой стрелки
|
* Цвет часовой стрелки
|
||||||
*/
|
*/
|
||||||
hoursColor: string = "black";
|
hoursColor: string = 'black';
|
||||||
})(),
|
})(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CursorEffectsSetting {
|
/**
|
||||||
[key: string]: any;
|
* Восстановление класса CursorEffectsLib.DefaultOptions
|
||||||
|
*/
|
||||||
|
class DefaultOptions {
|
||||||
|
readonly element?: HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultCursorEffectsSetting implements CursorEffectsSetting {
|
/**
|
||||||
|
* Класс настроек для курсора
|
||||||
|
*/
|
||||||
|
class CursorEffectsSetting extends DefaultOptions {
|
||||||
/**
|
/**
|
||||||
* Флаг возможности срабатывания
|
* Флаг возможности срабатывания
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import { getTextNodes } from "../common";
|
import {getTextNodes} from '../common';
|
||||||
import $ from "jquery";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Ад гуманитария**
|
* **Ад гуманитария**
|
||||||
@@ -10,20 +9,29 @@ import $ from "jquery";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class HumanitarianHellJoke extends Joke<HumanitarianHellJokeSettings> {
|
export class HumanitarianHellJoke extends Joke<HumanitarianHellJokeSettings> {
|
||||||
id = "humanitarian_hell";
|
id = 'humanitarian_hell';
|
||||||
|
|
||||||
title = "Ад гуманитария";
|
title = 'Ад гуманитария';
|
||||||
|
|
||||||
description = 'Все "тся" заменяются на "ться", а все "ться" на "тся"';
|
description = 'Все "тся" заменяются на "ться", а все "ться" на "тся"';
|
||||||
|
|
||||||
_settings = new HumanitarianHellJokeSettings();
|
_settings = new HumanitarianHellJokeSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Обработка текста
|
||||||
|
*
|
||||||
|
* @param {string} text Входная строка
|
||||||
|
* @return {string} Итоговая строка
|
||||||
|
*/
|
||||||
processText(text: string): string {
|
processText(text: string): string {
|
||||||
return text.replace(/(ть?ся)/g, function (fnd) {
|
return text.replace(/(ть?ся)/g, function(fnd) {
|
||||||
return fnd.indexOf("ь") > 0 ? "тся" : "ться";
|
return fnd.indexOf('ь') > 0 ? 'тся' : 'ться';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
const textNodes = getTextNodes(this.settings.selector);
|
const textNodes = getTextNodes(this.settings.selector);
|
||||||
|
|
||||||
@@ -33,6 +41,9 @@ export class HumanitarianHellJoke extends Joke<HumanitarianHellJokeSettings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Ад гуманитария"
|
||||||
|
*/
|
||||||
export class HumanitarianHellJokeSettings implements JokeSettings {
|
export class HumanitarianHellJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@@ -41,5 +52,5 @@ export class HumanitarianHellJokeSettings implements JokeSettings {
|
|||||||
/**
|
/**
|
||||||
* Селектор всех элементов, которые будут затронуты
|
* Селектор всех элементов, которые будут затронуты
|
||||||
*/
|
*/
|
||||||
selector: string = ".post-content";
|
selector: HTMLElement | JQuery<HTMLElement> | string = '.post-content';
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-17
@@ -1,7 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import { getTextNodes } from "../common";
|
import {getTextNodes} from '../common';
|
||||||
import $ from "jquery";
|
|
||||||
import { JokerClass } from "../joker";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Буквенный хаос**
|
* **Буквенный хаос**
|
||||||
@@ -11,26 +9,29 @@ import { JokerClass } from "../joker";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class LetterChaosJoke extends Joke<LetterChaosJokeSettings> {
|
export class LetterChaosJoke extends Joke<LetterChaosJokeSettings> {
|
||||||
id = "letter_chaos";
|
id = 'letter_chaos';
|
||||||
|
|
||||||
title = "Буквенный хаос";
|
title = 'Буквенный хаос';
|
||||||
|
|
||||||
description = "Все буквы в словах, кроме первой и последней, перемешены";
|
description = 'Все буквы в словах, кроме первой и последней, перемешены';
|
||||||
|
|
||||||
_settings = new LetterChaosJokeSettings();
|
_settings = new LetterChaosJokeSettings();
|
||||||
|
|
||||||
punctuationSymbols: string[] | null = null;
|
punctuationSymbols: string[] | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Перемешивание букв в словах
|
||||||
|
* @param {string} word
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private shuffleLetters(word: string): string {
|
private shuffleLetters(word: string): string {
|
||||||
// Check if the word has two or more letters
|
|
||||||
if (word.length < 3 || !this.check(this.settings.shuffle_chance)) {
|
if (word.length < 3 || !this.check(this.settings.shuffle_chance)) {
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split the word into an array of characters
|
const characters = word.split('');
|
||||||
const characters = word.split("");
|
|
||||||
|
|
||||||
// Shuffle the characters between the first and last letters
|
|
||||||
const middleCharacters = characters.slice(1, -1);
|
const middleCharacters = characters.slice(1, -1);
|
||||||
for (let i = middleCharacters.length - 1; i > 0; i--) {
|
for (let i = middleCharacters.length - 1; i > 0; i--) {
|
||||||
const j = Math.floor(Math.random() * (i + 1));
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
@@ -40,28 +41,38 @@ export class LetterChaosJoke extends Joke<LetterChaosJokeSettings> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join the shuffled characters back into a word
|
|
||||||
return [
|
return [
|
||||||
characters[0],
|
characters[0],
|
||||||
...middleCharacters,
|
...middleCharacters,
|
||||||
characters[characters.length - 1],
|
characters[characters.length - 1],
|
||||||
].join("");
|
].join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
private processNode(node: any) {
|
/**
|
||||||
|
* Обработка текстовой ноды
|
||||||
|
* @param {Text} node
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private processNode(node: Text) {
|
||||||
node.textContent = node.textContent?.replace(
|
node.textContent = node.textContent?.replace(
|
||||||
/([А-Яа-яA-Za-z]+)/gm,
|
/([А-Яа-яA-Za-z]+)/gm,
|
||||||
(_: any, word: string) => this.shuffleLetters(word)
|
(_: string, word: string) => this.shuffleLetters(word)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
const textNodes = getTextNodes(this.settings.selector);
|
const textNodes = getTextNodes(this.settings.selector);
|
||||||
|
|
||||||
textNodes.each((_, node) => this.processNode(node));
|
textNodes.each((_, node) => this.processNode(node as Text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Буквенный хаос"
|
||||||
|
*/
|
||||||
export class LetterChaosJokeSettings implements JokeSettings {
|
export class LetterChaosJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@@ -70,7 +81,7 @@ export class LetterChaosJokeSettings implements JokeSettings {
|
|||||||
/**
|
/**
|
||||||
* Селектор всех элементов, которые будут затронуты
|
* Селектор всех элементов, которые будут затронуты
|
||||||
*/
|
*/
|
||||||
selector: string = ".post-content";
|
selector: string = '.post-content';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Вероятность того, что буквы будут перемешаны
|
* Вероятность того, что буквы будут перемешаны
|
||||||
|
|||||||
+19
-13
@@ -1,5 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Зеркало**
|
* **Зеркало**
|
||||||
@@ -9,26 +9,32 @@ import $ from "jquery";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class MirrorJoke extends Joke<MirrorJokeSettings> {
|
export class MirrorJoke extends Joke<MirrorJokeSettings> {
|
||||||
id = "mirror";
|
id = 'mirror';
|
||||||
|
|
||||||
title = "Зеркало";
|
title = 'Зеркало';
|
||||||
|
|
||||||
description = "Элементы форума отражаются (по крайней мере, пытаются)";
|
description = 'Элементы форума отражаются (по крайней мере, пытаются)';
|
||||||
|
|
||||||
_settings = new MirrorJokeSettings();
|
_settings = new MirrorJokeSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
$(".post, .post h3, .post-links, .post-author, .post-content")
|
$('.post, .post h3, .post-links, .post-author, .post-content')
|
||||||
.css("transform", "scaleX(-1)")
|
.css('transform', 'scaleX(-1)')
|
||||||
.css("-moz-transform", "scaleX(-1)")
|
.css('-moz-transform', 'scaleX(-1)')
|
||||||
.css("-moz-transform", "scaleX(-1)")
|
.css('-moz-transform', 'scaleX(-1)')
|
||||||
.css("filter", "FlipH")
|
.css('filter', 'FlipH')
|
||||||
.css("-ms-filter", '"FlipH"');
|
.css('-ms-filter', '"FlipH"');
|
||||||
$(".post-links, .post-links ul, .post h3 span").css("margin-left", "0");
|
$('.post-links, .post-links ul, .post h3 span').css('margin-left', '0');
|
||||||
$(".post h3 span").css("margin-right", "25em");
|
$('.post h3 span').css('margin-right', '25em');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Зеркало"
|
||||||
|
*/
|
||||||
export class MirrorJokeSettings implements JokeSettings {
|
export class MirrorJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = false;
|
enabled: boolean = false;
|
||||||
|
|
||||||
|
|||||||
+36
-21
@@ -1,5 +1,5 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {JokeSettings, StoppableJoke} from '../joke';
|
||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Форумо-трясение**
|
* **Форумо-трясение**
|
||||||
@@ -8,73 +8,88 @@ import $ from "jquery";
|
|||||||
*
|
*
|
||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class ShakeJoke extends StopableJoke<ShakeJokeSettings> {
|
export class ShakeJoke extends StoppableJoke<ShakeJokeSettings> {
|
||||||
id = "shake";
|
id = 'shake';
|
||||||
|
|
||||||
title = "Форумо-трясение";
|
title = 'Форумо-трясение';
|
||||||
|
|
||||||
description = "Страница форума начинает трястись";
|
description = 'Страница форума начинает трястись';
|
||||||
|
|
||||||
_settings = new ShakeJokeSettings();
|
_settings = new ShakeJokeSettings();
|
||||||
|
|
||||||
private interval_id: NodeJS.Timer;
|
private intervalId: NodeJS.Timeout;
|
||||||
|
|
||||||
private items: JQuery;
|
private items: JQuery;
|
||||||
|
|
||||||
private data_name: string = "april-fools-shake";
|
private dataName: string = 'april-fools-shake';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выбор случайной амплитуды
|
||||||
|
* @param {number} a
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
rand(a: number): number {
|
rand(a: number): number {
|
||||||
return a + this.settings.force * (Math.random() * 2 - 1);
|
return a + this.settings.force * (Math.random() * 2 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
this.items = $(this.settings.selector);
|
this.items = $(this.settings.selector);
|
||||||
|
|
||||||
this.items.each((_, elem) => {
|
this.items.each((_, elem) => {
|
||||||
let data: ShakeJokeMargin = {};
|
const data: ShakeJokeMargin = {};
|
||||||
|
|
||||||
this.settings.directions.forEach((d) => {
|
this.settings.directions.forEach((d) => {
|
||||||
data[d] = parseInt($(elem).css("margin-" + d));
|
data[d] = parseInt($(elem).css('margin-' + d));
|
||||||
});
|
});
|
||||||
|
|
||||||
$(elem).data(this.data_name, data);
|
$(elem).data(this.dataName, data);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.interval_id = setInterval(() => {
|
this.intervalId = setInterval(() => {
|
||||||
this.items.each((_, elem) => {
|
this.items.each((_, elem) => {
|
||||||
const data: ShakeJokeMargin = $(elem).data(this.data_name);
|
const data: ShakeJokeMargin = $(elem).data(this.dataName);
|
||||||
|
|
||||||
for (const entry of Object.entries(data)) {
|
for (const entry of Object.entries(data)) {
|
||||||
$(elem).css("margin-" + entry[0], this.rand(entry[1]));
|
$(elem).css('margin-' + entry[0], this.rand(entry[1]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, this.settings.interval);
|
}, this.settings.interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Остновка шутки
|
||||||
|
*/
|
||||||
stop(): void {
|
stop(): void {
|
||||||
clearInterval(this.interval_id);
|
clearInterval(this.intervalId);
|
||||||
|
|
||||||
this.items.each((_, elem) => {
|
this.items.each((_, elem) => {
|
||||||
let data: ShakeJokeMargin = {};
|
const data: ShakeJokeMargin = {};
|
||||||
|
|
||||||
this.settings.directions.forEach((d) => {
|
this.settings.directions.forEach((d) => {
|
||||||
$(elem).css("margin-" + d, data[d]);
|
$(elem).css('margin-' + d, data[d]);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(elem).data(this.data_name, data);
|
$(elem).data(this.dataName, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Форумо-трясение"
|
||||||
|
*/
|
||||||
export class ShakeJokeSettings implements JokeSettings {
|
export class ShakeJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = false;
|
enabled: boolean = false;
|
||||||
|
|
||||||
chance: number = 1;
|
chance: number = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Направление тряски (тряска происходит путём изменения перечисленных направлений margin на значение ±force от стандартного значения)
|
* Направление тряски (тряска происходит путём изменения перечисленных
|
||||||
|
* направлений margin на значение ±force от стандартного значения)
|
||||||
*/
|
*/
|
||||||
directions: string[] = ["top", "left", "bottom", "left"];
|
directions: string[] = ['top', 'left', 'bottom', 'left'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сила тряски - насколько отклоняется элемент от стандартного значения
|
* Сила тряски - насколько отклоняется элемент от стандартного значения
|
||||||
@@ -84,7 +99,7 @@ export class ShakeJokeSettings implements JokeSettings {
|
|||||||
/**
|
/**
|
||||||
* Селектор всех элементов, которые будут трястись
|
* Селектор всех элементов, которые будут трястись
|
||||||
*/
|
*/
|
||||||
selector: string = "[id^=pun]";
|
selector: string = '[id^=pun]';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Частота тряски
|
* Частота тряски
|
||||||
|
|||||||
+180
-91
@@ -1,6 +1,6 @@
|
|||||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
import {Joke, JokeSettings} from '../joke';
|
||||||
import $ from "jquery";
|
import $ from 'jquery';
|
||||||
import { StupidTitleDefaultVariants } from "../data/stupid_title_variants";
|
import {StupidTitleDefaultVariants} from '../data/stupid_title_variants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **Глупые статусы**
|
* **Глупые статусы**
|
||||||
@@ -10,21 +10,26 @@ import { StupidTitleDefaultVariants } from "../data/stupid_title_variants";
|
|||||||
* @author Kozhilya
|
* @author Kozhilya
|
||||||
*/
|
*/
|
||||||
export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
||||||
id = "stupid_title";
|
id = 'stupid_title';
|
||||||
|
|
||||||
title = "Глупые статусы";
|
title = 'Глупые статусы';
|
||||||
|
|
||||||
description = "Каждому пользователю даётся новый глупый статус";
|
description = 'Каждому пользователю даётся новый глупый статус';
|
||||||
|
|
||||||
_settings = new StupidTitleJokeSettings();
|
_settings = new StupidTitleJokeSettings();
|
||||||
|
|
||||||
private loadedGenders: any = null;
|
private loadedGenders: { [key in string]: boolean } = null;
|
||||||
|
private variantsGenerated = false;
|
||||||
|
private seed = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Загрузка полов, если они не определены
|
||||||
|
*/
|
||||||
async loadGenders(): Promise<void> {
|
async loadGenders(): Promise<void> {
|
||||||
const names = $(".pa-author a")
|
const names = $('.pa-author a').
|
||||||
.map((_, elem) => elem.innerText)
|
map((_, elem) => elem.innerText).
|
||||||
.toArray()
|
toArray().
|
||||||
.reduce((arr: string[], name: string) => {
|
reduce((arr: string[], name: string) => {
|
||||||
if (arr.indexOf(name) < 0) {
|
if (arr.indexOf(name) < 0) {
|
||||||
arr.push(name);
|
arr.push(name);
|
||||||
}
|
}
|
||||||
@@ -32,8 +37,8 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const url =
|
const url =
|
||||||
"/api.php?" +
|
'/api.php?' +
|
||||||
$.param({ method: "users.get", fields: "username,sex", username: names });
|
$.param({method: 'users.get', fields: 'username,sex', username: names});
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
|
|
||||||
@@ -43,15 +48,21 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
json.response.users.forEach((element: any) => {
|
json.response?.users.forEach(
|
||||||
if (element.sex === "0") {
|
(element: { username: string, sex: string }) => {
|
||||||
|
if (element.sex === '0') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadedGenders[element.username] = element.sex === "1";
|
this.loadedGenders[element.username] = element.sex === '1';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Разрешение пола по имени
|
||||||
|
* @param {string} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
resolveGender(name: string): boolean {
|
resolveGender(name: string): boolean {
|
||||||
if (this.settings.gender_resolver !== null) {
|
if (this.settings.gender_resolver !== null) {
|
||||||
return !!this.settings.gender_resolver.call(this, name);
|
return !!this.settings.gender_resolver.call(this, name);
|
||||||
@@ -62,11 +73,12 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.resetSeed();
|
this.resetSeed();
|
||||||
return this.selectRandom(name, { m: 1, f: 1 }) === "m";
|
return this.selectRandom(name, {m: 1, f: 1}) === 'm';
|
||||||
}
|
}
|
||||||
|
|
||||||
private variantsGenerated = false;
|
/**
|
||||||
|
* Запуск шутки
|
||||||
|
*/
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
if (!this.variantsGenerated) {
|
if (!this.variantsGenerated) {
|
||||||
StupidTitleDefaultVariants(this.settings.variants);
|
StupidTitleDefaultVariants(this.settings.variants);
|
||||||
@@ -75,10 +87,10 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
|
|
||||||
await this.loadGenders();
|
await this.loadGenders();
|
||||||
|
|
||||||
const cache: any = {};
|
const cache: {[key in string]: string} = {};
|
||||||
|
|
||||||
$(".post-author").each((_, root) => {
|
$('.post-author').each((_, root) => {
|
||||||
const name = $(".pa-author a", root).text();
|
const name = $('.pa-author a', root).text();
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,21 +100,47 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
cache[name] = this.generatePhrase(name);
|
cache[name] = this.generatePhrase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".pa-title", root).text(cache[name]);
|
$('.pa-title', root).text(cache[name]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private prng(name: string, seed: number, limit: number): number {
|
/**
|
||||||
/*
|
* Сгенерировать фразу
|
||||||
https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
* @param {string} name Имя, кому необходимо сгенерировать фразу
|
||||||
|
* @return {string} Итоговая фраза
|
||||||
cyrb53 (c) 2018 bryc (github.com/bryc)
|
|
||||||
A fast and simple hash function with decent collision resistance.
|
|
||||||
Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
|
|
||||||
Public domain. Attribution appreciated.
|
|
||||||
*/
|
*/
|
||||||
let h1 = 0xdeadbeef ^ seed,
|
generatePhrase(name: string): string {
|
||||||
h2 = 0x41c6ce57 ^ seed;
|
const gender = this.resolveGender(name);
|
||||||
|
const phrase = this.selectRandom(name, this.settings.schemas);
|
||||||
|
|
||||||
|
return this.capitalizeFirst(
|
||||||
|
phrase.replace(/\{(.+?)}/g, (_, type: string) => {
|
||||||
|
const variants = this.buildVariants(type, gender);
|
||||||
|
|
||||||
|
return this.selectRandom(name, variants);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Функция хеширования
|
||||||
|
*
|
||||||
|
* https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
||||||
|
*
|
||||||
|
* cyrb53 (c) 2018 bryc (github.com/bryc)
|
||||||
|
* A fast and simple hash function with decent collision resistance.
|
||||||
|
* Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
|
||||||
|
* Public domain. Attribution appreciated.
|
||||||
|
*
|
||||||
|
* @param {string} name Имя
|
||||||
|
* @param {number} seed Зерно случайности
|
||||||
|
* @param {limit} limit Максимальное значение
|
||||||
|
* @return {number} Хеш-значение
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private prng(name: string, seed: number, limit: number): number {
|
||||||
|
let h1 = 0xdeadbeef ^ seed;
|
||||||
|
let h2 = 0x41c6ce57 ^ seed;
|
||||||
for (let i = 0, ch; i < name.length; i++) {
|
for (let i = 0, ch; i < name.length; i++) {
|
||||||
ch = name.charCodeAt(i);
|
ch = name.charCodeAt(i);
|
||||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||||
@@ -120,8 +158,10 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
return Math.floor(Math.pow(Math.sin(value), 2) * limit) % limit;
|
return Math.floor(Math.pow(Math.sin(value), 2) * limit) % limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private seed = 0;
|
/**
|
||||||
|
* Сброс зерна случайности
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private resetSeed(): void {
|
private resetSeed(): void {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const time = date.getUTCHours() * 60 + date.getUTCMinutes();
|
const time = date.getUTCHours() * 60 + date.getUTCMinutes();
|
||||||
@@ -134,14 +174,21 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
this.seed = Math.floor(time / this.settings.change_frequency);
|
this.seed = Math.floor(time / this.settings.change_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выбор случайного слова
|
||||||
|
* @param {string} name
|
||||||
|
* @param {StupidTitleWeightedVariants} variants
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private selectRandom(
|
private selectRandom(
|
||||||
name: string,
|
name: string,
|
||||||
variants: StupidTitleWeightedVariants
|
variants: StupidTitleWeightedVariants,
|
||||||
): string {
|
): string {
|
||||||
const elements = Object.keys(variants);
|
const elements = Object.keys(variants);
|
||||||
const totalWeight = elements.reduce(
|
const totalWeight = elements.reduce(
|
||||||
(sum, element) => sum + variants[element],
|
(sum, element) => sum + variants[element],
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
const randomWeight = this.prng(name, this.seed++, totalWeight);
|
const randomWeight = this.prng(name, this.seed++, totalWeight);
|
||||||
|
|
||||||
@@ -153,12 +200,19 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Тебя быть тут не должно...");
|
throw new Error('Тебя быть тут не должно...');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выбор случайной фразы
|
||||||
|
* @param {string} type
|
||||||
|
* @param {boolean} gender
|
||||||
|
* @return {StupidTitleWeightedVariants}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private buildVariants(
|
private buildVariants(
|
||||||
type: string,
|
type: string,
|
||||||
gender: boolean
|
gender: boolean,
|
||||||
): StupidTitleWeightedVariants {
|
): StupidTitleWeightedVariants {
|
||||||
const result: StupidTitleWeightedVariants = {};
|
const result: StupidTitleWeightedVariants = {};
|
||||||
const variants: StupidTitleVariant = this.settings.variants[type];
|
const variants: StupidTitleVariant = this.settings.variants[type];
|
||||||
@@ -181,24 +235,27 @@ export class StupidTitleJoke extends Joke<StupidTitleJokeSettings> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сделать первую буква слова заглавной
|
||||||
|
* @param {string} str Слово
|
||||||
|
* @return {string} Исправленное слово
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private capitalizeFirst(str: string): string {
|
private capitalizeFirst(str: string): string {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePhrase(name: string): string {
|
|
||||||
const gender = this.resolveGender(name);
|
|
||||||
const prhase = this.selectRandom(name, this.settings.schemas);
|
|
||||||
|
|
||||||
return this.capitalizeFirst(
|
|
||||||
prhase.replace(/\{(.+?)\}/g, (_, type: string) => {
|
|
||||||
const variants = this.buildVariants(type, gender);
|
|
||||||
|
|
||||||
return this.selectRandom(name, variants);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Определение пола по имени.
|
||||||
|
* @param {string} name Имя персонажа
|
||||||
|
* @return {boolean | null} true, если мужской род; false, если женский род
|
||||||
|
*/
|
||||||
|
type GenderResolverFunction = (name: string) => (boolean | null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек для шутки "Глупые статусы"
|
||||||
|
*/
|
||||||
export class StupidTitleJokeSettings implements JokeSettings {
|
export class StupidTitleJokeSettings implements JokeSettings {
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
chance: number = 100;
|
chance: number = 100;
|
||||||
@@ -207,12 +264,13 @@ export class StupidTitleJokeSettings implements JokeSettings {
|
|||||||
* Определение пола по имени.
|
* Определение пола по имени.
|
||||||
* По умолчанию род устанавливается случайным образом
|
* По умолчанию род устанавливается случайным образом
|
||||||
*
|
*
|
||||||
* Если установлено значение `null`, система попытается загрузить пол, установленный в настройках аккаунта. Если этот пол определить невозможно, то он будет выбран случайно. Эта настройка позволяет изменить это поведение, если ваш форум обладает ролевой системой, в которой пол определяется иным образом.
|
* Если установлено значение `null`, система попытается загрузить пол,
|
||||||
*
|
* установленный в настройках аккаунта. Если этот пол определить невозможно,
|
||||||
* @param name Имя персонажа
|
* то он будет выбран случайно. Эта настройка позволяет изменить это
|
||||||
* @returns true, если мужской род; false, если женский род
|
* поведение, если ваш форум обладает ролевой системой, в которой пол
|
||||||
|
* определяется иным образом.
|
||||||
*/
|
*/
|
||||||
gender_resolver: Function | null = null;
|
gender_resolver: GenderResolverFunction | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Разрешить возможно оскорбительные варианты
|
* Разрешить возможно оскорбительные варианты
|
||||||
@@ -221,7 +279,8 @@ export class StupidTitleJokeSettings implements JokeSettings {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Частота смены статусов (в минутах)
|
* Частота смены статусов (в минутах)
|
||||||
* Установите значение 0, что бы обновление происходило при каждом обновлении страницы
|
* Установите значение 0, что бы обновление происходило при
|
||||||
|
* каждом обновлении страницы
|
||||||
*/
|
*/
|
||||||
change_frequency: number = 5;
|
change_frequency: number = 5;
|
||||||
|
|
||||||
@@ -236,14 +295,14 @@ export class StupidTitleJokeSettings implements JokeSettings {
|
|||||||
* {p} - знак препинания
|
* {p} - знак препинания
|
||||||
*/
|
*/
|
||||||
schemas: StupidTitleWeightedVariants = {
|
schemas: StupidTitleWeightedVariants = {
|
||||||
"{adj} {noun}{p}": 10,
|
'{adj} {noun}{p}': 10,
|
||||||
"{noun} {adj}{p}": 3,
|
'{noun} {adj}{p}': 3,
|
||||||
"{adj}, {adj} {noun}{p}": 10,
|
'{adj}, {adj} {noun}{p}': 10,
|
||||||
"{adj} и очень {adj} {noun}{p}": 10,
|
'{adj} и очень {adj} {noun}{p}': 10,
|
||||||
"{adj} {noun} {verb}{p}": 10,
|
'{adj} {noun} {verb}{p}': 10,
|
||||||
"{adj} {noun} {adv} {verb}{p}": 5,
|
'{adj} {noun} {adv} {verb}{p}': 5,
|
||||||
"{adj} {noun} {verb} {place}{p}": 5,
|
'{adj} {noun} {verb} {place}{p}': 5,
|
||||||
"{adj} {noun} {adv} {verb} {place}{p}": 5,
|
'{adj} {noun} {adv} {verb} {place}{p}': 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,13 +316,13 @@ export class StupidTitleJokeSettings implements JokeSettings {
|
|||||||
place: {},
|
place: {},
|
||||||
adv: {},
|
adv: {},
|
||||||
p: {
|
p: {
|
||||||
"": new StupidTitleSetting({ weight: 10 }),
|
'': new StupidTitleSetting({weight: 15}),
|
||||||
".": new StupidTitleSetting({ weight: 10 }),
|
'.': new StupidTitleSetting({weight: 10}),
|
||||||
"...": new StupidTitleSetting({ weight: 5 }),
|
'...': new StupidTitleSetting({weight: 5}),
|
||||||
"!": new StupidTitleSetting({ weight: 5 }),
|
'!': new StupidTitleSetting({weight: 5}),
|
||||||
"!!!": new StupidTitleSetting({ weight: 2 }),
|
'!!!': new StupidTitleSetting({weight: 2}),
|
||||||
"?": new StupidTitleSetting({ weight: 2 }),
|
'?': new StupidTitleSetting({weight: 2}),
|
||||||
"?!": new StupidTitleSetting({ weight: 1 }),
|
'?!': new StupidTitleSetting({weight: 1}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -280,6 +339,16 @@ interface StupidTitleWeightedVariants {
|
|||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StupidTitleSettingInitializer = {
|
||||||
|
weight?: number;
|
||||||
|
enabled?: boolean;
|
||||||
|
rude?: boolean;
|
||||||
|
gender?: boolean | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настройки
|
||||||
|
*/
|
||||||
class StupidTitleSetting {
|
class StupidTitleSetting {
|
||||||
weight: number = 10;
|
weight: number = 10;
|
||||||
|
|
||||||
@@ -289,42 +358,62 @@ class StupidTitleSetting {
|
|||||||
|
|
||||||
gender: boolean | null = null;
|
gender: boolean | null = null;
|
||||||
|
|
||||||
constructor(options: any = new Object()) {
|
/**
|
||||||
for (const iterator of Object.entries(options)) {
|
* Создание класса
|
||||||
if (iterator[0] in this) {
|
* @param {StupidTitleSettingInitializer} options
|
||||||
(<any>this)[iterator[0]] = iterator[1];
|
*/
|
||||||
}
|
constructor(options: StupidTitleSettingInitializer) {
|
||||||
}
|
this.weight ??= options.weight;
|
||||||
|
this.enabled ??= options.enabled;
|
||||||
|
this.rude ??= options.rude;
|
||||||
|
this.gender ??= options.gender;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BuildStupdiTitleVariant(
|
/**
|
||||||
|
* Метод создания списка слов
|
||||||
|
* @param {boolean | null} gender
|
||||||
|
* @param {string} input
|
||||||
|
* @return {StupidTitleVariant}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
export function BuildStupidTitleVariant(
|
||||||
gender: boolean | null,
|
gender: boolean | null,
|
||||||
input: string
|
input: string,
|
||||||
): StupidTitleVariant {
|
): StupidTitleVariant {
|
||||||
const result: StupidTitleVariant = {};
|
const result: StupidTitleVariant = {};
|
||||||
const words = input.split(",").map((word) => word.trim());
|
const words = input.split(',').map((word) => word.trim());
|
||||||
|
|
||||||
words.forEach((word) => {
|
words.forEach((word) => {
|
||||||
const clean_word = word.replace(/[^А-ЯЁа-яёA-Za-z\- ]/g, "");
|
const cleanWord = word.replace(/[^А-ЯЁа-яёA-Za-z\- ]/g, '');
|
||||||
|
|
||||||
if (clean_word === "") {
|
if (cleanWord === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result[clean_word] = new StupidTitleSetting({
|
result[cleanWord] = new StupidTitleSetting({
|
||||||
gender,
|
gender,
|
||||||
rude: word.indexOf("$") >= 0,
|
rude: word.indexOf('$') >= 0,
|
||||||
enabled: word.indexOf("!") < 0,
|
enabled: word.indexOf('!') < 0,
|
||||||
weight:
|
weight:
|
||||||
10 *
|
10 *
|
||||||
(word.indexOf("$") >= 0 ? 0.5 : 1) *
|
(word.indexOf('$') >= 0 ? 0.5 : 1) *
|
||||||
(word.indexOf("%") >= 0 ? 0.5 : 1) *
|
(word.indexOf('%') >= 0 ? 0.5 : 1) *
|
||||||
(word.indexOf("^") >= 0 ? 2 : 1),
|
(word.indexOf('^') >= 0 ? 2 : 1),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
(window as any).BuildStupdiTitleVariant = BuildStupdiTitleVariant;
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
BuildStupidTitleVariant(
|
||||||
|
gender: boolean | null,
|
||||||
|
input: string,
|
||||||
|
): StupidTitleVariant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.BuildStupidTitleVariant = BuildStupidTitleVariant;
|
||||||
|
|
||||||
|
|||||||
+18
-14
@@ -1,19 +1,23 @@
|
|||||||
import { JokerClass } from "./joker";
|
import {JokerClass} from './joker';
|
||||||
import { Joke } from "./joke";
|
import {Joke, JokeSettings} from './joke';
|
||||||
import { ShakeJoke } from "./jokes/shake";
|
import {ShakeJoke} from './jokes/shake';
|
||||||
import { HumanitarianHellJoke } from "./jokes/humanitarian_hell";
|
import {HumanitarianHellJoke} from './jokes/humanitarian_hell';
|
||||||
import { MirrorJoke } from "./jokes/mirror";
|
import {MirrorJoke} from './jokes/mirror';
|
||||||
import { CarnivalJoke } from "./jokes/carnival";
|
import {CarnivalJoke} from './jokes/carnival';
|
||||||
import { CrazyLettersJoke } from "./jokes/crazy_letters";
|
import {CrazyLettersJoke} from './jokes/crazy_letters';
|
||||||
import { LetterChaosJoke } from "./jokes/letter_chaos";
|
import {LetterChaosJoke} from './jokes/letter_chaos';
|
||||||
import { CursorEffectsJoke } from "./jokes/cursor";
|
import {CursorEffectsJoke} from './jokes/cursor';
|
||||||
import { StupidTitleJoke } from "./jokes/stupid_title";
|
import {StupidTitleJoke} from './jokes/stupid_title';
|
||||||
|
|
||||||
(window as any).AprilJokes = ((jokes: JokeClassList): JokerClass => {
|
declare global {
|
||||||
|
interface Window { AprilJokes: JokerClass; }
|
||||||
|
}
|
||||||
|
|
||||||
|
window.AprilJokes = ((jokes: JokeList): JokerClass => {
|
||||||
const cl = new JokerClass();
|
const cl = new JokerClass();
|
||||||
|
|
||||||
jokes.forEach((joke) => {
|
jokes.forEach((CustomJoke) => {
|
||||||
cl.add(new joke());
|
cl.add(new CustomJoke());
|
||||||
});
|
});
|
||||||
|
|
||||||
$(() => cl.regularStart());
|
$(() => cl.regularStart());
|
||||||
@@ -30,4 +34,4 @@ import { StupidTitleJoke } from "./jokes/stupid_title";
|
|||||||
StupidTitleJoke,
|
StupidTitleJoke,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
interface JokeClassList extends Array<new () => Joke<any>> {}
|
interface JokeList extends Array<new () => Joke<JokeSettings>> {}
|
||||||
|
|||||||
Vendored
+108
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Настройки формы ответа MyBB
|
||||||
|
*/
|
||||||
|
export type MybbEditor = {
|
||||||
|
settings: MybbEditorSettings;
|
||||||
|
[key: string]: MybbEditorTag | MybbEditorSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общий объект настройки тега MyBB
|
||||||
|
*/
|
||||||
|
export class MybbEditorTag {
|
||||||
|
/**
|
||||||
|
* Название кнопки.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Функция, которая будет вызвана при нажатии кнопки.
|
||||||
|
*/
|
||||||
|
onclick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общий объект настройки формы ответа MyBB
|
||||||
|
*/
|
||||||
|
export type MybbEditorSettings = {
|
||||||
|
autofocus: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Информация о теме
|
||||||
|
*/
|
||||||
|
export class MybbTopic {
|
||||||
|
/**
|
||||||
|
* Тема сообщения
|
||||||
|
*/
|
||||||
|
subject: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Флаг закрытия
|
||||||
|
* @type "0"|"1"
|
||||||
|
*/
|
||||||
|
closed: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество ответов в теме
|
||||||
|
*/
|
||||||
|
num_replies: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество просмотров темы
|
||||||
|
*/
|
||||||
|
num_views: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID форума
|
||||||
|
*/
|
||||||
|
forum_id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Имя форума
|
||||||
|
*/
|
||||||
|
forum_name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Список модераторов форума,
|
||||||
|
* ключ - ID пользователя, значение - имя модератора
|
||||||
|
*/
|
||||||
|
moderators: {
|
||||||
|
[key in string]: string
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Объект языков
|
||||||
|
*/
|
||||||
|
language: {
|
||||||
|
share_legend: string
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Настройки видео-хостингов
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line
|
||||||
|
export class MYBB_vsc {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
cH: any;
|
||||||
|
RG: { [key: string]: MYBB_vsc_item };
|
||||||
|
checkHost: (hostingItem: MYBB_vsc_item, input: string) => boolean;
|
||||||
|
clickHost: (element: HTMLAnchorElement) => void;
|
||||||
|
parse: () => void;
|
||||||
|
isLink: (input: string) => boolean;
|
||||||
|
message: (html: string) => void;
|
||||||
|
reInit: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Настройка отдельного видео-хостинга
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line
|
||||||
|
type MYBB_vsc_item = {
|
||||||
|
l: '0' | '1';
|
||||||
|
t: string;
|
||||||
|
x: RegExp;
|
||||||
|
nf: string;
|
||||||
|
}
|
||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Объект утилит ForumDUtils
|
||||||
|
*/
|
||||||
|
export class ForumDUtils {
|
||||||
|
/**
|
||||||
|
* Проверяет, разрешён ли запуск скрипта
|
||||||
|
*/
|
||||||
|
check(): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ошибка, сообщающая о невозможности запуска скрипта
|
||||||
|
*/
|
||||||
|
error(): Error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Набор настроек скриптов
|
||||||
|
*/
|
||||||
|
scripts: {
|
||||||
|
[key in string]: ForumDUtilsScript;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс настроек скриптов
|
||||||
|
*/
|
||||||
|
export abstract class ForumDUtilsScript {
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
declare module "*.html" {
|
declare module '*.html' {
|
||||||
const content: string;
|
const content: string;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
Vendored
+335
@@ -0,0 +1,335 @@
|
|||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
import {MYBB_vsc, MybbEditor, MybbTopic} from './FORUM';
|
||||||
|
import {ForumDUtils} from './ForumDUtils';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
/**
|
||||||
|
* Объект для работы с ForumD Utils.
|
||||||
|
*/
|
||||||
|
FDU?: ForumDUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Объект настроек форума.
|
||||||
|
*/
|
||||||
|
FORUM: {
|
||||||
|
topic?: MybbTopic;
|
||||||
|
editor?: MybbEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставить в форму цитату в теге [quote].
|
||||||
|
* @param {string} author Автор сообщения
|
||||||
|
* @param {number} postId ID сообщения, из которого происходит цитата
|
||||||
|
*/
|
||||||
|
quote(author: string, postId: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка BB-кода.
|
||||||
|
* @param {string} tagStart Текст, что будет вставлен до выделения
|
||||||
|
* @param {string} tagEnd Текст, что будет вставлен после выделения
|
||||||
|
*/
|
||||||
|
bbcode(tagStart: string, tagEnd: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Изменить видимость служебной области.
|
||||||
|
* @param {string} areaName Идентификатор области
|
||||||
|
*/
|
||||||
|
changeVisibility(areaName: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка сообщения.
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
insert(value: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставить смайл.
|
||||||
|
* @param {string} emote Код смайла
|
||||||
|
*/
|
||||||
|
smile(emote: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка тега таблицы.
|
||||||
|
* @param {number} rows Количество строк
|
||||||
|
* @param {number} columns Количество столбцов
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
tag_table(rows: number, columns: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Метод выбора видео-хостинга.
|
||||||
|
* @param {HTMLElement} element Элемент
|
||||||
|
* @param {Event|Event[]} event Событие
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
MYBB_vsi(element: HTMLElement, event: Event|Event[]): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Объект с правилами для видео-тегов.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
MYBB_vsc: MYBB_vsc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка загруженного изображения.
|
||||||
|
* @param {HTMLElement | JQuery} element Элемент области вставки
|
||||||
|
*/
|
||||||
|
insertUploadedImage(element: HTMLElement | JQuery): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка тега спойлера.
|
||||||
|
* @param {string} spoilerType Тип спойлера
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
tag_spoiler(spoilerType: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставка символа клавиатуры.
|
||||||
|
* @param {string} character Вставляемый символ
|
||||||
|
*/
|
||||||
|
keyboard(character: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Вставить обращение к пользователю.
|
||||||
|
* @param {string} target Имя пользователя
|
||||||
|
*/
|
||||||
|
to(target: string): void;
|
||||||
|
|
||||||
|
// ===== Переменные форума =====
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID форума.
|
||||||
|
*/
|
||||||
|
BoardID: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Категория форума в каталоге.
|
||||||
|
*/
|
||||||
|
BoardCat: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Название стиля форума или `Custom`, если используется свой стиль.
|
||||||
|
*/
|
||||||
|
BoardStyle: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API-код пользователя.
|
||||||
|
*/
|
||||||
|
ForumAPITicket: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID группы пользователя.
|
||||||
|
* `1` - это группа администраторов, `2` - модераторов, `3` - гостей.
|
||||||
|
*/
|
||||||
|
GroupID: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Название группы пользователя.
|
||||||
|
*/
|
||||||
|
GroupTitle: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Статус группы пользователя.
|
||||||
|
*/
|
||||||
|
GroupUserTitle: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID партнёра форума.
|
||||||
|
*/
|
||||||
|
PartnerID: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время запроса к форуму.
|
||||||
|
*/
|
||||||
|
RequestTime: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс URL для доступа к статическим файлам.
|
||||||
|
* Не имеет заключающей косой черты.
|
||||||
|
*/
|
||||||
|
StaticURL: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс URL для доступа к аватарам.
|
||||||
|
* Не имеет заключающей косой черты.
|
||||||
|
*/
|
||||||
|
AvatarsURL: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс URL для доступа к файлам форума.
|
||||||
|
* Не имеет заключающей косой черты.
|
||||||
|
*/
|
||||||
|
FilesURL: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс URL для доступа к скриптам.
|
||||||
|
* Не имеет заключающей косой черты.
|
||||||
|
*/
|
||||||
|
ScriptsURL: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс URL для доступа к загружаемым файлам.
|
||||||
|
* Не имеет заключающей косой черты.
|
||||||
|
*/
|
||||||
|
UploadsURL: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID пользователя.
|
||||||
|
*/
|
||||||
|
UserID?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Логин пользователя.
|
||||||
|
*/
|
||||||
|
UserLogin?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Имя пользователя.
|
||||||
|
*/
|
||||||
|
UserName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Статус пользователя
|
||||||
|
*/
|
||||||
|
UserTitle?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Пол пользователя.
|
||||||
|
* 0 - мужской, 1 - женский.
|
||||||
|
*/
|
||||||
|
UserSex?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возраст пользователя.
|
||||||
|
*/
|
||||||
|
UserAge?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дата рождения пользователя.
|
||||||
|
*/
|
||||||
|
UserBirthDate?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ссылка на аватар пользователя.
|
||||||
|
* Не содержит домен, но имеет начальную косую черту.
|
||||||
|
* @see AvatarsURL
|
||||||
|
*/
|
||||||
|
UserAvatar?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время регистрации пользователя.
|
||||||
|
*/
|
||||||
|
UserRegistered?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Код приглашения пользователя.
|
||||||
|
*/
|
||||||
|
UserInviteCode?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество сообщений пользователя.
|
||||||
|
*/
|
||||||
|
UserPosts?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время последнего сообщения.
|
||||||
|
*/
|
||||||
|
UserLastPost?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время последнего посещения.
|
||||||
|
*/
|
||||||
|
UserLastVisit?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время пребывания пользователя на форуме.
|
||||||
|
*/
|
||||||
|
UserTotalTime?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество плюсов, полученных пользователем.
|
||||||
|
*/
|
||||||
|
UserRespectPlus?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество минусов, полученных пользователем.
|
||||||
|
*/
|
||||||
|
UserRespectMinus?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество плюсов, поставленных пользователем.
|
||||||
|
*/
|
||||||
|
UserPositivePlus?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Количество плюсов, поставленных пользователем.
|
||||||
|
*/
|
||||||
|
UserPositiveMinus?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Уникальный ID пользователя.
|
||||||
|
*/
|
||||||
|
UserUniqueID?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Язык пользователя.
|
||||||
|
*/
|
||||||
|
UserLanguage?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Путь к папке.
|
||||||
|
*/
|
||||||
|
UserUploadsDir?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 1.
|
||||||
|
*/
|
||||||
|
UserFld1?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 2.
|
||||||
|
*/
|
||||||
|
UserFld2?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 3.
|
||||||
|
*/
|
||||||
|
UserFld3?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 4.
|
||||||
|
*/
|
||||||
|
UserFld4?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 5.
|
||||||
|
*/
|
||||||
|
UserFld5?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 6.
|
||||||
|
*/
|
||||||
|
UserFld6?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 7.
|
||||||
|
*/
|
||||||
|
UserFld7?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 8.
|
||||||
|
*/
|
||||||
|
UserFld8?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Дополнительное поле форума 9.
|
||||||
|
*/
|
||||||
|
UserFld9?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JQuery {
|
||||||
|
mybbModal(data: object): JQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,23 +1,36 @@
|
|||||||
/// <reference path="html.d.ts"/>
|
// / <reference path="html.d.ts"/>
|
||||||
import { JokerClass } from "./joker";
|
|
||||||
import $ from "jquery";
|
|
||||||
import button_html from "./html/button.html";
|
|
||||||
import styles_html from "./html/styles.html";
|
|
||||||
import window_html from "./html/window.html";
|
|
||||||
|
|
||||||
|
import './types/html.d.ts';
|
||||||
|
import './types/mybb.d.ts';
|
||||||
|
|
||||||
|
import {JokerClass} from './joker';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import buttonHTML from './html/button.html';
|
||||||
|
import stylesHTML from './html/styles.html';
|
||||||
|
import windowHTML from './html/window.html';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс интерфейса настроек
|
||||||
|
*/
|
||||||
export class JokerUI {
|
export class JokerUI {
|
||||||
joker: JokerClass;
|
joker: JokerClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создание класса интерфейса настроек
|
||||||
|
*
|
||||||
|
* @param {JokerClass} joker
|
||||||
|
*/
|
||||||
constructor(joker: JokerClass) {
|
constructor(joker: JokerClass) {
|
||||||
this.joker = joker;
|
this.joker = joker;
|
||||||
|
|
||||||
$('link[rel="stylesheet"]').eq(0).before(styles_html);
|
$('link[rel="stylesheet"]').eq(0).before(stylesHTML);
|
||||||
|
|
||||||
const button = this.button;
|
const button = this.button;
|
||||||
|
|
||||||
button.hide();
|
button.hide();
|
||||||
(<any>button).mybbModal({
|
|
||||||
title: "Настройки первоапрельских шуток",
|
button.mybbModal({
|
||||||
|
title: 'Настройки первоапрельских шуток',
|
||||||
content: () => this.render(),
|
content: () => this.render(),
|
||||||
closer: true,
|
closer: true,
|
||||||
noscroll: true,
|
noscroll: true,
|
||||||
@@ -25,40 +38,53 @@ export class JokerUI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get button() {
|
/**
|
||||||
let button = $(".april-fools__button");
|
* Основная кнопка, открывающая настройки
|
||||||
|
* @return {JQuery<HTMLButtonElement>}
|
||||||
|
*/
|
||||||
|
get button(): JQuery<HTMLButtonElement> {
|
||||||
|
let button = $('.april-fools__button');
|
||||||
|
|
||||||
if (button.length === 0) {
|
if (button.length === 0) {
|
||||||
button = $(button_html).appendTo("body");
|
button = $(buttonHTML).appendTo('body');
|
||||||
}
|
}
|
||||||
|
|
||||||
return button;
|
return button as JQuery<HTMLButtonElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Показать кнопку настроек
|
||||||
|
*/
|
||||||
show() {
|
show() {
|
||||||
this.button.show();
|
this.button.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): JQuery {
|
/**
|
||||||
const result: JQuery = $("<div></div>").html(window_html);
|
* Создать окно настроек
|
||||||
const row_template = $("#april-fools__window-row", result).html();
|
* @return {JQuery<HTMLDivElement>}
|
||||||
const joke_container = $(".april-fools__jokes", result);
|
*/
|
||||||
|
render(): JQuery<HTMLDivElement> {
|
||||||
|
const result = $('<div></div>').html(windowHTML) as JQuery<HTMLDivElement>;
|
||||||
|
const rowTemplate = $('#april-fools__window-row', result).html();
|
||||||
|
const jokeContainer = $('.april-fools__jokes', result);
|
||||||
|
|
||||||
for (const joke of Object.values(this.joker.jokes)) {
|
for (const joke of Object.values(this.joker.jokes)) {
|
||||||
const row = $(eval("`" + row_template + "`"));
|
const row = $(eval('`' + rowTemplate + '`'));
|
||||||
$('input[type="checkbox"]', row)
|
$('input[type="checkbox"]', row)
|
||||||
.prop("checked", joke.settings.enabled)
|
.prop('checked', joke.settings.enabled)
|
||||||
.on("click", (e) =>
|
.on('click', (e) => {
|
||||||
this.joker.toggleJoke(joke.id, (<any>e).currentTarget.checked)
|
const target = (e.currentTarget as HTMLInputElement);
|
||||||
|
this.joker.toggleJoke(joke.id, target.checked);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
joke_container.append(row);
|
jokeContainer.append(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
$("button", result).on("click", async () => {
|
$('button', result).on('click', async () => {
|
||||||
await this.joker.clearUserStates();
|
await this.joker.clearUserStates();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
return $(".april-fools__content", result);
|
return $('.april-fools__content', result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user