Merge branch 'master' into newads

This commit is contained in:
Miodec 2023-02-26 13:39:55 +01:00
commit 6b445b1927
32 changed files with 565 additions and 33 deletions

View file

@ -89,7 +89,7 @@
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"project": "./tsconfig.json"
"project": "**/tsconfig.json"
}
}
]

View file

@ -283,7 +283,8 @@ export async function addResult(
result.mode === "time" &&
result.wpm > 130 &&
result.testDuration < 122 &&
(user.verified === false || user.verified === undefined)
(user.verified === false || user.verified === undefined) &&
user.lbOptOut !== true
) {
if (!result.keySpacingStats || !result.keyDurationStats) {
const status = MonkeyStatusCodes.MISSING_KEY_DATA;
@ -389,7 +390,8 @@ export async function addResult(
const validResultCriteria =
(funbox === "none" || funbox === "plus_one" || funbox === "plus_two") &&
!bailedOut &&
!user.banned &&
user.banned !== true &&
user.lbOptOut !== true &&
(process.env.MODE === "dev" || (user.timeTyping ?? 0) > 7200);
const selectedBadgeId = user.inventory?.badges?.find((b) => b.selected)?.id;
@ -438,7 +440,8 @@ export async function addResult(
const weeklyXpLeaderboardConfig = req.ctx.configuration.leaderboards.weeklyXp;
let weeklyXpLeaderboardRank = -1;
const eligibleForWeeklyXpLeaderboard =
!user.banned &&
user.banned !== true &&
user.lbOptOut !== true &&
(process.env.MODE === "dev" || (user.timeTyping ?? 0) > 7200);
const weeklyXpLeaderboard = WeeklyXpLeaderboard.get(

View file

@ -201,6 +201,21 @@ export async function clearPb(
return new MonkeyResponse("User's PB cleared");
}
export async function optOutOfLeaderboards(
req: MonkeyTypes.Request
): Promise<MonkeyResponse> {
const { uid } = req.ctx.decodedToken;
await UserDAL.optOutOfLeaderboards(uid);
await purgeUserFromDailyLeaderboards(
uid,
req.ctx.configuration.dailyLeaderboards
);
Logger.logToDb("user_opted_out_of_leaderboards", "", uid);
return new MonkeyResponse("User opted out of leaderboards");
}
export async function checkName(
req: MonkeyTypes.Request
): Promise<MonkeyResponse> {
@ -606,6 +621,7 @@ export async function getProfile(
discordAvatar,
xp,
streak,
lbOptOut,
} = user;
const validTimePbs = _.pick(personalBests?.time, "15", "30", "60", "120");
@ -633,6 +649,7 @@ export async function getProfile(
xp,
streak: streak?.length ?? 0,
maxStreak: streak?.maxLength ?? 0,
lbOptOut,
};
if (banned) {

View file

@ -202,6 +202,15 @@ router.delete(
asyncHandler(UserController.clearPb)
);
router.post(
"/optOutOfLeaderboards",
authenticateRequest({
requireFreshToken: true,
}),
RateLimit.userOptOutOfLeaderboards,
asyncHandler(UserController.optOutOfLeaderboards)
);
const requireFilterPresetsEnabled = validateConfiguration({
criteria: (configuration) => {
return configuration.results.filterPresets.enabled;

View file

@ -59,7 +59,7 @@ const RESULT_SCHEMA = joi
numbers: joi.boolean().required(),
punctuation: joi.boolean().required(),
quoteLength: joi.number(),
rawWpm: joi.number().required(),
rawWpm: joi.number().min(0).max(420).required(),
restartCount: joi.number().required(),
smoothConsistency: joi.number().optional(), // to be removed
tags: joi
@ -69,7 +69,7 @@ const RESULT_SCHEMA = joi
testDuration: joi.number().required().min(1),
timestamp: joi.date().timestamp().required(),
uid: joi.string().required(),
wpm: joi.number().min(0).max(350).required(),
wpm: joi.number().min(0).max(420).required(),
wpmConsistency: joi.number().min(0).required(),
})
.required();

View file

@ -79,6 +79,7 @@ export async function resetUser(uid: string): Promise<void> {
$unset: {
discordAvatar: "",
discordId: "",
lbOptOut: "",
},
}
);
@ -136,6 +137,20 @@ export async function clearPb(uid: string): Promise<void> {
);
}
export async function optOutOfLeaderboards(uid: string): Promise<void> {
await getUsersCollection().updateOne(
{ uid },
{
$set: {
lbOptOut: true,
lbPersonalBests: {
time: {},
},
},
}
);
}
export async function updateQuoteRatings(
uid: string,
quoteRatings: MonkeyTypes.UserQuoteRatings

View file

@ -348,6 +348,13 @@ export const userClearPB = rateLimit({
handler: customHandler,
});
export const userOptOutOfLeaderboards = rateLimit({
windowMs: ONE_HOUR_MS,
max: 10 * REQUEST_MULTIPLIER,
keyGenerator: getKeyWithUid,
handler: customHandler,
});
export const userCustomFilterAdd = rateLimit({
windowMs: ONE_HOUR_MS,
max: 60 * REQUEST_MULTIPLIER,

View file

@ -189,6 +189,7 @@ declare namespace MonkeyTypes {
inbox?: MonkeyMail[];
streak?: UserStreak;
lastReultHashes?: string[];
lbOptOut?: boolean;
}
interface UserStreak {

View file

@ -209,6 +209,9 @@
align-self: normal;
color: var(--text-color);
grid-area: text;
.red {
color: var(--error-color);
}
}
.inputs {

View file

@ -37,6 +37,10 @@ export default class Users {
return await this.httpClient.patch(`${BASE_PATH}/reset`);
}
async optOutOfLeaderboards(): Ape.EndpointData {
return await this.httpClient.post(`${BASE_PATH}/optOutOfLeaderboards`);
}
async updateName(name: string): Ape.EndpointData {
return await this.httpClient.patch(`${BASE_PATH}/name`, {
payload: { name },

View file

@ -669,7 +669,14 @@ $(document).on("keydown", (e) => {
trigger(command);
return;
}
if (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Tab") {
if (
e.key === "ArrowUp" ||
e.key === "ArrowDown" ||
e.key === "Tab" ||
// Should only branch if ctrl is held to allow the letters to still be typed
(e.ctrlKey &&
(e.key === "p" || e.key === "n" || e.key === "j" || e.key === "k"))
) {
e.preventDefault();
$("#commandLineWrapper #commandLine .suggestions .entry").unbind(
"mouseenter mouseleave"
@ -682,7 +689,10 @@ $(document).on("keydown", (e) => {
});
if (
e.key === "ArrowUp" ||
(e.key === "Tab" && e.shiftKey && Config.quickRestart !== "esc")
(e.key === "Tab" && e.shiftKey && Config.quickRestart !== "esc") ||
// Don't need to check for ctrl because that was already done above
e.key === "p" ||
e.key === "k"
) {
entries.removeClass("activeKeyboard");
if (activenum == 0) {
@ -695,7 +705,9 @@ $(document).on("keydown", (e) => {
}
if (
e.key === "ArrowDown" ||
(e.key === "Tab" && !e.shiftKey && Config.quickRestart !== "esc")
(e.key === "Tab" && !e.shiftKey && Config.quickRestart !== "esc") ||
e.key === "n" ||
e.key === "j"
) {
entries.removeClass("activeKeyboard");
if (activenum + 1 == entries.length) {

View file

@ -18,6 +18,7 @@ export function setSnapshot(
): void {
const originalBanned = dbSnapshot?.banned;
const originalVerified = dbSnapshot?.verified;
const lbOptOut = dbSnapshot?.lbOptOut;
//not allowing user to override these values i guess?
try {
@ -26,10 +27,14 @@ export function setSnapshot(
try {
delete newSnapshot?.verified;
} catch {}
try {
delete newSnapshot?.lbOptOut;
} catch {}
dbSnapshot = newSnapshot;
if (dbSnapshot) {
dbSnapshot.banned = originalBanned;
dbSnapshot.verified = originalVerified;
dbSnapshot.lbOptOut = lbOptOut;
}
}
@ -91,6 +96,7 @@ export async function initSnapshot(): Promise<
snap.name = userData.name;
snap.personalBests = userData.personalBests;
snap.banned = userData.banned;
snap.lbOptOut = userData.lbOptOut;
snap.verified = userData.verified;
snap.discordId = userData.discordId;
snap.discordAvatar = userData.discordAvatar;

View file

@ -150,11 +150,20 @@ function updateFooter(lb: LbKey): void {
return;
}
$(`#leaderboardsWrapper table.${side} tfoot`).html(`
if (DB.getSnapshot()?.lbOptOut === true) {
$(`#leaderboardsWrapper table.${side} tfoot`).html(`
<tr>
<td colspan="6" style="text-align:center;">You have opted out of the leaderboards</>
</tr>
`);
return;
} else {
$(`#leaderboardsWrapper table.${side} tfoot`).html(`
<tr>
<td colspan="6" style="text-align:center;">Not qualified</>
</tr>
`);
}
let toppercent;
if (currentTimeRange === "allTime" && currentRank[lb]) {

View file

@ -31,6 +31,8 @@ export async function update(
const banned = profile.banned === true;
const lbOptOut = profile.lbOptOut === true;
if (!details || !profile || !profile.name || !profile.addedAt) return;
details.find(".placeholderAvatar").removeClass("hidden");
@ -75,6 +77,14 @@ export async function update(
);
}
if (lbOptOut) {
details
.find(".name")
.append(
`<div class="bannedIcon" aria-label="This account has opted out of leaderboards" data-balloon-pos="up"><i class="fas fa-crown"></i></div>`
);
}
updateNameFontSize(where);
const joinedText = "Joined " + format(profile.addedAt ?? 0, "dd MMM yyyy");

View file

@ -828,6 +828,10 @@ export function showAccountSection(): void {
refreshTagsSettingsSection();
refreshPresetsSettingsSection();
updateDiscordSection();
if (DB.getSnapshot()?.lbOptOut === true) {
$(".pageSettings .section.optOutOfLeaderboards").remove();
}
}
export async function update(groupUpdate = true): Promise<void> {

View file

@ -183,7 +183,7 @@ $(`${popup} .randomInputFields .time input`).on("keypress", () => {
function apply(): void {
let text = ($(`${popup} textarea`).val() as string).normalize();
// text = text.trim();
text = text.trim();
// text = text.replace(/[\r]/gm, " ");
text = text.replace(/\\\\t/gm, "\t");
text = text.replace(/\\\\n/gm, "\n");

View file

@ -734,7 +734,7 @@ list["resetAccount"] = new SimplePopup(
Notifications.add("Resetting settings...", 0);
UpdateConfig.reset();
Loader.show();
Notifications.add("Resetting account and stats...", 0);
Notifications.add("Resetting account...", 0);
const response = await Ape.users.reset();
if (response.status !== 200) {
@ -772,6 +772,71 @@ list["resetAccount"] = new SimplePopup(
}
);
list["optOutOfLeaderboards"] = new SimplePopup(
"optOutOfLeaderboards",
"text",
"Opt out of leaderboards",
[
{
placeholder: "Password",
type: "password",
initVal: "",
},
],
"Are you sure you want to opt out of leaderboards?",
"Opt out",
async (_thisPopup, password: string) => {
try {
const user = Auth?.currentUser;
if (!user) return;
if (user.providerData.find((p) => p?.providerId === "password")) {
const credential = EmailAuthProvider.credential(
user.email as string,
password
);
await reauthenticateWithCredential(user, credential);
} else {
await reauthenticateWithPopup(user, AccountController.gmailProvider);
}
Loader.show();
const response = await Ape.users.optOutOfLeaderboards();
if (response.status !== 200) {
Loader.hide();
return Notifications.add(
`Failed to opt out of leaderboards: ${response.message}`,
-1
);
}
Loader.hide();
Notifications.add("Leaderboard opt out successful", 1);
setTimeout(() => {
location.reload();
}, 3000);
} catch (e) {
const typedError = e as FirebaseError;
Loader.hide();
if (typedError.code === "auth/wrong-password") {
Notifications.add("Incorrect password", -1);
} else {
Notifications.add("Something went wrong: " + e, -1);
}
}
},
(thisPopup) => {
const user = Auth?.currentUser;
if (!user) return;
if (!user.providerData.find((p) => p?.providerId === "password")) {
thisPopup.inputs = [];
thisPopup.buttonText = "Reauthenticate to reset";
}
},
(_thisPopup) => {
//
}
);
list["clearTagPb"] = new SimplePopup(
"clearTagPb",
"text",
@ -1376,6 +1441,14 @@ $(".pageSettings #resetAccount").on("click", () => {
list["resetAccount"].show();
});
$(".pageSettings #optOutOfLeaderboardsButton").on("click", () => {
if (!ConnectionState.get()) {
Notifications.add("You are offline", 0, 2);
return;
}
list["optOutOfLeaderboards"].show();
});
$("#popups").on("click", "#apeKeysPopup .generateApeKey", () => {
if (!ConnectionState.get()) {
Notifications.add("You are offline", 0, 2);

View file

@ -31,6 +31,13 @@ const accents: [string, string][] = [
["ٍ", ""],
["ّ", ""],
["ё", "е"],
["ά", "α"],
["έ", "ε"],
["ί", "ι"],
["ύ", "υ"],
["ό", "ο"],
["ή", "η"],
["ώ", "ω"],
];
export function replaceAccents(

View file

@ -4,14 +4,10 @@ import * as ConfigEvent from "../observables/config-event";
export async function update(burst: number): Promise<void> {
if (!Config.showLiveBurst) return;
let number = burst;
if (Config.blindMode) {
number = 0;
}
(document.querySelector("#miniTimerAndLiveWpm .burst") as Element).innerHTML =
number.toString();
burst.toString();
(document.querySelector("#liveBurst") as Element).innerHTML =
number.toString();
burst.toString();
}
export function show(): void {

View file

@ -565,6 +565,7 @@ declare namespace MonkeyTypes {
inboxUnreadSize: number;
streak: number;
maxStreak: number;
lbOptOut?: boolean;
}
interface UserDetails {

View file

@ -2760,8 +2760,9 @@
<span>reset settings</span>
</div>
<div class="text">
Resets settings to the default (but doesn't touch your tags). Warning:
you can't undo this action!
Resets settings to the default (but doesn't touch your tags).
<br />
<span class="red">You can't undo this action!</span>
</div>
<div class="buttons">
<div
@ -2781,7 +2782,9 @@
</div>
<div class="text">
Resets all your personal bests (but doesn't delete any tests from your
history). Warning: you can't undo this action!
history).
<br />
<span class="red">You can't undo this action!</span>
</div>
<div class="buttons">
<div
@ -2794,12 +2797,38 @@
</div>
</div>
</div>
<div class="section optOutOfLeaderboards needsAccount hidden">
<div class="groupTitle">
<i class="fas fa-crown"></i>
<span>opt out of leaderboards</span>
</div>
<div class="text">
Use this if you frequently trigger the anticheat (for example if using
stenography) to opt out of leaderboards.
<br />
<span class="red">You can't undo this action!</span>
</div>
<div class="buttons">
<div
class="button danger"
id="optOutOfLeaderboardsButton"
tabindex="0"
onclick="this.blur();"
>
opt out
</div>
</div>
</div>
<div class="section resetAccount needsAccount hidden">
<div class="groupTitle">
<i class="fas fa-redo-alt"></i>
<span>reset account</span>
</div>
<div class="text">Completely resets your account to a blank state.</div>
<div class="text">
Completely resets your account to a blank state.
<br />
<span class="red">You can't undo this action!</span>
</div>
<div class="buttons">
<div
class="button danger"
@ -2816,7 +2845,11 @@
<i class="fas fa-trash"></i>
<span>delete account</span>
</div>
<div class="text">Deletes your account and all data connected to it.</div>
<div class="text">
Deletes your account and all data connected to it.
<br />
<span class="red">You can't undo this action!</span>
</div>
<div class="buttons">
<div
class="button danger"

View file

@ -512,7 +512,7 @@
</div>
Replace new lines with spaces
<span>
Replace all new line characters with spaces. Can automatically adds
Replace all new line characters with spaces. Can automatically add
periods to the end of lines if you wish.
</span>
</label>

View file

@ -0,0 +1,284 @@
{
"name": "chinese_traditional",
"leftToRight": true,
"noLazyMode": true,
"words": [
"安靜",
"安全",
"按摩",
"包子",
"保護",
"報告",
"抱歉",
"背包",
"本子",
"鉛筆盒",
"比賽",
"筆記",
"表揚",
"餐具",
"操場",
"草莓",
"橙子",
"城堡",
"成績",
"承諾",
"成功",
"出發",
"傳統",
"窗戶",
"春天",
"錯誤",
"大門",
"大象",
"帶路",
"蛋糕",
"單車",
"盼望",
"丹麥",
"淡水",
"道路",
"得分",
"德國",
"登山",
"地球",
"地圖",
"滴水",
"點心",
"電話",
"店家",
"定時",
"豆芽",
"讀書",
"賭博",
"堆積",
"堆雪人",
"對話",
"多雲",
"夥伴",
"房間",
"放學",
"風景",
"風箏",
"服務",
"富士山",
"富士蘋",
"高高興興",
"高原",
"告訴",
"狗狗",
"故事",
"鼓勵",
"股票",
"股份",
"掛號",
"光亮",
"廣場",
"廣告",
"國旗",
"果汁",
"過年",
"過程",
"哈密瓜",
"海灘",
"害怕",
"寒假",
"含笑",
"漢堡",
"好孩子",
"好污",
"黑板",
"繪本",
"回憶",
"火車",
"機器人",
"積木",
"季節",
"家長",
"家庭",
"假日",
"假期",
"建築",
"講話",
"角落",
"腳踏車",
"教師",
"教室",
"餃子",
"接納",
"結果",
"解釋",
"訣竅",
"警察",
"景象",
"鏡子",
"舊金山",
"舉手",
"開心",
"開朗",
"開學",
"科學",
"課本",
"棵樹",
"空氣",
"空氣清新",
"空氣汙染",
"空氣流通",
"空中飛人",
"口渴",
"口香糖",
"哭泣",
"誇獎",
"塊餅",
"快樂",
"拉麵",
"辣椒",
"懶骨頭",
"浪漫",
"老師",
"冷氣",
"禮拜天",
"練習",
"鯉魚",
"力量",
"立志",
"例行",
"連線",
"連續",
"鏈子",
"綠色",
"綠豆湯",
"旅遊",
"旅行",
"輪流",
"輪胎",
"論文",
"綿羊",
"麵包",
"面對",
"迷宮",
"秘密",
"密碼",
"米飯",
"蜜蜂",
"民宿",
"明信片",
"明天",
"命運",
"名字",
"鳴叫",
"魔法",
"魔術",
"牛奶",
"女士",
"女孩",
"女孩子",
"女兒",
"盆栽",
"批改",
"皮膚",
"啤酒",
"脾氣",
"篇章",
"騎馬",
"期望",
"起飛",
"氣球",
"汽水",
"氣味",
"氣溫",
"汽車",
"欠債",
"愜意",
"清潔",
"清新",
"清爽",
"清晨",
"青蛙",
"情緒",
"情感",
"親情",
"親密",
"親吻",
"親戚",
"勤勞",
"青少年",
"青菜",
"青年",
"青蛙",
"清潔劑",
"秋天",
"球場",
"求助",
"求知",
"裙子",
"群眾",
"人口",
"人類",
"人物",
"人才",
"人生",
"日出",
"日落",
"日光",
"日曆",
"日本",
"日報",
"熱狗",
"熱鬧",
"熱情",
"熱心",
"熱氣球",
"熱帶",
"熱線",
"熱帶雨林",
"熱水器",
"熱炒",
"熱門",
"任務",
"日用品",
"榮譽",
"乳酪",
"肉球",
"軟體",
"軟糖",
"若菜",
"桶裝水",
"沙發",
"沙灘",
"山脈",
"山水",
"山丘",
"商店",
"商業",
"商人",
"商標",
"上學",
"上課",
"上班",
"上網",
"燒烤",
"燒餅",
"鞋子",
"神話",
"神秘",
"神聖",
"神奇",
"身高",
"身影",
"身材",
"身心",
"身體",
"生命",
"生活",
"生產",
"生物",
"生日",
"生態",
"聲音",
"慎重",
"甚至",
"石頭",
"十字路口"
]
}

View file

@ -1,7 +1,6 @@
{
"name": "greek",
"leftToRight": true,
"noLazyMode": true,
"bcp47": "el-GR",
"words": [
"άρθρο",

View file

@ -1,7 +1,6 @@
{
"name": "greek_10k",
"leftToRight": true,
"noLazyMode": true,
"bcp47": "el-GR",
"words": [
"άγρια",

View file

@ -1,7 +1,6 @@
{
"name": "greek_1k",
"leftToRight": true,
"noLazyMode": true,
"bcp47": "el-GR",
"words": [
"άλλα",

View file

@ -1,7 +1,6 @@
{
"name": "greek_25k",
"leftToRight": true,
"noLazyMode": true,
"bcp47": "el-GR",
"words": [
"ά",

View file

@ -1,7 +1,6 @@
{
"name": "greek_5k",
"leftToRight": true,
"noLazyMode": true,
"bcp47": "el-GR",
"words": [
"άδεια",

View file

@ -359,8 +359,9 @@
<p>
For further information, see
<a href="https://en.wikipedia.org/wiki/HTTP_cookie" target="_blank">
HTTP cookie
</a> on Wikipedia.
HTTP cookie
</a>
on Wikipedia.
</p>
<h1 id="Usage_of_Cookies">How do we use cookies?</h1>

View file

@ -60,6 +60,18 @@
"source": "vkd3d 3D Graphics Library",
"length": 932,
"id": 9
},
{
"text": "struct nlist *lookup(char *);\\nchar *strdup(char *);\\n\\nstruct nlist *install(char *name, char *defn)\\n{\\n\\tstruct nlist *np;\\n\\tunsigned hashval;\\n\\tif ((np = lookup(name)) == NULL) {\\n\\t\\tnp = (struct nlist *) malloc(sizeof(*np));\\n\\t\\tif (np == NULL || (np->name = strdup(name)) == NULL)\\n\\t\\t\\treturn NULL;\\n\\t\\thashval = hash(name);\\n\\t\\tnp->next = hashtab[hashval];\\n\\t\\thashtab[hashval] = np;\\n\\t} else\\n\\t\\tfree((void *) np->defn);\\n\\tif ((np->defn = strdup(defn)) == NULL)\\n\\t\\treturn NULL;\\n\\treturn np;\\n}",
"source": "The C Programming Language (K&R)",
"length": 516,
"id": 10
},
{
"text": "int strcmp(char *s, char *t)\\n{\\n\\tfor ( ; *s == *t; s++, t++)\\n\\t\\tif (*s == '\\0')\\n\\t\\t\\treturn 0;\\n\\treturn *s - *t;\\n}",
"source": "The C Programming Language (K&R)",
"length": 122,
"id": 11
}
]
}

View file

@ -3216,6 +3216,36 @@
"source": "Die Kunst des klaren Denkens",
"length": 97,
"id": 543
},
{
"text": "Ich habe positive Gedanken, die meine Heilung fördern. Ich entscheide mich für Gesundheit und Wohlbefinden Ich bin glücklich und gesund. Mein Immunsystem ist ein starker, intelligenter und engagierter Beschützer meines Körpers. Ich bin frei und fühle mich gesund. Mein Körper ist ein Haus des Wohlbefindens. Ich atme tief durch und jeder Atemzug gibt mir Kraft. Mein Körper sagt mir, was er braucht. Ich erlaube mir zu glauben, dass ich es verdient habe, geheilt zu werden. Ich habe Vertrauen in meine Heilung. Je mehr ich mich entspanne, desto gesünder werde ich. Mein Geist ist klar und harmonisch. Meine Gefühle sind wichtige Botschaften meines Körpers. Ich glaube an die Heilkraft in mir, die jede Wunde heilt. Ich bin immer und überall ganz, heil und vollkommen beschützt. Ich unternehme gerne Schritte in Richtung eines gesünderen Lebensstils. Ich behandle meinen Körper mit Respekt und achte seine Grenzen. Ich empfinde meinen Körper als harmonisches Ganzes. Mein Körper produziert jede Minute eines jeden Tages neue gesunde Zellen. Meine Träume bringen mir neue Wege und Ideen, wie ich vollständig heilen kann.",
"source": "[1/5] 20 Affirmationen zur Selbstheilung",
"length": 1118,
"id": 544
},
{
"text": "Ich bin voller Energie, Freunde und Lebenskraft in allem, was ich tue. Ich habe Kraft, in Gesundheit und Vitalität zu gedeihen. Jeder Teil meines Körpers erfüllt seine Aufgaben leicht und natürlich. Ich vertraue auf mich. Ich vertraue auf meine Selbstheilungskräfte. Jede Zelle meines Körpers strahl Vitalität aus. Ich behandele meinen Körper behutsam und liebevoll. Ich bin bereit, an meine Fähigkeit zu glauben, Heilung und Glück zu schaffen. Mein Geist ist so klar und harmonisch. Ich bin bereit, heilende Energie zu erhalten. Ich bin kraftvoll, lebendig und ausdauernd. Ich bin fasziniert und voller Ehrfurcht, wie schnell ich heile. Mein Körper ist ein perfekter Heilmechanismus, weil Energie in mir ist. Meine Chakren sind in perfekter Harmonie. Ich bin in vollkommener Harmonie. Mein Körper weiß, wie er sich heilt. Ich kann tun, was ich mir vorgenommen habe, weil mir meine Gesundheit wichtig ist. Ich kann Heilung und Gesundheit aufgrund meiner Erfahrungen viel mehr schätzen. Ein Leben in Gesundheit steht mir zu, weil ich es wert bin. Mein Immunsystem ist stark. Mein Körper ist von heilender Kraft erfüllt.",
"source": "[2/5] 20 Affirmationen zur Selbstheilung",
"length": 1118,
"id": 545
},
{
"text": "Ich bin umgeben von gesunder, heilender und positiver Energie. Ich vergebe und lasse alles frei, was mir weh tut. Meinen Körper durchströmt eine heilende Energie. Ich bin stark. Ich bin in großartiger Form. Niemand außer mir entscheidet, wie ich mich fühle. Ich liebe es zu fühlen, wie mein Körper auf einem optimalen Niveau funktioniert. Ich weiß, dass Heilung Zeit braucht und jeden Tag stattfindet. Ich tue liebevoll alles, um meinen Körper bei der Aufrechterhaltung einer perfekten Gesundheit zu unterstützen. Ich liebe mich. Ich habe mich entschieden, gut und gesund zu leben, um 100 Jahre alt zu werden. Du bist bereit, dein Leben so zu ändern, wie es sich für dich stimmig anfühlt. Durch meine Heilungsreise erreiche ich vollkommene Glückseligkeit und Erleuchtung. Der Schöpfer hat mich mit erstaunlichen Selbstheilungskräften gesegnet. Ich bin zu 100% gesund in meinem Körper. Ich passe mit Respekt und Liebe auf meinen Körper auf. Ich fühle herrliche, dynamische Energie. Ich bin aktiv und lebendig. Ich erweitere immer meinen Glauben an das, was möglich ist. Licht leuchtet aus jeder Zelle meines Körpers, mit jedem Schritt bin ich ganz. Mein Körper kennt den Heilungsweg, ich folge diesem Weg.",
"source": "[3/5] 20 Affirmationen zur Selbstheilung",
"length": 1204,
"id": 546
},
{
"text": "Meine Gesundheit ist vollkommen. Mein Geist und mein Körper sind in perfekter Balance. Ich bin ein harmonisches Wesen. Die Zellen meines Körpers nehmen den ganzen Tag über das Wohlbefinden auf. Ich entspanne mich und vertraue meinen Selbstheilungskräften. Mit jeder Entscheidung, die ich treffe, werde ich gesünder. Ich bin fähig und bereit meinen Körper zu heilen. Alle Zellen meines Körpers werden mit jedem Atemzug gesünder und vitaler. Ich erhalte meine Gesundheit durch positive Gedanken. Mein Körper ist der Tempel meiner Seele, ich finde Ruhe in mir. Meine Gesundheit wird im Hier und Jetzt zu einem Stadium der vollständigen Heilung gebracht. Jeden Tag lerne ich etwas Wunderbares über meine eigenen Gesundheitsbedürfnisse. Mein Körper ist ausgeglichen, gesund und gedeiht. Ich werde ein langes und gesundes Leben zu führen. Ich behandle meinen Körper wie einen reinen Tempel. Ich bin bereit, heilende Energie zu erhalten. Ich werde die Qualität meines Lebens verbessern. Ich atme heilende Luft ein und blase alle Negativität aus. Ich bin vollkommen gesund. Ich bin stark und gesund. Mein Körper weiß am besten, was ich brauche und ich gebe ihm das gerne.",
"source": "[4/5] 20 Affirmationen zur Selbstheilung",
"length": 1163,
"id": 547
},
{
"text": "Ich übernehme die Verantwortung für meine Gesundheit und stelle sie her. Ich bin der lebendige Ausdruck göttlicher Vollkommenheit. Mein heutiges Ziel ist es, jeden Satz positiv und heilend zu formulieren. Ich liebe meinen Körper und sorge gut für ihn. Ich werde auf völlig neue Weise gesund. Mein Körper ist auf die Weisheit des Universums abgestimmt. Ich bin stark. Ich liebe jede Zelle meines Körpers. Ich bin bereit, an meine Fähigkeit zu glauben, Heilung und Glück zu schaffen. Ich habe durch meine Geburt ein Recht auf bedingungslose Gesundheit. Ich bin voller Vertrauen. Mein Körper weiß alles was er wissen muss und er hat alle Mittel um Gesundheit zu erschaffen. Ich genieße strahlende Energie von innen. Mein Leben ist eine Frage der Wahl, und genau in dieser Sekunde entscheide ich mich für ein vollständig geheiltes Leben. Ich besitze natürliche, strahlende Heilkraft, die jetzt in mir arbeitet, ohne dass ich daran denke. Mir geht es gut. Ich schaffe eine positive, mentale Einstellung. Liebe kontrolliert mein Leben. Ich höre auf meinen Körper und helfe seinen Bedürfnissen. Ich liebe es, wie mein Geist und mein Körper miteinander kommunizieren, um meine Heilung zu unterstützen. Jeden Tag gebe ich Liebe und danke jedem Teil meines Körpers.",
"source": "[5/5] 20 Affirmationen zur Selbstheilung",
"length": 1255,
"id": 548
}
]
}

View file

@ -7,8 +7,8 @@
"prepare": "husky install",
"pre-commit": "pretty-quick --staged",
"lint": "npm run lint-be && npm run lint-fe",
"lint-be": "cd backend && eslint \"**/*.ts\"",
"lint-fe": "cd frontend && eslint \"**/*.ts\"",
"lint-be": "eslint \"./backend/**/*.ts\"",
"lint-fe": "eslint \"./frontend/**/*.ts\"",
"install-all": "sh ./bin/install.sh",
"install-windows": ".\\bin\\install.cmd",
"docker": "cd backend && docker-compose up",