instagram-private-api
Version:
Instagram private API wrapper for full access to instagram
172 lines • 7.68 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const crypto_1 = require("crypto");
const rxjs_1 = require("rxjs");
const attempt_1 = require("@lifeomic/attempt");
const request = require("request-promise");
const errors_1 = require("../errors");
const JSONbigInt = require("json-bigint");
const JSONbigString = JSONbigInt({ storeAsString: true });
const debug_1 = require("debug");
class Request {
constructor(client) {
this.client = client;
this.end$ = new rxjs_1.Subject();
this.error$ = new rxjs_1.Subject();
this.attemptOptions = {
maxAttempts: 1,
};
this.defaults = {};
}
static requestTransform(body, response, resolveWithFullResponse) {
try {
response.body = JSONbigString.parse(body);
}
catch (e) {
if (lodash_1.inRange(response.statusCode, 200, 299)) {
throw e;
}
}
return resolveWithFullResponse ? response : response.body;
}
async send(userOptions, onlyCheckHttpStatus) {
const options = lodash_1.defaultsDeep(userOptions, {
baseUrl: 'https://i.instagram.com/',
resolveWithFullResponse: true,
proxy: this.client.state.proxyUrl,
simple: false,
transform: Request.requestTransform,
jar: this.client.state.cookieJar,
strictSSL: false,
gzip: true,
headers: this.getDefaultHeaders(),
method: 'GET',
}, this.defaults);
Request.requestDebug(`Requesting ${options.method} ${options.url || options.uri || '[could not find url]'}`);
const response = await this.faultTolerantRequest(options);
this.updateState(response);
process.nextTick(() => this.end$.next());
if (response.body.status === 'ok' || (onlyCheckHttpStatus && response.statusCode === 200)) {
return response;
}
const error = this.handleResponseError(response);
process.nextTick(() => this.error$.next(error));
throw error;
}
updateState(response) {
const { 'x-ig-set-www-claim': wwwClaim, 'ig-set-authorization': auth, 'ig-set-password-encryption-key-id': pwKeyId, 'ig-set-password-encryption-pub-key': pwPubKey, } = response.headers;
if (typeof wwwClaim === 'string') {
this.client.state.igWWWClaim = wwwClaim;
}
if (typeof auth === 'string' && !auth.endsWith(':')) {
this.client.state.authorization = auth;
}
if (typeof pwKeyId === 'string') {
this.client.state.passwordEncryptionKeyId = pwKeyId;
}
if (typeof pwPubKey === 'string') {
this.client.state.passwordEncryptionPubKey = pwPubKey;
}
}
signature(data) {
return crypto_1.createHmac('sha256', this.client.state.signatureKey)
.update(data)
.digest('hex');
}
sign(payload) {
const json = typeof payload === 'object' ? JSON.stringify(payload) : payload;
const signature = this.signature(json);
return {
ig_sig_key_version: this.client.state.signatureVersion,
signed_body: `${signature}.${json}`,
};
}
userBreadcrumb(size) {
const term = lodash_1.random(2, 3) * 1000 + size + lodash_1.random(15, 20) * 1000;
const textChangeEventCount = Math.round(size / lodash_1.random(2, 3)) || 1;
const data = `${size} ${term} ${textChangeEventCount} ${Date.now()}`;
const signature = Buffer.from(crypto_1.createHmac('sha256', this.client.state.userBreadcrumbKey)
.update(data)
.digest('hex')).toString('base64');
const body = Buffer.from(data).toString('base64');
return `${signature}\n${body}\n`;
}
handleResponseError(response) {
Request.requestDebug(`Request ${response.request.method} ${response.request.uri.path} failed: ${typeof response.body === 'object' ? JSON.stringify(response.body) : response.body}`);
const json = response.body;
if (json.spam) {
return new errors_1.IgActionSpamError(response);
}
if (response.statusCode === 404) {
return new errors_1.IgNotFoundError(response);
}
if (typeof json.message === 'string') {
if (json.message === 'challenge_required') {
this.client.state.checkpoint = json;
return new errors_1.IgCheckpointError(response);
}
if (json.message === 'user_has_logged_out') {
return new errors_1.IgUserHasLoggedOutError(response);
}
if (json.message === 'login_required') {
return new errors_1.IgLoginRequiredError(response);
}
if (json.message.toLowerCase() === 'not authorized to view user') {
return new errors_1.IgPrivateUserError(response);
}
}
if (json.error_type === 'sentry_block') {
return new errors_1.IgSentryBlockError(response);
}
if (json.error_type === 'inactive user') {
return new errors_1.IgInactiveUserError(response);
}
return new errors_1.IgResponseError(response);
}
async faultTolerantRequest(options) {
try {
return await attempt_1.retry(async () => request(options), this.attemptOptions);
}
catch (err) {
throw new errors_1.IgNetworkError(err);
}
}
getDefaultHeaders() {
var _a;
return {
'User-Agent': this.client.state.appUserAgent,
'X-Ads-Opt-Out': this.client.state.adsOptOut ? '1' : '0',
'X-CM-Bandwidth-KBPS': '-1.000',
'X-CM-Latency': '-1.000',
'X-IG-App-Locale': this.client.state.language,
'X-IG-Device-Locale': this.client.state.language,
'X-Pigeon-Session-Id': this.client.state.pigeonSessionId,
'X-Pigeon-Rawclienttime': (Date.now() / 1000).toFixed(3),
'X-IG-Connection-Speed': `${lodash_1.random(1000, 3700)}kbps`,
'X-IG-Bandwidth-Speed-KBPS': '-1.000',
'X-IG-Bandwidth-TotalBytes-B': '0',
'X-IG-Bandwidth-TotalTime-MS': '0',
'X-IG-EU-DC-ENABLED': typeof this.client.state.euDCEnabled === 'undefined' ? void 0 : this.client.state.euDCEnabled.toString(),
'X-IG-Extended-CDN-Thumbnail-Cache-Busting-Value': this.client.state.thumbnailCacheBustingValue.toString(),
'X-Bloks-Version-Id': this.client.state.bloksVersionId,
'X-MID': (_a = this.client.state.extractCookie('mid')) === null || _a === void 0 ? void 0 : _a.value,
'X-IG-WWW-Claim': this.client.state.igWWWClaim || '0',
'X-Bloks-Is-Layout-RTL': this.client.state.isLayoutRTL.toString(),
'X-IG-Connection-Type': this.client.state.connectionTypeHeader,
'X-IG-Capabilities': this.client.state.capabilitiesHeader,
'X-IG-App-ID': this.client.state.fbAnalyticsApplicationId,
'X-IG-Device-ID': this.client.state.uuid,
'X-IG-Android-ID': this.client.state.deviceId,
'Accept-Language': this.client.state.language.replace('_', '-'),
'X-FB-HTTP-Engine': 'Liger',
Authorization: this.client.state.authorization,
Host: 'i.instagram.com',
'Accept-Encoding': 'gzip',
Connection: 'close',
};
}
}
exports.Request = Request;
Request.requestDebug = debug_1.default('ig:request');
//# sourceMappingURL=request.js.map