@fnlb-project/fnbr
Version:
A library to interact with Epic Games' Fortnite HTTP and XMPP services
219 lines • 7.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.chunk = exports.resolveAuthObject = exports.resolveAuthString = exports.parseStatKey = exports.createDefaultInputTypeStats = exports.parseM3U8File = exports.parseBlurlStream = exports.createPartyInvitation = exports.getRandomDefaultCharacter = exports.makeSnakeCase = exports.makeCamelCase = void 0;
const tslib_1 = require("tslib");
/* eslint-disable no-restricted-syntax */
const zlib_1 = tslib_1.__importDefault(require("zlib"));
const fs_1 = require("fs");
const defaultCharacters = [
'CID_A_272_Athena_Commando_F_Prime',
'CID_A_273_Athena_Commando_F_Prime_B',
'CID_A_274_Athena_Commando_F_Prime_C',
'CID_A_275_Athena_Commando_F_Prime_D',
'CID_A_276_Athena_Commando_F_Prime_E',
'CID_A_277_Athena_Commando_F_Prime_F',
'CID_A_278_Athena_Commando_F_Prime_G',
'CID_A_279_Athena_Commando_M_Prime',
'CID_A_280_Athena_Commando_M_Prime_B',
'CID_A_281_Athena_Commando_M_Prime_C',
'CID_A_282_Athena_Commando_M_Prime_D',
'CID_A_283_Athena_Commando_M_Prime_E',
'CID_A_284_Athena_Commando_M_Prime_F',
'CID_A_285_Athena_Commando_M_Prime_G',
];
const makeCamelCase = (obj) => {
const returnObj = {};
Object.keys(obj).forEach((k) => {
returnObj[k.split('_').map((s, i) => (i > 0 ? `${s.charAt(0).toUpperCase()}${s.slice(1)}` : s)).join('')] = obj[k];
});
return returnObj;
};
exports.makeCamelCase = makeCamelCase;
const makeSnakeCase = (obj) => {
const returnObj = {};
Object.keys(obj).forEach((k) => {
returnObj[k.replace(/[A-Z]/g, (l) => `_${l.toLowerCase()}`)] = obj[k];
});
return returnObj;
};
exports.makeSnakeCase = makeSnakeCase;
const getRandomDefaultCharacter = () => defaultCharacters[Math.floor(Math.random() * defaultCharacters.length)];
exports.getRandomDefaultCharacter = getRandomDefaultCharacter;
const createPartyInvitation = (clientUserId, pingerId, data) => {
const member = data.members.find((m) => m.account_id === pingerId);
const partyMeta = data.meta;
const memberMeta = member.meta;
const meta = {
'urn:epic:conn:type_s': 'game',
'urn:epic:cfg:build-id_s': partyMeta['urn:epic:cfg:build-id_s'],
'urn:epic:invite:platformdata_s': '',
};
if (memberMeta.Platform_j) {
meta['Platform_j'] = JSON.parse(memberMeta.Platform_j).Platform.platformStr;
}
if (memberMeta['urn:epic:member:dn_s'])
meta['urn:epic:member:dn_s'] = memberMeta['urn:epic:member:dn_s'];
return {
party_id: data.id,
sent_by: pingerId,
sent_to: clientUserId,
sent_at: data.sent,
updated_at: data.sent,
expires_at: data.expies_at,
status: 'SENT',
meta,
};
};
exports.createPartyInvitation = createPartyInvitation;
const parseBlurlStream = (stream) => new Promise((res) => {
zlib_1.default.inflate(stream.slice(8), (_err, buffer) => {
const data = JSON.parse(buffer.toString());
res(data);
});
});
exports.parseBlurlStream = parseBlurlStream;
const parseM3U8FileLine = (line) => {
const [key, value] = line.replace(/^#EXT-X-/, '').split(/:(.+)/);
let output;
if (value.includes(',')) {
output = {};
let store = '';
let isString = false;
for (const char of value.split('')) {
if (char === '"') {
isString = !isString;
}
else if (char === ',' && !isString) {
const [vK, vV] = store.split(/=(.+)/);
output[vK] = vV.replace(/(^"|"$)/g, '');
store = '';
}
else {
store += char;
}
}
}
else {
output = value;
}
return [key, output];
};
const parseM3U8File = (data) => {
const output = {
streams: [],
};
let streamInf;
for (const line of data.split(/\n/).slice(1)) {
if (line.startsWith('#EXT-X-STREAM-INF:')) {
[, streamInf] = parseM3U8FileLine(line);
}
else if (line.startsWith('#EXT-X-')) {
const [key, value] = parseM3U8FileLine(line);
output[key] = value;
}
else if (!line.startsWith('#') && streamInf && line.length > 0) {
output.streams.push({
data: streamInf,
url: line,
});
streamInf = undefined;
}
}
return output;
};
exports.parseM3U8File = parseM3U8File;
const defaultStats = {
score: 0,
scorePerMin: 0,
scorePerMatch: 0,
wins: 0,
top3: 0,
top5: 0,
top6: 0,
top10: 0,
top12: 0,
top25: 0,
kills: 0,
killsPerMin: 0,
killsPerMatch: 0,
deaths: 0,
kd: 0,
matches: 0,
winRate: 0,
minutesPlayed: 0,
playersOutlived: 0,
lastModified: undefined,
};
const createDefaultInputTypeStats = () => ({
overall: { ...defaultStats },
solo: { ...defaultStats },
duo: { ...defaultStats },
squad: { ...defaultStats },
ltm: { ...defaultStats },
});
exports.createDefaultInputTypeStats = createDefaultInputTypeStats;
const parseStatKey = (key, value) => {
switch (key) {
case 'lastmodified':
return ['lastModified', new Date(value * 1000)];
case 'placetop25':
return ['top25', value];
case 'placetop12':
return ['top12', value];
case 'placetop10':
return ['top10', value];
case 'placetop6':
return ['top6', value];
case 'placetop5':
return ['top5', value];
case 'placetop3':
return ['top3', value];
case 'placetop1':
return ['wins', value];
case 'playersoutlived':
return ['playersOutlived', value];
case 'minutesplayed':
return ['minutesPlayed', value];
case 'matchesplayed':
return ['matches', value];
default:
return [key, value];
}
};
exports.parseStatKey = parseStatKey;
const resolveAuthString = async (str) => {
switch (typeof str) {
case 'function':
return str();
case 'string':
if (str.length === 32 || str.startsWith('eg1')) {
return str;
}
return fs_1.promises.readFile(str, 'utf8');
default:
throw new TypeError(`The type "${typeof str}" does not resolve to a valid auth string`);
}
};
exports.resolveAuthString = resolveAuthString;
const resolveAuthObject = async (obj) => {
switch (typeof obj) {
case 'function':
return obj();
case 'string':
return JSON.parse(await fs_1.promises.readFile(obj, 'utf8'));
case 'object':
return obj;
default:
throw new TypeError(`The type "${typeof obj}" does not resolve to a valid auth object`);
}
};
exports.resolveAuthObject = resolveAuthObject;
const chunk = (array, maxSize) => {
const chunkedArray = [];
for (let i = 0; i < array.length; i += maxSize) {
chunkedArray.push(array.slice(i, i + maxSize));
}
return chunkedArray;
};
exports.chunk = chunk;
//# sourceMappingURL=Util.js.map