Update checkmate/checkmate.js

This commit is contained in:
aka paul 2025-12-28 13:03:36 +00:00
parent 9fec9d8fff
commit 5fdb173990

View file

@ -317,59 +317,58 @@ async function extractEpisodes(url) {
async function extractStreamUrl(ID) {
try {
let subtitle = null;
if (ID.includes('movie')) {
const tmdbID = ID.split('/')[2];
const subResponse = await fetchv2(`https://sub.wyzie.ru/search?id=${tmdbID}&format=srt`);
const subtitles = await subResponse.json();
subtitle = subtitles.find(sub => sub.language.toLowerCase() === 'en')?.url || null;
} else if (ID.includes('tv')) {
const parts = ID.split('/');
const tmdbID = parts[2];
const seasonNumber = parts[3];
const episodeNumber = parts[4];
const subResponse = await fetchv2(`https://sub.wyzie.ru/search?id=${tmdbID}&format=srt&season=${seasonNumber}&episode=${episodeNumber}`);
const subtitles = await subResponse.json();
subtitle = subtitles.find(sub => sub.language.toLowerCase() === 'en')?.url || null;
}
const alphaPromise = alpha(ID).then(result => ({ source: 'alpha', data: JSON.parse(result) })).catch(err => ({ source: 'alpha', error: err }));
const betaPromise = beta(ID).then(result => ({ source: 'beta', data: JSON.parse(result) })).catch(err => ({ source: 'beta', error: err }));
const gammaPromise = gamma(ID).then(result => ({ source: 'gamma', data: JSON.parse(result) })).catch(err => ({ source: 'gamma', error: err }));
const deltaPromise = delta(ID).then(result => ({ source: 'delta', data: JSON.parse(result) })).catch(err => ({ source: 'delta', error: err }));
const epsilonPromise = epsilon(ID).then(result => ({ source: 'epsilon', data: JSON.parse(result) })).catch(err => ({ source: 'epsilon', error: err }));
const racePromise = Promise.race([alphaPromise, gammaPromise, deltaPromise]);
const [fastestResult, betaResult, alphaResult] = await Promise.all([racePromise, betaPromise, alphaPromise]);
const [fastestResult, alphaResult] = await Promise.all([racePromise, alphaPromise]);
let epsilonResult = null;
const alphaHas4K = alphaResult && !alphaResult.error && alphaResult.data && alphaResult.data.streams &&
alphaResult.data.streams.some((_, i, arr) => i % 2 === 0 && arr[i] && arr[i].toLowerCase().includes('4k'));
if (!alphaHas4K) {
epsilonResult = await epsilonPromise;
}
const resultStreams = [];
let subtitle = null;
if (fastestResult && !fastestResult.error && fastestResult.data && fastestResult.data.streams && fastestResult.data.streams.length > 0) {
const streamUrl = fastestResult.data.streams.length >= 2 ? fastestResult.data.streams[1] : fastestResult.data.streams[0];
let streamUrl;
let headers = {};
if (typeof fastestResult.data.streams[0] === 'string') {
streamUrl = fastestResult.data.streams.length >= 2 ? fastestResult.data.streams[1] : fastestResult.data.streams[0];
} else {
streamUrl = fastestResult.data.streams[0].streamUrl;
headers = fastestResult.data.streams[0].headers || {};
}
resultStreams.push({
title: "Default (1080p)",
streamUrl: streamUrl,
headers: fastestResult.data.referer ? { "Referer": fastestResult.data.referer } : {}
headers: { ...headers, ...(fastestResult.data.referer ? { "Referer": fastestResult.data.referer } : {}) }
});
subtitle = fastestResult.data.subtitles || null;
} else {
if (betaResult && !betaResult.error && betaResult.data && betaResult.data.streams && betaResult.data.streams.length > 0) {
const streamUrl = betaResult.data.streams.length >= 2 ? betaResult.data.streams[1] : betaResult.data.streams[0];
resultStreams.push({
title: "Default (1080p)",
streamUrl: streamUrl,
headers: betaResult.data.referer ? { "Referer": betaResult.data.referer } : {}
});
subtitle = betaResult.data.subtitles || null;
}
}
if (alphaResult && !alphaResult.error && alphaResult.data && alphaResult.data.streams) {
const streams = alphaResult.data.streams;
let fourKUrl = null;
let fourKHeaders = {};
for (let i = 0; i < streams.length; i += 2) {
if (streams[i] && streams[i].toLowerCase().includes('4k') && streams[i + 1]) {
fourKUrl = streams[i + 1];
for (let stream of streams) {
if (stream.title && stream.title.toLowerCase().includes('4k') && stream.streamUrl) {
fourKUrl = stream.streamUrl;
fourKHeaders = stream.headers || {};
break;
}
}
@ -378,36 +377,10 @@ async function extractStreamUrl(ID) {
resultStreams.push({
title: "4K",
streamUrl: fourKUrl,
headers: {
"Origin": "https://player.videasy.net",
"Referer": "https://player.videasy.net/"
}
headers: fourKHeaders
});
} else {
console.log('Alpha did not return a 4K stream, checking epsilon as fallback');
if (epsilonResult && !epsilonResult.error && epsilonResult.data && epsilonResult.data.streams) {
const epsilonStreams = epsilonResult.data.streams;
let epsilonFourKUrl = null;
for (const stream of epsilonStreams) {
if (stream.title && stream.title.includes('4K') && stream.streamUrl) {
epsilonFourKUrl = stream;
break;
}
}
if (epsilonFourKUrl) {
console.log('Using epsilon as 4K fallback provider');
resultStreams.push({
title: "4K",
streamUrl: epsilonFourKUrl.streamUrl,
headers: epsilonFourKUrl.headers || { "Referer": "https://mapple.uk/", "Origin": "https://mapple.uk" }
});
} else {
console.log('Epsilon fallback also did not return a 4K stream');
}
}
console.log('Alpha did not return a 4K stream');
}
}
console.log(JSON.stringify({
@ -457,7 +430,7 @@ async function alpha(ID) {
const imdbId = cinebyData.external_ids?.imdb_id || '';
const tmdbId = cinebyData.id;
const fullUrl = `https://api.videasy.net/myflixerzupcloud/sources-with-title?title=${title}&mediaType=movie&year=${year}&episodeId=1&seasonId=1&tmdbId=${tmdbId}&imdbId=${imdbId}`;
const fullUrl = `https://api.videasy.net/cdn/sources-with-title?title=${title}&mediaType=movie&year=${year}&episodeId=1&seasonId=1&tmdbId=${tmdbId}&imdbId=${imdbId}`;
console.log('Full URL:' + fullUrl);
@ -472,9 +445,9 @@ async function alpha(ID) {
const postData = JSON.stringify({
text: encrypted,
id: tmdbID
id: tmdbID.split('-')[0]
});
console.log('Post Data:' + postData);
const decryptedResponse = await fetchv2("https://enc-dec.app/api/dec-videasy", headers, "POST", postData);
const decryptedData = await decryptedResponse.json();
console.log('Decrypted Data:' + JSON.stringify(decryptedData));
@ -485,15 +458,22 @@ async function alpha(ID) {
const nonHDRSources = sources.filter(s => !s.quality.includes("HDR"));
const streams = nonHDRSources.flatMap(src => [src.quality, src.url]);
const streamObjects = nonHDRSources.map(src => ({
title: src.quality,
streamUrl: src.url,
headers: {
"Origin": "https://player.videasy.net",
"Referer": "https://player.videasy.net/"
}
}));
const englishSubtitle = subtitles.find(
sub => sub.language.toLowerCase().includes('english')
)?.url || null;
return JSON.stringify({
streams,
subtitles: englishSubtitle
streams: streamObjects,
subtitle: englishSubtitle
});
} else if (ID.includes('tv')) {
const parts = ID.split('/');
@ -501,7 +481,7 @@ async function alpha(ID) {
const seasonNumber = parts[3];
const episodeNumber = parts[4];
const cinebyResponse = await soraFetch(`hhttps://db.videasy.net/3/tv/${tmdbID}?append_to_response=external_ids&language=en&api_key=ad301b7cc82ffe19273e55e4d4206885`);
const cinebyResponse = await soraFetch(`https://db.videasy.net/3/tv/${tmdbID}?append_to_response=external_ids&language=en&api_key=ad301b7cc82ffe19273e55e4d4206885`);
const cinebyData = await cinebyResponse.json();
const title = encodeURIComponent(cinebyData.name);
@ -509,7 +489,7 @@ async function alpha(ID) {
const imdbId = cinebyData.external_ids?.imdb_id || '';
const tmdbId = cinebyData.id;
const fullUrl = `https://api.videasy.net/myflixerzupcloud/sources-with-title?title==${title}&mediaType=tv&year=${year}&episodeId=${episodeNumber}&seasonId=${seasonNumber}&tmdbId=${tmdbId}&imdbId=${imdbId}`;
const fullUrl = `https://api.videasy.net/cdn/sources-with-title?title=${title}&mediaType=tv&year=${year}&episodeId=${episodeNumber}&seasonId=${seasonNumber}&tmdbId=${tmdbId}&imdbId=${imdbId}`;
console.log('Full URL:' + fullUrl);
@ -524,7 +504,7 @@ async function alpha(ID) {
const postData = JSON.stringify({
text: encrypted,
id: tmdbID
id: tmdbID.split('-')[0]
});
const decryptedResponse = await fetchv2("https://enc-dec.app/api/dec-videasy", headers, "POST", postData);
@ -537,101 +517,26 @@ async function alpha(ID) {
const nonHDRSources = sources.filter(s => !s.quality.includes("HDR"));
const streams = nonHDRSources.flatMap(src => [src.quality, src.url]);
const streamObjects = nonHDRSources.map(src => ({
title: src.quality,
streamUrl: src.url,
headers: {
"Origin": "https://player.videasy.net",
"Referer": "https://player.videasy.net/"
}
}));
const englishSubtitle = subtitles.find(
sub => sub.language.toLowerCase().includes('english')
)?.url || null;
return JSON.stringify({
streams,
subtitles: englishSubtitle
streams: streamObjects,
subtitle: englishSubtitle
});
}
}
async function beta(ID) {
if (ID.includes('movie')) {
const tmdbID = ID.replace('/movie/', '');
const headersOne = {
"Content-Type": "application/json",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI2NTQ0MWU0MTg4NjhhMWI0NDZiM2I0Mzg1MmE4OWQ2NyIsIm5iZiI6MTYzMDg4NDI0My40NzMsInN1YiI6IjYxMzU1MTkzZmQ0YTk2MDA0NDVkMTJjNiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.Hm0W-hUx-7ph-ASvk2TpMxZbMtwVa5DEXWcgNgcqXJM",
"Referer": "https://player.smashystream.com/",
"Origin": "https://player.smashystream.com",
"X-Requested-With": "XMLHttpRequest",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/"
};
const tmdbResponse = await fetchv2(`https://post-eosin.vercel.app/api/proxy?url=${encodeURIComponent(`https://api.themoviedb.org/3/movie/${tmdbID}?append_to_response=external_ids`)}&simple=true`, headersOne);
const tmdbData = await tmdbResponse.json();
const imdbID = tmdbData.imdb_id;
const streamResponse = await ilovefeet(imdbID, false, null, null, 'm3u8');
const streams = [];
if (streamResponse && streamResponse.defaultUrl) {
streams.push("1080p", streamResponse.defaultUrl);
}
if (streamResponse && streamResponse.vFastUrl) {
const fourKResult = await ilovearmpits(streamResponse.vFastUrl);
if (fourKResult.available && fourKResult.url) {
streams.push("4K", fourKResult.url);
}
}
const final = {
streams,
subtitles: streamResponse.subtitles || "None",
referer: "https://vidfast.pro/"
};
console.log(JSON.stringify(final));
return JSON.stringify(final);
} else if (ID.includes('tv')) {
const parts = ID.split('/');
const tmdbID = parts[2];
const seasonNumber = parts[3];
const episodeNumber = parts[4];
console.log(`TMDB ID: ${tmdbID}, Season: ${seasonNumber}, Episode: ${episodeNumber}`);
const headersOne = {
"Content-Type": "application/json",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI2NTQ0MWU0MTg4NjhhMWI0NDZiM2I0Mzg1MmE4OWQ2NyIsIm5iZiI6MTYzMDg4NDI0My40NzMsInN1YiI6IjYxMzU1MTkzZmQ0YTk2MDA0NDVkMTJjNiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.Hm0W-hUx-7ph-ASvk2TpMxZbMtwVa5DEXWcgNgcqXJM",
"Referer": "https://player.smashystream.com/",
"Origin": "https://player.smashystream.com",
"X-Requested-With": "XMLHttpRequest",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/"
};
const tmdbResponse = await fetchv2(`https://post-eosin.vercel.app/api/proxy?url=${encodeURIComponent(`https://api.themoviedb.org/3/tv/${tmdbID}?append_to_response=external_ids`)}&simple=true`, headersOne);
const tmdbData = await tmdbResponse.json();
const imdbID = tmdbData.external_ids.imdb_id;
const streamResponse = await ilovefeet(imdbID, true, seasonNumber, episodeNumber, 'm3u8');
const streams = [];
if (streamResponse && streamResponse.defaultUrl) {
streams.push("1080p", streamResponse.defaultUrl);
}
if (streamResponse && streamResponse.vFastUrl) {
const fourKResult = await ilovearmpits(streamResponse.vFastUrl);
if (fourKResult.available && fourKResult.url) {
streams.push("4K", fourKResult.url);
}
}
const final = {
streams,
subtitles: streamResponse.subtitles || "None",
referer: "https://vidfast.pro/"
};
console.log(JSON.stringify(final));
return JSON.stringify(final);
}
}
async function gamma(ID) {
if (ID.includes('movie')) {
const parts = ID.split('/');
@ -690,9 +595,9 @@ async function delta(ID) {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"X-Api-Key": "24ef089ebcab51d107a4e4709e87861ef609bace89ac23af13235f6ea743488f"
};
const response = await fetchv2(`https://post-eosin.vercel.app/api/proxy?url=${encodeURIComponent(`https://themoviedb.hexa.watch/api/tmdb/movie/${ID.split('/')[2]}/images`)}&simple=true`, headersOne);
const response = await fetchv2(`https://themoviedb.hexa.su/api/tmdb/movie/${ID.split('/')[2]}/images`, headersOne);
const data = await response.text();
console.log('Encrypted Data:' + data);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
@ -725,8 +630,7 @@ async function delta(ID) {
return JSON.stringify({
streams,
subtitles: englishSubtitle,
referer: "https://hexa.watch/"
subtitles: englishSubtitle
});
} else if (ID.includes('tv')) {
const parts = ID.split('/');
@ -737,7 +641,7 @@ async function delta(ID) {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"X-Api-Key": "24ef089ebcab51d107a4e4709e87861ef609bace89ac23af13235f6ea743488f"
};
const response = await fetchv2(`https://post-eosin.vercel.app/api/proxy?url=${encodeURIComponent(`https://themoviedb.hexa.watch/api/tmdb/tv/${tmdbID}/season/${seasonNumber}/episode/${episodeNumber}/images`)}&simple=true`, headersOne);
const response = await fetchv2(`https://themoviedb.hexa.su/api/tmdb/tv/${tmdbID}/season/${seasonNumber}/episode/${episodeNumber}/images`, headersOne);
const data = await response.text();
const headers = {
@ -772,208 +676,11 @@ async function delta(ID) {
return JSON.stringify({
streams,
subtitles: null,
referer: "https://hexa.watch/"
subtitles: englishSubtitle
});
}
}
async function epsilon(ID) {
const actionIdentifier = await ilovethighs("https://mapple.uk/watch/movie/1061474-superman");
console.log("Action Identifier: " + actionIdentifier);
const sessionResponse = await soraFetch("https://enc-dec.app/api/enc-mapple");
const sessionData = await sessionResponse.json();
console.log("Session Data: " + JSON.stringify(sessionData));
const sessionID = sessionData.result.sessionId || "N/A";
console.log("ID: " + ID);
if (ID.startsWith('/movie/') || ID.startsWith('movie/')) {
const match = ID.match(/movie\/(\d+)/);
const tmdbID = match ? match[1] : '';
console.log("Extracted TMDB ID: " + tmdbID);
const headers = {
"Content-Type": "text/plain",
"next-action": actionIdentifier
};
const postData = `[{"mediaId":${tmdbID},"mediaType":"movie","tv_slug":"","source":"mapple","useFallbackVideo":false,"sessionId":"${sessionID}"}]`;
const response = await fetchv2("https://mapple.uk/watch/"+ ID, headers, "POST", postData);
const data = await response.text();
console.log("Stream data: " + data);
const lines = data.split('\n');
let streamData = null;
for (const line of lines) {
if (line.includes('"success":true')) {
streamData = JSON.parse(line.substring(line.indexOf('{')));
break;
}
}
if (streamData && streamData.data && streamData.data.stream_url) {
const m3u8Response = await soraFetch(streamData.data.stream_url, {
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
});
const m3u8Text = await m3u8Response.text();
console.log("M3U8 Playlist: " + m3u8Text);
const streams = [];
const lines = m3u8Text.split('\n');
const resolutionNames = {
"3840x2160": "4K",
"1920x1080": "1080p",
"1280x720": "720p",
"640x360": "360p"
};
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('#EXT-X-STREAM-INF')) {
const resolutionMatch = lines[i].match(/RESOLUTION=(\d+x\d+)/);
const streamUrl = lines[i + 1];
if (resolutionMatch && streamUrl && streamUrl.trim()) {
const resolution = resolutionMatch[1];
const friendlyName = resolutionNames[resolution] || resolution;
streams.push({
title: friendlyName,
streamUrl: streamUrl.trim(),
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
});
}
}
}
let englishSubtitleUrl = "";
try {
const subResponse = await soraFetch(`https://mapple.uk/api/subtitles?id=${tmdbID}&mediaType=movie`);
const subData = await subResponse.json();
const englishSub = subData.find(sub => sub.language === "en");
if (englishSub) {
englishSubtitleUrl = englishSub.url;
}
} catch (e) {
englishSubtitleUrl = "";
}
console.log("English Subtitle URL: " + englishSubtitleUrl);
console.log("Extracted streams: " + JSON.stringify(streams));
return JSON.stringify({
streams: streams.length > 0 ? streams : [
{
title: "Mapple Server",
streamUrl: streamData.data.stream_url,
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
}
],
subtitle: englishSubtitleUrl || ""
});
} else {
throw new Error("Failed to extract stream URL");
}
} else if (ID.startsWith('/tv/') || ID.startsWith('tv/')) {
const match = ID.match(/tv\/(\d+)-(\d+)-(\d+)/);
if (!match) throw new Error("Invalid TV URL format");
const tmdbID = match[1];
const seasonNumber = match[2];
const episodeNumber = match[3];
const headers = {
"Content-Type": "text/plain",
"next-action": actionIdentifier
};
const postData = `[{"mediaId":${tmdbID},"mediaType":"tv","tv_slug":"${seasonNumber}-${episodeNumber}","source":"mapple","useFallbackVideo":false,"sessionId":"${sessionID}"}]`;
const response = await fetchv2("https://mapple.uk/watch"+ ID, headers, "POST", postData);
const data = await response.text();
console.log("Stream data: " + data);
const lines = data.split('\n');
let streamData = null;
for (const line of lines) {
if (line.includes('"success":true')) {
streamData = JSON.parse(line.substring(line.indexOf('{')));
break;
}
}
if (streamData && streamData.data && streamData.data.stream_url) {
const m3u8Response = await soraFetch(streamData.data.stream_url, {
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
});
const m3u8Text = await m3u8Response.text();
console.log("M3U8 Playlist: " + m3u8Text);
const streams = [];
const lines = m3u8Text.split('\n');
const resolutionNames = {
"3840x2160": "4K",
"1920x1080": "1080p",
"1280x720": "720p",
"640x360": "360p"
};
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('#EXT-X-STREAM-INF')) {
const resolutionMatch = lines[i].match(/RESOLUTION=(\d+x\d+)/);
const streamUrl = lines[i + 1];
if (resolutionMatch && streamUrl && streamUrl.trim()) {
const resolution = resolutionMatch[1];
const friendlyName = resolutionNames[resolution] || resolution;
streams.push({
title: friendlyName,
streamUrl: streamUrl.trim(),
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
});
}
}
}
let englishSubtitleUrl = "";
try {
const subResponse = await soraFetch(`https://mapple.uk/api/subtitles?id=${tmdbID}&mediaType=tv&season=${seasonNumber}&episode=${episodeNumber}`);
const subData = await subResponse.json();
const englishSub = subData.find(sub => sub.language === "en");
if (englishSub) {
englishSubtitleUrl = englishSub.url;
}
} catch (e) {
englishSubtitleUrl = "";
}
console.log("English Subtitle URL: " + englishSubtitleUrl);
console.log("Extracted streams: " + JSON.stringify(streams));
return JSON.stringify({
streams: streams.length > 0 ? streams : [
{
title: "Mapple Server",
streamUrl: streamData.data.stream_url,
headers: {
"referer": "https://mapple.uk/",
"origin": "https://mapple.uk"
}
}
],
subtitle: englishSubtitleUrl || ""
});
} else {
throw new Error("Failed to extract stream URL");
}
}
}
async function soraFetch(url, options = { headers: {}, method: 'GET', body: null, encoding: 'utf-8' }) {
try {
return await fetchv2(
@ -1362,50 +1069,7 @@ async function ilovefeet(imdbId, isSeries = false, season = null, episode = null
};
}
async function ilovethighs(watchUrl) {
const htmlResponse = await soraFetch(watchUrl);
const htmlText = await htmlResponse.text();
const layoutMatch = htmlText.match(/<script[^>]*src="([^"]*app\/watch\/movie\/[^"]*layout-[^"]*\.js)"[^>]*><\/script><link rel="preload"/);
if (!layoutMatch || !layoutMatch[1]) {
throw new Error("error 1");
}
const beforeLayoutMatch = htmlText.match(/<script[^>]*src="([^"]*\.js)"[^>]*><\/script><script[^>]*src="[^"]*app\/watch\/(movie|tv)\/[^"]*layout-[^"]*\.js"/);
if (!beforeLayoutMatch || !beforeLayoutMatch[1]) {
throw new Error("error 2");
}
let targetUrl = beforeLayoutMatch[1];
if (targetUrl.startsWith('/_next/')) {
targetUrl = 'https://mapple.uk' + targetUrl;
} else if (!targetUrl.startsWith('http')) {
targetUrl = 'https://mapple.uk/' + targetUrl;
}
try {
const response = await soraFetch(targetUrl);
const text = await response.text();
let actionMatch = text.match(/createServerReference\)\("([a-f0-9]{40,})"[^"]*"getStreamUrl/);
if (!actionMatch) {
actionMatch = text.match(/createServerReference\)\("([a-f0-9]{40,})"/);
}
if (!actionMatch) {
actionMatch = text.match(/"([a-f0-9]{40,})"[^"]*"getStreamUrl/);
}
if (actionMatch && actionMatch[1]) {
return actionMatch[1];
}
} catch (e) {
throw new Error("error 3: " + e);
}
throw new Error("error 4");
}
function wordArrayToUint8Array(wordArray) {
const words = wordArray.words;