mirror of
https://github.com/uditkarode/bing-chat-telegram.git
synced 2025-02-23 09:42:15 +00:00
130 lines
3.9 KiB
TypeScript
130 lines
3.9 KiB
TypeScript
// This code is licensed under the MIT License
|
|
// Copyright (c) MKRhere (https://mkr.pw)
|
|
import { FmtString } from "telegraf/format";
|
|
import { MessageEntity } from "typegram";
|
|
|
|
interface EntityCompare {
|
|
offset: number;
|
|
length: number;
|
|
}
|
|
|
|
/** get the starting of the entity */
|
|
const starts = (e: EntityCompare) => e.offset;
|
|
|
|
/** get the ending of the entity */
|
|
const ends = (e: EntityCompare) => e.offset + e.length;
|
|
|
|
const before = (A: EntityCompare, B: EntityCompare) =>
|
|
// B ends before A starts
|
|
ends(B) <= starts(A);
|
|
|
|
const after = (A: EntityCompare, B: EntityCompare) =>
|
|
// B starts after A ends
|
|
starts(B) >= ends(A);
|
|
|
|
const inside = (A: EntityCompare, B: EntityCompare) =>
|
|
// B starts with/after A and ends before A
|
|
(starts(B) >= starts(A) && ends(B) < ends(A)) ||
|
|
// B starts after A and ends before/with A
|
|
(starts(B) > starts(A) && ends(B) <= ends(A));
|
|
|
|
const contains = (A: EntityCompare, B: EntityCompare) =>
|
|
// B starts before/with A and ends with/after A
|
|
starts(B) <= starts(A) && ends(B) >= ends(A);
|
|
|
|
const endsInside = (A: EntityCompare, B: EntityCompare) =>
|
|
// B starts before A starts, ends after A starts, ends before B ends
|
|
starts(B) < starts(A) && ends(B) > starts(A) && ends(B) < ends(A);
|
|
|
|
const startsInside = (A: EntityCompare, B: EntityCompare) =>
|
|
// B starts after A, starts before A ends, ends after A
|
|
starts(B) > starts(A) && starts(B) < ends(A) && ends(B) > ends(A);
|
|
|
|
export const replace = (
|
|
source: string | FmtString,
|
|
search: string | RegExp,
|
|
value: string | FmtString | ((...match: string[]) => string | FmtString),
|
|
): FmtString => {
|
|
source = FmtString.normalise(source);
|
|
|
|
let text = source.text;
|
|
let entities: MessageEntity[] | undefined = source.entities;
|
|
|
|
function fixEntities(offset: number, length: number, correction: number) {
|
|
const A = { offset, length };
|
|
|
|
return (entities || [])
|
|
.map(E => {
|
|
if (before(A, E)) return E;
|
|
if (inside(A, E)) return;
|
|
if (after(A, E)) return { ...E, offset: E.offset + correction };
|
|
if (contains(A, E)) return { ...E, length: E.length + correction };
|
|
if (endsInside(A, E))
|
|
return { ...E, length: E.length - (ends(E) - starts(A)) };
|
|
if (startsInside(A, E)) {
|
|
const entityInside = ends(A) - starts(E);
|
|
return {
|
|
...E,
|
|
offset: E.offset + entityInside + correction,
|
|
length: E.length - entityInside,
|
|
};
|
|
}
|
|
|
|
throw new Error(
|
|
"Entity found in an unexpected condition. " +
|
|
"This is probably a bug in telegraf. " +
|
|
"You should report this to https://github.com/telegraf/telegraf/issues",
|
|
);
|
|
})
|
|
.filter((x): x is MessageEntity => Boolean(x));
|
|
}
|
|
|
|
if (typeof search === "string") {
|
|
const replace = FmtString.normalise(
|
|
typeof value === "function" ? value(...search) : value,
|
|
);
|
|
const offset = text.indexOf(search);
|
|
const length = search.length;
|
|
text = text.slice(0, offset) + replace.text + text.slice(offset + length);
|
|
const currentCorrection = replace.text.length - length;
|
|
entities = [
|
|
...fixEntities(offset, length, currentCorrection),
|
|
...(replace.entities || []).map(E => ({
|
|
...E,
|
|
offset: E.offset + offset,
|
|
})),
|
|
];
|
|
} else {
|
|
let index = 0; // context position in text string
|
|
let acc = ""; // incremental return value
|
|
let correction = 0;
|
|
|
|
let regexArray: RegExpExecArray | null;
|
|
while ((regexArray = search.exec(text))) {
|
|
const match = regexArray[0];
|
|
const offset = regexArray.index;
|
|
const length = match.length;
|
|
const replace = FmtString.normalise(
|
|
typeof value === "function" ? value(...regexArray) : value,
|
|
);
|
|
acc += text.slice(index, offset) + replace.text;
|
|
const currentCorrection = replace.text.length - length;
|
|
|
|
entities = [
|
|
...fixEntities(offset + correction, length, currentCorrection),
|
|
...(replace.entities || []).map(E => ({
|
|
...E,
|
|
offset: E.offset + offset + correction,
|
|
})),
|
|
];
|
|
|
|
correction += currentCorrection;
|
|
index = offset + length;
|
|
}
|
|
|
|
text = acc + text.slice(index);
|
|
}
|
|
|
|
return new FmtString(text, entities);
|
|
};
|