35 lines
1 KiB
JavaScript
35 lines
1 KiB
JavaScript
import { number, option, ord, readonlyArray } from "fp-ts";
|
|
import { flow, pipe } from "fp-ts/lib/function.js";
|
|
|
|
const RE_URL =
|
|
/(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/;
|
|
|
|
// getMessageUrl :: Message -> Option<string>
|
|
const getMessageUrl = (msg) => option.fromNullable(RE_URL.exec(msg.text)?.[0]);
|
|
|
|
// getMessageEntities :: Message -> ReadonlyArray<MessageEntity>
|
|
const getMessageEntities = (msg) => msg.entities ?? readonlyArray.empty;
|
|
|
|
// isTextLink :: MessageEntity -> boolean
|
|
const isTextLink = (msgEntity) => msgEntity.type === "text_link";
|
|
|
|
const ordStringLength = pipe(
|
|
number.Ord,
|
|
ord.contramap((s) => s.length),
|
|
);
|
|
|
|
// getTextLink :: Message -> Option<string>
|
|
const getTextLink = flow(
|
|
getMessageEntities,
|
|
readonlyArray.filterMap(
|
|
flow(option.fromPredicate(isTextLink), option.map((link) => link.url)),
|
|
),
|
|
readonlyArray.sort(ordStringLength),
|
|
readonlyArray.last,
|
|
);
|
|
|
|
export const extractMessageLink = (msg) =>
|
|
pipe(
|
|
getTextLink(msg),
|
|
option.orElse(() => getMessageUrl(msg)),
|
|
);
|