From 2ce0686425cf6690eaf70b9acc91e3757b9a905f Mon Sep 17 00:00:00 2001 From: Gimenz Date: Fri, 14 Oct 2022 21:47:14 +0700 Subject: [PATCH 1/9] fix: uploadPhoto --- README.md | 10 +++++- package-lock.json | 4 +-- src/config/index.ts | 12 ++----- src/helper/RequestHandler.ts | 62 --------------------------------- src/index.ts | 67 +++++++++++++++++------------------- src/utils/index.ts | 14 ++++++-- 6 files changed, 58 insertions(+), 111 deletions(-) delete mode 100644 src/helper/RequestHandler.ts diff --git a/README.md b/README.md index 34dff46..c238998 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,15 @@ more example you can check at example.ts file ```js let { igApi } = require("insta-fetcher"); -let ig = new igApi("your cookie"); + +// some example with proxy, but i never test it +let ig = new igApi("your cookie", false, { + proxy: { + host: 'proxy-url', + port: 80, + auth: {username: 'my-user', password: 'my-password'} + } +}); // Public post ig.fetchPost("https://www.instagram.com/reel/CXhW_4sp32Z/").then((res) => { diff --git a/package-lock.json b/package-lock.json index 1f1ec31..c1e71e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "insta-fetcher", - "version": "1.3.22", + "version": "1.3.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "insta-fetcher", - "version": "1.3.22", + "version": "1.3.23", "license": "MIT", "dependencies": { "axios": "^0.27.2", diff --git a/src/config/index.ts b/src/config/index.ts index cdf1b58..28f271b 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,20 +2,14 @@ export const config = { /** Instagram Base URL */ instagram_base_url: 'https://www.instagram.com', instagram_base_z4: 'https://z-p4.www.instagram.com', - /** Instagram Api Stories */ - instagram_stories_url: 'https://i.instagram.com/api/v1/feed/user', - /** Instagram Api Fetch User Data */ - instagram_user_url: 'https://i.instagram.com/api/v1/users', - /** Instagram Api Fetch media info by media_id */ - instagram_media_info_url: 'https://i.instagram.com/api/v1/media/{mediaId}/info/', + /** Instagram Api v1 */ + instagram_api_v1: 'https://i.instagram.com/api/v1', /** Instagram API Search User */ instagram_search_url: 'https://www.instagram.com/web/search/topsearch/?query=', - /** Instagram GraphQL query */ - instagram_graphql: 'https://www.instagram.com/graphql/query/', /** Android User-Agent */ android: 'Instagram 177.0.0.30.119 Android (18/4.3; 320dpi; 720x1280; Xiaomi; HM 1SW; armani; qcom; en_US)', /** Desktop User-Agent */ desktop: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36', /** iPhone User-Agent */ iPhone: 'Instagram 123.0.0.21.114 (iPhone; CPU iPhone OS 11_4 like Mac OS X; en_US; en-US; scale=2.00; 750x1334) AppleWebKit/605.1.15' -}; +} \ No newline at end of file diff --git a/src/helper/RequestHandler.ts b/src/helper/RequestHandler.ts deleted file mode 100644 index 9e2758b..0000000 --- a/src/helper/RequestHandler.ts +++ /dev/null @@ -1,62 +0,0 @@ -import axios from 'axios'; -import { config } from '../config'; -import { CookieHandler } from './CookieHandler'; -let c = new CookieHandler(); -let session_id = c.get() - -const buildHeaders = (agent: string = config.android) => { - return { - 'cache-control': 'no-cache', - 'user-agent': agent, - 'cookie': `sessionid=${session_id};`, - 'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,ru;q=0.5', - 'Accept-Encoding': 'gzip, deflate, br', - 'pragma': 'no-cache', - 'sec-fetch-mode': 'navigate', - 'sec-fetch-site': 'none', - 'sec-fetch-user': '?1', - 'upgrade-insecure-requests': '1', - }; -} - -/** Fetches Using Instagram Base Url with Desktop user-agent */ -export const IGFetchDesktop = axios.create({ - baseURL: config.instagram_base_url, - headers: buildHeaders(config.desktop) -}); - -/** Fetches Using Instagram Base Url with Android user-agent */ -export const IGFetchAndroid = axios.create({ - baseURL: config.instagram_base_url, - headers: buildHeaders(config.android) -}); - -/** Fetches Using Instagram Base Url with iPhone user-agent */ -export const IGFetchiPhone = axios.create({ - baseURL: config.instagram_base_url, - headers: buildHeaders(config.iPhone) -}); - -/** Fetches Instagram User */ -export const IGUser = axios.create({ - baseURL: config.instagram_user_url, - headers: buildHeaders(), -}); - -/** Fetches Instagram Stories */ -export const IGStories = axios.create({ - baseURL: config.instagram_stories_url, - headers: buildHeaders(config.iPhone), -}); - -/** Fetches Instagram Highlights */ -export const IGHighlight = axios.create({ - baseURL: config.instagram_graphql, - headers: buildHeaders(config.iPhone) -}) - -/** Fetches Instagram Search Users | Places | Hashtags*/ -export const IGSearch = axios.create({ - baseURL: config.instagram_search_url, - headers: buildHeaders() -}); diff --git a/src/index.ts b/src/index.ts index eb1ad27..cd9c01d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ import fs from 'fs' import FormData from 'form-data'; import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; -import { bufferToStream, getPostType, randInt, shortcodeFormatter } from './utils/index'; +import { bufferToStream, getPostType, parseCookie, randInt, shortcodeFormatter } from './utils/index'; import { CookieHandler } from './helper/CookieHandler'; import { username, url, IgCookie, ProductType, MediaType, IChangedProfilePicture } from './types'; import { IGUserMetadata, UserGraphQL } from './types/UserMetadata'; @@ -31,12 +31,14 @@ export class igApi { * Recommended to set cookie for most all IG Request * @param IgCookie cookie you can get it by using getSessionId function, see README.md or example file * @param storeCookie + * @param AxiosOpts */ - constructor(private IgCookie: IgCookie = '', public storeCookie: boolean = true) { + constructor(private IgCookie: IgCookie = '', public storeCookie: boolean = true, public AxiosOpts: AxiosRequestConfig = {}) { this.IgCookie = IgCookie; if (this.storeCookie) { this.setCookie(this.IgCookie); } + this.AxiosOpts = AxiosOpts; } private cookie = new CookieHandler(this.IgCookie) private accountUserId = this.IgCookie.match(/sessionid=(.*?);/)?.[1].split('%')[0] || '' @@ -65,16 +67,17 @@ export class igApi { * @param baseURL * @param url * @param agent - * @param options + * @param AxiosOptions */ - private FetchIGAPI = (baseURL: string, url: string = '', agent: string = config.android, options: AxiosRequestConfig = {}): Promise | undefined => { + private FetchIGAPI = (baseURL: string, url: string = '', agent: string = config.android, AxiosOptions: AxiosRequestConfig = {}): Promise | undefined => { try { return axios({ baseURL, url, - headers: options.headers ? options.headers : this.buildHeaders(agent), - method: options.method || 'GET', - ...options + headers: AxiosOptions.headers ? AxiosOptions.headers : this.buildHeaders(agent), + method: AxiosOptions.method || 'GET', + ...AxiosOptions, + ...this.AxiosOpts }); } catch (error) { if (axios.isAxiosError(error)) { @@ -196,7 +199,8 @@ export class igApi { ): Promise => { try { const res = await this.FetchIGAPI( - config.instagram_media_info_url.replace('{mediaId}', mediaId.toString()) + config.instagram_api_v1, + `/media/${mediaId.toString()}/info/` ) return res?.data } catch (error) { @@ -212,8 +216,8 @@ export class igApi { ): Promise => { try { const res = await this.FetchIGAPI( - config.instagram_user_url, - `/${userID}/info/` + config.instagram_api_v1, + `/users/${userID}/info/` ); const graphql: UserGraphQL = res?.data; @@ -232,10 +236,9 @@ export class igApi { */ public fetchUser = async (username: username, simplifiedMetadata: boolean = true): Promise => { const userID = await this.getIdByUsername(username); - // const { data } = await IGUser.get(`/${userID}/info/`); const res = await this.FetchIGAPI( - config.instagram_user_url, - `/${userID}/info/` + config.instagram_api_v1, + `/users/${userID}/info/` ); const graphql: UserGraphQL = res?.data; const isSet: boolean = typeof graphql.user.full_name !== 'undefined'; @@ -345,10 +348,9 @@ export class igApi { public fetchStories = async (username: username): Promise => { if (!this.IgCookie) throw new Error('set cookie first to use this function'); const userID = await this.getIdByUsername(username); - //const { data } = await IGStories.get(`/${userID}/reel_media/`); const res = await this.FetchIGAPI( - config.instagram_stories_url, - `/${userID}/reel_media/`, + config.instagram_api_v1, + `/feed/user${userID}/reel_media/`, config.iPhone ); const graphql: StoriesGraphQL = res?.data; @@ -372,12 +374,9 @@ export class igApi { */ public _getReelsIds = async (username: username): Promise => { const userID: string = await this.getIdByUsername(username); - // const { data } = await IGHighlight.get('', { - // params: highlight_ids_query(userID) - // }) const res = await this.FetchIGAPI( - config.instagram_graphql, - '', + config.instagram_base_url, + '/graphql/query/', config.iPhone, { params: highlight_ids_query(userID) } ) @@ -399,10 +398,9 @@ export class igApi { * @returns */ public _getReels = async (ids: string): Promise => { - // const { data } = await IGHighlight.get('', { params: highlight_media_query(ids) }) const res = await this.FetchIGAPI( - config.instagram_graphql, - '', + config.instagram_base_url, + '/graphql/query/', config.iPhone, { params: highlight_media_query(ids) } ) @@ -420,7 +418,7 @@ export class igApi { } /** - * fetches highlight metadata (REQUIRES cookie) + * fetches highlight metadata * @param {string} username username target to fetch the highlights, also work with private profile if you use cookie \w your account that follows target account * @returns */ @@ -454,7 +452,7 @@ export class igApi { /** * fetches user posts, with pagination - * @deprecated Does not return all information about a post + * @deprecated Does not return all information about a post, use fetchUserPostsV2() * @param username * @param end_cursor get end_cursor by fetch user posts first * @returns @@ -467,7 +465,7 @@ export class igApi { 'first': 12, 'after': end_cursor } - const res = await this.FetchIGAPI(config.instagram_graphql, '', config.android, { params }) + const res = await this.FetchIGAPI(config.instagram_base_url, '/graphql/query/', config.android, { params }) return res?.data?.data.user.edge_owner_to_timeline_media } @@ -489,7 +487,7 @@ export class igApi { "after": end_cursor } } - const res = await this.FetchIGAPI(config.instagram_graphql, '', config.android, { params }) + const res = await this.FetchIGAPI(config.instagram_base_url, '/graphql/query/', config.android, { params }) return res?.data?.data.user.edge_owner_to_timeline_media } @@ -519,7 +517,7 @@ export class igApi { const nameEntity = `${uploadId}_0_${randInt(1000000000, 9999999999)}` - const ndas = { + const headers = { 'x-entity-type': 'image/jpeg', offset: 0, 'x-entity-name': nameEntity, @@ -536,7 +534,7 @@ export class igApi { 'X-IG-Bandwidth-TotalTime-MS': '0', } - const headersPhoto = this.buildHeaders(config.android, ndas) + const headersPhoto = this.buildHeaders(config.android, headers) const result = await this.FetchIGAPI( `${config.instagram_base_url}`, @@ -591,21 +589,20 @@ export class igApi { 'accept': '*/*', 'user-agent': config.desktop, 'x-requested-with': 'XMLHttpRequest', - 'x-csrftoken': await getCsrfToken(), + 'x-csrftoken': parseCookie(this.IgCookie).csrftoken, 'x-ig-app-id': '1217981644879628', 'origin': 'https://www.instagram.com', 'sec-fetch-site': 'same-origin', 'sec-fetch-mode': 'cors', 'sec-fetch-dest': 'empty', - 'referer': 'https://www.instagram.com/create/details/', + 'referer': 'https://www.instagram.com/', 'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', 'cookie': `${this.storeCookie && this.cookie.get() || this.IgCookie}`, } - //let payload = `upload_id=${responseUpload.upload_id}&caption=${caption}&usertags=&custom_accessibility_caption=&retry_timeout=` const result = await this.FetchIGAPI( - `${config.instagram_base_url}`, - `/create/${type === 'feed' ? 'configure/' : 'configure_to_story/'}`, + `${config.instagram_api_v1}`, + `/media/${type === 'feed' ? 'configure/' : 'configure_to_story/'}`, config.android, { data: new URLSearchParams(Object.entries(payloadForm)).toString(), method: 'POST', headers: headers } ); diff --git a/src/utils/index.ts b/src/utils/index.ts index 4771685..3d4deb2 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,7 @@ import { Readable } from 'stream'; import { formattedShortcode, IGPostType, postType, ProductType } from '../types/index'; import bigInt from 'big-integer'; -import { AxiosResponseHeaders } from 'axios'; +import { createHmac } from 'crypto'; // https://stackoverflow.com/questions/16758316/where-do-i-find-the-instagram-media-id-of-a-image // https://gist.github.com/sclark39/9daf13eea9c0b381667b61e3d2e7bc11 @@ -27,7 +27,7 @@ export const shortcodeToMediaID = (shortcode: string) => { export const shortcodeFromMediaID = (media_id: string) => { var o = bigInt(media_id).toString(64) - return o.replace(/<(\d+)>|(\w)/g, (m, m1, m2) => { + return o.replace(/<(\d+)>|(\w)/g, (_m: any, m1: string, m2: string) => { return ig_alphabet.charAt((m1) ? parseInt(m1) : bigint_alphabet.indexOf(m2)) @@ -94,4 +94,14 @@ export const bufferToStream = (buffer: Buffer) => { export const formatCookie = (setCookie: string[] | undefined) => { return setCookie?.map(x => x.match(/(.*?=.*?);/)?.[1])?.join('; '); +} + +export const parseCookie = (str: string) => { + return str.split(';') + .map(v => v.trim().split('=')) + .reduce((acc: any, v) => { + acc[decodeURIComponent(v[0])] = decodeURIComponent(v[1]); + delete acc[''] + return acc; + }, {}); } \ No newline at end of file From f412f68f3c143e979def1ea314b33b9c47b5d90c Mon Sep 17 00:00:00 2001 From: Gimenz Date: Thu, 27 Oct 2022 08:17:12 +0700 Subject: [PATCH 2/9] fix: fetchStories() returns 404 --- examples/example.ts | 9 ++++++++- package.json | 2 +- src/index.ts | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/example.ts b/examples/example.ts index 472aa69..3b982b8 100644 --- a/examples/example.ts +++ b/examples/example.ts @@ -1,7 +1,14 @@ // an example to get cookie using getCookie function import { getCookie, igApi, isIgPostUrl, shortcodeFormatter } from '../src' -const ig = new igApi('your Cookie'); + +// some example working with axios proxy +const proxy = { + host: '127.0.0.1', + port: 1337, + protocol: 'http' +} +const ig = new igApi('your Cookie', false, { proxy }); // you can easily get ig cookie. from anywhere, termux, terminal or etc getCookie('username', 'password').then(res => { diff --git a/package.json b/package.json index ec9c69e..e027116 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "insta-fetcher", - "version": "1.3.23", + "version": "1.3.25", "description": "Simplified Instagram metadata scraping", "main": "./dist/index.js", "scripts": { diff --git a/src/index.ts b/src/index.ts index cd9c01d..0c15479 100644 --- a/src/index.ts +++ b/src/index.ts @@ -350,7 +350,7 @@ export class igApi { const userID = await this.getIdByUsername(username); const res = await this.FetchIGAPI( config.instagram_api_v1, - `/feed/user${userID}/reel_media/`, + `/feed/user/${userID}/reel_media/`, config.iPhone ); const graphql: StoriesGraphQL = res?.data; From 897e66a4cf987ce15c0c3077d1cb725acfc3bc2f Mon Sep 17 00:00:00 2001 From: Muhamad Ristiyanto Date: Thu, 20 Jul 2023 16:57:17 +0700 Subject: [PATCH 3/9] feat: stories graphql --- package-lock.json | 4 ++-- src/index.ts | 20 ++++++++++---------- src/types/StoriesMetadata.ts | 3 ++- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index c1e71e4..fb2ca4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "insta-fetcher", - "version": "1.3.23", + "version": "1.3.25", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "insta-fetcher", - "version": "1.3.23", + "version": "1.3.25", "license": "MIT", "dependencies": { "axios": "^0.27.2", diff --git a/src/index.ts b/src/index.ts index 0c15479..d45c3d3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -346,7 +346,6 @@ export class igApi { * @returns */ public fetchStories = async (username: username): Promise => { - if (!this.IgCookie) throw new Error('set cookie first to use this function'); const userID = await this.getIdByUsername(username); const res = await this.FetchIGAPI( config.instagram_api_v1, @@ -354,17 +353,18 @@ export class igApi { config.iPhone ); const graphql: StoriesGraphQL = res?.data; - const isFollowing: boolean = - typeof graphql.user.friendship_status !== 'undefined'; + const isFollowing = typeof graphql.user?.friendship_status !== 'undefined'; - if (!isFollowing && graphql.user.is_private) + if (!isFollowing && graphql.user.is_private) { throw new Error('Private profile'); - if (graphql.items.length == 0) throw new Error('Stories not available'); - return { - username: graphql.user.username, - stories_count: graphql.media_count, - stories: this._parseStories(graphql), - }; + } else { + return { + username: graphql.user.username, + stories_count: graphql.media_count, + stories: graphql.items.length == 0 ? null : this._parseStories(graphql), + graphql, + }; + } } /** diff --git a/src/types/StoriesMetadata.ts b/src/types/StoriesMetadata.ts index 2515d56..9d90935 100644 --- a/src/types/StoriesMetadata.ts +++ b/src/types/StoriesMetadata.ts @@ -6,7 +6,8 @@ export interface IGStoriesMetadata { username: string; /** stories count */ stories_count: number; - stories: ItemStories[]; + stories: ItemStories[] | null; + graphql: StoriesGraphQL; } /** an Array of simplified StoriesMetadata */ From 973ed8572b3940131a9a37c99c59d7b2441533ca Mon Sep 17 00:00:00 2001 From: Muhamad Ristiyanto Date: Thu, 20 Jul 2023 16:58:15 +0700 Subject: [PATCH 4/9] feat: stories graphql --- package.json | 102 +++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index e027116..2ec1447 100644 --- a/package.json +++ b/package.json @@ -1,53 +1,53 @@ { - "name": "insta-fetcher", - "version": "1.3.25", - "description": "Simplified Instagram metadata scraping", - "main": "./dist/index.js", - "scripts": { - "build:all": "tsc && typedoc", - "build": "tsc", - "build:docs": "typedoc", - "build:tsc": "tsc", - "start": "tsc && node dist/index.js", - "prepare": "npm run build-ts", - "build-ts": "tsc" - }, - "files": [ - "dist" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/Gimenz/insta-fetcher.git" - }, - "publishConfig": { - "registry": "https://registry.npmjs.org/" - }, - "keywords": [ - "instagram-scraper", - "instagram-downloader", - "instagram-saver", - "insta-scraper", - "instagram", - "ig-scraper", - "ig-api", - "instagram-private-api", - "instagram-api", - "instagram-scraping" - ], - "author": "Muhamad Ristiyanto ", - "license": "MIT", - "bugs": { - "url": "https://github.com/Gimenz/insta-fetcher/issues" - }, - "homepage": "https://github.com/Gimenz/insta-fetcher", - "dependencies": { - "axios": "^0.27.2", - "big-integer": "^1.6.51", - "form-data": "^4.0.0" - }, - "devDependencies": { - "@types/node": "^17.0.29", - "typedoc": "^0.22.15", - "typescript": "^4.6.3" - } + "name": "insta-fetcher", + "version": "1.3.26", + "description": "Simplified Instagram metadata scraping", + "main": "./dist/index.js", + "scripts": { + "build:all": "tsc && typedoc", + "build": "tsc", + "build:docs": "typedoc", + "build:tsc": "tsc", + "start": "tsc && node dist/index.js", + "prepare": "npm run build-ts", + "build-ts": "tsc" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/Gimenz/insta-fetcher.git" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "keywords": [ + "instagram-scraper", + "instagram-downloader", + "instagram-saver", + "insta-scraper", + "instagram", + "ig-scraper", + "ig-api", + "instagram-private-api", + "instagram-api", + "instagram-scraping" + ], + "author": "Muhamad Ristiyanto ", + "license": "MIT", + "bugs": { + "url": "https://github.com/Gimenz/insta-fetcher/issues" + }, + "homepage": "https://github.com/Gimenz/insta-fetcher", + "dependencies": { + "axios": "^0.27.2", + "big-integer": "^1.6.51", + "form-data": "^4.0.0" + }, + "devDependencies": { + "@types/node": "^17.0.29", + "typedoc": "^0.22.15", + "typescript": "^4.6.3" + } } From cdc54d76ad75e2181ca82f2d2b7b512f78466f2f Mon Sep 17 00:00:00 2001 From: Muhamad Ristiyanto Date: Sat, 2 Dec 2023 22:59:42 +0700 Subject: [PATCH 5/9] think storing cookie is bad --- src/index.ts | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/index.ts b/src/index.ts index d45c3d3..0485309 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ import fs from 'fs' import FormData from 'form-data'; import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { bufferToStream, getPostType, parseCookie, randInt, shortcodeFormatter } from './utils/index'; -import { CookieHandler } from './helper/CookieHandler'; import { username, url, IgCookie, ProductType, MediaType, IChangedProfilePicture } from './types'; import { IGUserMetadata, UserGraphQL } from './types/UserMetadata'; import { IGStoriesMetadata, ItemStories, StoriesGraphQL } from './types/StoriesMetadata'; @@ -33,20 +32,16 @@ export class igApi { * @param storeCookie * @param AxiosOpts */ - constructor(private IgCookie: IgCookie = '', public storeCookie: boolean = true, public AxiosOpts: AxiosRequestConfig = {}) { + constructor(private IgCookie: IgCookie = '', public AxiosOpts: AxiosRequestConfig = {}) { this.IgCookie = IgCookie; - if (this.storeCookie) { - this.setCookie(this.IgCookie); - } this.AxiosOpts = AxiosOpts; } - private cookie = new CookieHandler(this.IgCookie) private accountUserId = this.IgCookie.match(/sessionid=(.*?);/)?.[1].split('%')[0] || '' private buildHeaders = (agent: string = config.android, options?: any) => { return { 'user-agent': agent, - 'cookie': `${this.storeCookie && this.cookie.get() || this.IgCookie}`, + 'cookie': `${this.IgCookie}`, 'authority': 'www.instagram.com', 'content-type': 'application/x-www-form-urlencoded', 'origin': 'https://www.instagram.com', @@ -86,21 +81,6 @@ export class igApi { } } - /** - * Set cookie for most all IG Request - * @param {IgCookie} IgCookie - */ - private setCookie = (IgCookie: IgCookie = this.IgCookie) => { - try { - if (!this.cookie.check()) { - this.cookie.save(IgCookie); - } else { - this.cookie.update(IgCookie); - } - } catch (error) { - throw error; - } - } /** * get user id by username * @param {username} username @@ -165,7 +145,6 @@ export class igApi { } public fetchPost = async (url: url): Promise => { - if (!this.IgCookie) throw new Error('set cookie first to use this function'); const post = shortcodeFormatter(url); //const req = (await IGFetchDesktop.get(`/${post.type}/${post.shortcode}/?__a=1`)) @@ -220,8 +199,6 @@ export class igApi { `/users/${userID}/info/` ); const graphql: UserGraphQL = res?.data; - - if (!this.IgCookie) throw new Error('set cookie first to use this function'); return graphql } catch (error) { throw error @@ -242,8 +219,6 @@ export class igApi { ); const graphql: UserGraphQL = res?.data; const isSet: boolean = typeof graphql.user.full_name !== 'undefined'; - if (!this.IgCookie) throw new Error('set cookie first to use this function'); - if (!isSet && this.cookie.check()) throw new Error('Invalid cookie, pls update with new cookie'); if (!simplifiedMetadata) { return graphql as UserGraphQL } else return { @@ -424,7 +399,6 @@ export class igApi { */ public fetchHighlights = async (username: username): Promise => { try { - if (!this.IgCookie) throw new Error('set cookie first to use this function'); const ids = await this._getReelsIds(username); const reels = await Promise.all(ids.map(x => this._getReels(x.highlight_id))) @@ -556,7 +530,6 @@ export class igApi { * @returns */ public addPost = async (photo: string | Buffer, type: 'feed' | 'story' = 'feed', options: MediaConfigureOptions): Promise => { - if (!this.IgCookie) throw new Error('set cookie first to use this function'); try { const dateObj = new Date() const now = dateObj @@ -597,7 +570,7 @@ export class igApi { 'sec-fetch-dest': 'empty', 'referer': 'https://www.instagram.com/', 'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', - 'cookie': `${this.storeCookie && this.cookie.get() || this.IgCookie}`, + 'cookie': `${this.IgCookie}`, } const result = await this.FetchIGAPI( From 6101dfd879b71b2d5c68c1ab9bf958bb5f4a5529 Mon Sep 17 00:00:00 2001 From: Muhamad Ristiyanto Date: Sat, 2 Dec 2023 23:02:01 +0700 Subject: [PATCH 6/9] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ec1447..3237220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "insta-fetcher", - "version": "1.3.26", + "version": "1.3.27", "description": "Simplified Instagram metadata scraping", "main": "./dist/index.js", "scripts": { From a220e84905782753e0a43f4503e0ae03a3b03d7f Mon Sep 17 00:00:00 2001 From: Evandro <34420396+ev4ndropc@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:51:05 -0300 Subject: [PATCH 7/9] Added functions to search the list of followers and following by a user --- src/index.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 0485309..df30246 100644 --- a/src/index.ts +++ b/src/index.ts @@ -95,6 +95,24 @@ export class igApi { return res?.data.graphql.user.id || res } + public searchFollower = async (userId: string, seachTerm: string): Promise => { + const res = await this.FetchIGAPI( + config.instagram_base_url, + `/api/v1/friendships/${userId}/followers/?count=12&query=${seachTerm}&search_surface=follow_list_page`, + config.iPhone, + ); + return res?.data || res + } + + public searchFollowing = async (userId: string, seachTerm: string): Promise => { + const res = await this.FetchIGAPI( + config.instagram_base_url, + `/api/v1/friendships/${userId}/following/?query=${seachTerm}`, + config.iPhone, + ); + return res?.data || res + } + private _formatSidecar = (data: IRawBody): Array => { const gql = data.items[0] let urls: MediaUrls[] = [] @@ -611,4 +629,4 @@ export class igApi { return result?.data } -} \ No newline at end of file +} From 0079589d81dd3246ef0b3b3d153dd12979dff4fa Mon Sep 17 00:00:00 2001 From: Evandro <34420396+ev4ndropc@users.noreply.github.com> Date: Sun, 24 Dec 2023 16:49:47 -0300 Subject: [PATCH 8/9] add userId and searchTerm types --- src/index.ts | 6 +++--- src/types/index.ts | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index df30246..5c5fcb3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import fs from 'fs' import FormData from 'form-data'; import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { bufferToStream, getPostType, parseCookie, randInt, shortcodeFormatter } from './utils/index'; -import { username, url, IgCookie, ProductType, MediaType, IChangedProfilePicture } from './types'; +import { username, userId, seachTerm, url, IgCookie, ProductType, MediaType, IChangedProfilePicture } from './types'; import { IGUserMetadata, UserGraphQL } from './types/UserMetadata'; import { IGStoriesMetadata, ItemStories, StoriesGraphQL } from './types/StoriesMetadata'; import { highlight_ids_query, highlight_media_query } from './helper/query'; @@ -95,7 +95,7 @@ export class igApi { return res?.data.graphql.user.id || res } - public searchFollower = async (userId: string, seachTerm: string): Promise => { + public searchFollower = async (userId: userId, seachTerm: seachTerm): Promise => { const res = await this.FetchIGAPI( config.instagram_base_url, `/api/v1/friendships/${userId}/followers/?count=12&query=${seachTerm}&search_surface=follow_list_page`, @@ -104,7 +104,7 @@ export class igApi { return res?.data || res } - public searchFollowing = async (userId: string, seachTerm: string): Promise => { + public searchFollowing = async (userId: userId, seachTerm: seachTerm): Promise => { const res = await this.FetchIGAPI( config.instagram_base_url, `/api/v1/friendships/${userId}/following/?query=${seachTerm}`, diff --git a/src/types/index.ts b/src/types/index.ts index 85b6621..c4f41a8 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -13,6 +13,10 @@ export * from './LoginData' /** instagram username */ export type username = string; +/** instagram user pk */ +export type userId = string; +/** term to search for a user, it can be their name or username */ +export type seachTerm = string; /** instagram password */ export type password = string; /** Instagram Cookie */ From f8a1a132204dc77fec097274d075ce92e9e12268 Mon Sep 17 00:00:00 2001 From: Ahda Date: Fri, 23 Feb 2024 16:34:55 +0700 Subject: [PATCH 9/9] anuan --- examples/example.ts | 6 +++--- tea.yaml | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 tea.yaml diff --git a/examples/example.ts b/examples/example.ts index 3b982b8..3bac048 100644 --- a/examples/example.ts +++ b/examples/example.ts @@ -8,7 +8,7 @@ const proxy = { port: 1337, protocol: 'http' } -const ig = new igApi('your Cookie', false, { proxy }); +const ig = new igApi('your Cookie', { proxy }); // you can easily get ig cookie. from anywhere, termux, terminal or etc getCookie('username', 'password').then(res => { @@ -48,10 +48,10 @@ getCookie('username', 'password').then(res => { console.log(userV2); // ig url can be extracted , you can use shortcodeFormatter - const formatted = shortcodeFormatter('https://www.instagram.com/p/CW0hkIOFip9/?utm_source=ig_web_copy_link'); + const formatted = shortcodeFormatter('https://www.instagram.com/p/C3M96a2vOCV/?utm_source=ig_web_copy_link&igsh=MzRlODBiNWFlZA=='); console.log(formatted); // or if you want to check wether the ig post is valid url? - const check = isIgPostUrl('https://www.instagram.com/p/CW0hkIOFip9/?utm_source=ig_web_copy_link'); + const check = isIgPostUrl('https://www.instagram.com/p/C3M96a2vOCV/?utm_source=ig_web_copy_link&igsh=MzRlODBiNWFlZA=='); console.log(check); })(); diff --git a/tea.yaml b/tea.yaml new file mode 100644 index 0000000..213cea7 --- /dev/null +++ b/tea.yaml @@ -0,0 +1,6 @@ +# https://tea.xyz/what-is-this-file +--- +version: 1.0.0 +codeOwners: + - '0xBf3Ea78f403cA79E4D7F75C9cc0aF84EFc8A5a98' +quorum: 1