86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
|
import {
|
||
|
reader,
|
||
|
readerTaskEither as rte,
|
||
|
readonlyArray,
|
||
|
taskEither,
|
||
|
} from "fp-ts";
|
||
|
import { flow, pipe } from "fp-ts/lib/function.js";
|
||
|
|
||
|
// parseJsonCont :: string -> string -> TaskEither string string
|
||
|
const parseJsonCont = (attr) => (source) => {
|
||
|
try {
|
||
|
const data = JSON.parse(source)[attr];
|
||
|
if (!data) throw new Error(`Key '${attr}' doesn't exist`);
|
||
|
return taskEither.right(data);
|
||
|
} catch (e) {
|
||
|
return taskEither.left(`Invalid json data: ${e}`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const YANDEX_GPT_API_URL = "https://300.ya.ru/api/sharing-url";
|
||
|
|
||
|
// getYandexGptSharedUrl ::
|
||
|
// string ->
|
||
|
// ReaderTaskEither {yandexGptApiToken} string string
|
||
|
const getYandexGptSharedUrl = (articleUrl) =>
|
||
|
pipe(
|
||
|
reader.ask(),
|
||
|
reader.map(({ yandexGptApiToken }) =>
|
||
|
pipe(
|
||
|
taskEither.tryCatch(
|
||
|
() =>
|
||
|
fetch(YANDEX_GPT_API_URL, {
|
||
|
method: "POST",
|
||
|
headers: new Headers({
|
||
|
"Content-Type": "application/json",
|
||
|
"Authorization": `OAuth ${yandexGptApiToken}`,
|
||
|
}),
|
||
|
body: JSON.stringify({ article_url: articleUrl }),
|
||
|
}),
|
||
|
String,
|
||
|
),
|
||
|
/* TODO: fix to many requests error
|
||
|
{
|
||
|
ok: false,
|
||
|
error_code: 429,
|
||
|
description: 'Too Many Requests: retry after 5',
|
||
|
parameters: { retry_after: 5 }
|
||
|
}
|
||
|
*/
|
||
|
taskEither.flatMap((res) =>
|
||
|
taskEither.tryCatch(() => res.json(), String)
|
||
|
),
|
||
|
taskEither.flatMap((data) =>
|
||
|
data.status === "success" && data.sharing_url
|
||
|
? taskEither.right(data.sharing_url)
|
||
|
: taskEither.left(`Invalid response: ${JSON.stringify(data)}`)
|
||
|
),
|
||
|
)
|
||
|
),
|
||
|
);
|
||
|
|
||
|
// getYandexGptTesisesFromSharedUrl :: string -> TaskEither string[] string
|
||
|
const getYandexGptTesisesFromSharedUrl = (sharingUrl) =>
|
||
|
pipe(
|
||
|
taskEither.tryCatch(() => fetch(sharingUrl), String),
|
||
|
taskEither.flatMap((res) => taskEither.tryCatch(() => res.text(), String)),
|
||
|
taskEither.flatMap((html) =>
|
||
|
taskEither.fromNullable("Cannot find data in the shared url")(
|
||
|
/<script.+?type="application\/json".*?>([\s\S]+?)<\/script>/.exec(
|
||
|
html,
|
||
|
)[1],
|
||
|
)
|
||
|
),
|
||
|
taskEither.flatMap(parseJsonCont("body")),
|
||
|
taskEither.flatMap(parseJsonCont("thesis")),
|
||
|
taskEither.map(readonlyArray.map((t) => t.content)),
|
||
|
);
|
||
|
|
||
|
// describeArticle ::
|
||
|
// string ->
|
||
|
// ReaderTaskEither {yandexGptApiToken} string string
|
||
|
export const describeArticle = flow(
|
||
|
getYandexGptSharedUrl,
|
||
|
rte.flatMapTaskEither(getYandexGptTesisesFromSharedUrl),
|
||
|
);
|