Skip to content

Commit

Permalink
Merge pull request #38 from k-miras/feature-users-post-pagination
Browse files Browse the repository at this point in the history
request options can be modified in constructor. Added pagination in _getPosts()
  • Loading branch information
jlobos authored Jun 3, 2018
2 parents 08af220 + f122f6d commit 6e009f7
Show file tree
Hide file tree
Showing 5 changed files with 1,721 additions and 1,670 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
node_modules
test/credentials.json
test/cookies.json
132 changes: 79 additions & 53 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ const useragentFromSeed = require('useragent-from-seed')
const baseUrl = 'https://www.instagram.com'

class Instagram {
constructor({ username, password, cookieStore }, { language, proxy } = {}) {
constructor(
{ username, password, cookieStore },
{ language, proxy, requestOptions } = {}
) {
this.credentials = {
username,
password
Expand All @@ -22,21 +25,23 @@ class Instagram {
jar.getCookies(baseUrl).find(({ key }) => key === 'csrftoken') || {}

const userAgent = useragentFromSeed(username)

this.request = request.defaults({
baseUrl,
headers: {
'User-Agent': userAgent,
'Accept-Language': language || 'en-US',
'X-Instagram-AJAX': 1,
'X-CSRFToken': csrftoken,
'X-Requested-With': 'XMLHttpRequest',
Referer: baseUrl
},
proxy,
json: true,
jar
})
if (requestOptions === undefined) {
requestOptions = {}
}
requestOptions.baseUrl = baseUrl
requestOptions.uri = ''
requestOptions.headers = {
'User-Agent': userAgent,
'Accept-Language': language || 'en-US',
'X-Instagram-AJAX': 1,
'X-CSRFToken': csrftoken,
'X-Requested-With': 'XMLHttpRequest',
Referer: baseUrl
}
requestOptions.proxy = proxy
requestOptions.jar = jar
requestOptions.json = true
this.request = request.defaults(requestOptions)
}

async login({ username, password } = {}, { _sharedData = true } = {}) {
Expand Down Expand Up @@ -86,9 +91,11 @@ class Instagram {
return res.body
}

_getSharedData(url = '/') {
async _getSharedData(url = '/') {
return this.request(url)
.then(html => /window._sharedData = (.*);/.exec(html)[1])
.then(
html => html.split('window._sharedData = ')[1].split(';</script>')[0]
)
.then(_sharedData => JSON.parse(_sharedData))
}

Expand All @@ -101,19 +108,20 @@ class Instagram {
.digest('hex')
}

logout() {
async logout() {
return this.request('/accounts/logout/ajax/')
}

// https://github.com/jlobos/instagram-web-api/issues/23
getHome() {
async getHome() {
return this.request('/?__a=1').then(data => data.graphql.user)
}

async getUserByUsername({ username }) {
return this.request({
uri: `/${username}/?__a=1`,
headers: {
referer: baseUrl + '/' + username + '/',
'x-instagram-gis': await this._getGis(`/${username}/`)
}
}).then(data => data.graphql.user)
Expand Down Expand Up @@ -193,7 +201,7 @@ class Instagram {
})
}

_getFollowData({ fieldName, queryHash, variables }) {
async _getFollowData({ fieldName, queryHash, variables }) {
return this.request('/graphql/query/', {
qs: {
query_hash: queryHash,
Expand All @@ -208,7 +216,7 @@ class Instagram {
}))
}

getFollowers({ userId, first = 20, after }) {
async getFollowers({ userId, first = 20, after }) {
return this._getFollowData({
fieldName: 'edge_followed_by',
queryHash: '37479f2b8209594dde7facb0d904896a',
Expand All @@ -220,7 +228,7 @@ class Instagram {
})
}

getFollowings({ userId, first = 20, after }) {
async getFollowings({ userId, first = 20, after }) {
return this._getFollowData({
fieldName: 'edge_follow',
queryHash: '58712303d941c6855d4e888c5f0cd22f',
Expand All @@ -232,17 +240,17 @@ class Instagram {
})
}

getActivity() {
async getActivity() {
return this.request('/accounts/activity/?__a=1').then(
data => data.graphql.user
)
}

getProfile() {
async getProfile() {
return this.request('/accounts/edit/?__a=1').then(data => data.form_data)
}

updateProfile({
async updateProfile({
name = '',
email = '',
username,
Expand All @@ -266,19 +274,19 @@ class Instagram {
})
}

changeProfilePhoto({ photo }) {
async changeProfilePhoto({ photo }) {
return this.request.post('/accounts/web_change_profile_picture/', {
formData: {
profile_pic: isUrl(photo) ? request(photo) : fs.createReadStream(photo)
}
})
}

deleteMedia({ mediaId }) {
async deleteMedia({ mediaId }) {
return this.request.post(`/create/${mediaId}/delete/`)
}

_uploadPhoto({ photo }) {
async _uploadPhoto({ photo }) {
return this.request.post('/create/upload/photo/', {
formData: {
upload_id: Date.now().toString(),
Expand All @@ -288,61 +296,61 @@ class Instagram {
})
}

uploadStory({ photo, caption = '' }) {
async uploadStory({ photo, caption = '' }) {
return this._uploadPhoto({ photo }).then(({ upload_id }) =>
this.request.post('/create/configure_to_story/', {
form: { upload_id, caption }
})
)
}

uploadPhoto({ photo, caption = '' }) {
async uploadPhoto({ photo, caption = '' }) {
return this._uploadPhoto({ photo }).then(({ upload_id }) =>
this.request.post('/create/configure/', {
form: { upload_id, caption }
})
)
}

getMediaFeedByLocation({ locationId }) {
async getMediaFeedByLocation({ locationId }) {
return this.request(`/explore/locations/${locationId}/?__a=1`).then(
data => data.graphql.location
)
}

getMediaFeedByHashtag({ hashtag }) {
async getMediaFeedByHashtag({ hashtag }) {
return this.request(`/explore/tags/${hashtag}/?__a=1`).then(
data => data.graphql.hashtag
)
}

locationSearch({ query, latitude, longitude }) {
async locationSearch({ query, latitude, longitude }) {
return this.request('/location_search/', {
qs: { search_query: query, latitude, longitude }
}).then(data => data.venues)
}

getMediaByShortcode({ shortcode }) {
async getMediaByShortcode({ shortcode }) {
return this.request(`/p/${shortcode}/?__a=1`).then(
data => data.graphql.shortcode_media
)
}

addComment({ mediaId, text }) {
async addComment({ mediaId, text }) {
return this.request.post(`/web/comments/${mediaId}/add/`, {
form: { comment_text: text }
})
}

deleteComment({ mediaId, commentId }) {
async deleteComment({ mediaId, commentId }) {
return this.request.post(`/web/comments/${mediaId}/delete/${commentId}/`)
}

getChallenge({ challengeUrl }) {
async getChallenge({ challengeUrl }) {
return this.request(`${challengeUrl}?__a=1`)
}

_navigateChallenge({ challengeUrl, endpoint, form }) {
async _navigateChallenge({ challengeUrl, endpoint, form }) {
const url = endpoint
? challengeUrl.replace('/challenge/', `/challenge/${endpoint}/`)
: challengeUrl
Expand All @@ -354,7 +362,7 @@ class Instagram {
})
}

updateChallenge({ challengeUrl, choice, securityCode }) {
async updateChallenge({ challengeUrl, choice, securityCode }) {
const form = securityCode ? { security_code: securityCode } : { choice }

return this._navigateChallenge({
Expand All @@ -363,63 +371,81 @@ class Instagram {
})
}

resetChallenge({ challengeUrl }) {
async resetChallenge({ challengeUrl }) {
return this._navigateChallenge({
challengeUrl,
endpoint: 'reset'
})
}

replayChallenge({ challengeUrl }) {
async replayChallenge({ challengeUrl }) {
return this._navigateChallenge({
challengeUrl,
endpoint: 'replay'
})
}

approve({ userId }) {
async approve({ userId }) {
return this.request.post(`/web/friendships/${userId}/approve/`)
}

ignore({ userId }) {
async ignore({ userId }) {
return this.request.post(`/web/friendships/${userId}/ignore/`)
}

follow({ userId }) {
async follow({ userId }) {
return this.request.post(`/web/friendships/${userId}/follow/`)
}

unfollow({ userId }) {
async unfollow({ userId }) {
return this.request.post(`/web/friendships/${userId}/unfollow/`)
}

block({ userId }) {
async block({ userId }) {
return this.request.post(`/web/friendships/${userId}/block/`)
}

unblock({ userId }) {
async unblock({ userId }) {
return this.request.post(`/web/friendships/${userId}/unblock/`)
}

like({ mediaId }) {
async like({ mediaId }) {
return this.request.post(`/web/likes/${mediaId}/like/`)
}

unlike({ mediaId }) {
async unlike({ mediaId }) {
return this.request.post(`/web/likes/${mediaId}/unlike/`)
}

save({ mediaId }) {
async save({ mediaId }) {
return this.request.post(`/web/save/${mediaId}/save/`)
}

unsave({ mediaId }) {
async unsave({ mediaId }) {
return this.request.post(`/web/save/${mediaId}/unsave/`)
}

search({ query, context = 'blended' }) {
async search({ query, context = 'blended' }) {
return this.request('/web/search/topsearch/', { qs: { query, context } })
}

async _getPosts({ userId, perPage = 12, nextPageToken }) {
const variables = JSON.stringify({
id: userId,
first: perPage,
after: nextPageToken
})
const options = {
qs: {
query_hash: '42323d64886122307be10013ad2dcc44',
variables
}
}

return this.request
.get('/graphql/query/', options)
.then(response => response.data.user)
}
}

module.exports = Instagram
Loading

0 comments on commit 6e009f7

Please sign in to comment.