Skip to content

Commit

Permalink
feat (module) implement post data query
Browse files Browse the repository at this point in the history
  • Loading branch information
EdouardCourty committed Oct 16, 2021
1 parent c37b0c8 commit 5c852a0
Show file tree
Hide file tree
Showing 15 changed files with 1,602 additions and 1,752 deletions.
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
"lines-between-class-members": "off",
"comma-dangle": "off",
"max-len": "off",
"no-trailing-spaces": "off"
"no-trailing-spaces": "off",
"dot-notation": "off",
"indent": "off",
"quote-props": "off",
"no-shadow": "off",
"prefer-destructuring": "off",
"no-prototype-builtins": "off",
"object-shorthand": "off",
"consistent-return": "off"
},
"env": {
"jest": true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
- name: Running ESLint
run: npm run eslint
- name: Run unit tests
run: npm run unit-tests
run: npm run test
1 change: 1 addition & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/user-instagram-reborn.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

164 changes: 164 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,167 @@

[![Downloads](https://img.shields.io/npm/dt/user-instagram)](https://img.shields.io/david/EdouardCourty/user-instagram)
[![Node.js CI](https://github.com/EdouardCourty/user-instagram/actions/workflows/node.js.yml/badge.svg)](https://github.com/EdouardCourty/user-instagram/actions/workflows/node.js.yml)

## Usage

Use this module in your projet by installing it with `npm install user-instagram`.

Here is a quick example or usage:
```javascript
const instagram = require('user-instagram');

await instagram.authenticate('my_instagram_username', 'my_instagram_password');

// Fetching a user
instagram.getUserData('edouard_courty').then(userData => {
// Do whatever you need to to with this data
console.log(`My username is ${userData.getUsername()}.`);
})

// Fetching a post
instagram.getPostData('CUc7tBPFXvP').then(postData => {
// Do whatever you need to to with this data
console.log(`The caption of this post is ${postData.getCaption()}.`);
})
```

## Documentation

In the previous versions of `user-instagram`, only a small amount of requests could be sent every day without getting rate-mimited.
Couple of issues were submitted about this problem and it's the main reason why I decided to refactor this module, and add an authentication method to it.

### Authentication

The `authenticate` method takes two mandatory parameters: `username` and `password`.
A good way to keep these strings safe is storing them in an uncommited file in your repo like some `instagram_config.json` file structured like the following:
```json
{
"username": "your username here",
"password": "your password here"
}
```
Then use it like this:
```javascript
const instagram = require('user-instagram');
const {username, password} = require('instagram_config.json')

await instagram.authenticate(username, password);
```

### Getting a user's data

When logged in, you can request the data of any public user you want, plus the private users that your account follows.
The `getUserData` method takes only one parameter: the username of the user to be fetched.

This method will return a promise holding a `User` class, containing getters for all the interesting properties of this class.

#### Available user properties

All the boolean values are accessed with the following methods: (the function names should be self explanatory of their return value)
- `isVerified()`
- `isPrivate()`
- `isBusinessAccount()`
- `isProfessionalAccount()`
- `hasClips()`
- `hasArEffect()`
- `hasChannel()`
- `hasGuides()`
- `isHidingLikesAndViewsCount()`
- `hasJoinedRecently()`

All the non-boolean values are accessed with the following methods:
- `getUsername()`
- `getBiography()`
- `getPublicationsCount()`
- `getFollowersCount()`
- `getExternalUrl()`
- `getFollowingCount()`
- `getFullName()`
- `getHighlightsReelsCount()`
- `getId()`
- `getBusinessAddressJson()`
- `getBusinessContactMethod()`
- `getBusinessEmail()`
- `getBusinessPhoneNumber()`
- `getBusinessCategoryName()`
- `getOverallCategoryName()`
- `getCategoryEnum()`
- `getProfilePicture()`
- `getHdProfilePicture()`
- `getPronouns()`
- `getMedias()`

### Getting a post's data

When logged in, you can request the data of any public post you want, plus the posts of the private accounts that your account follows.
The `getPostData` method takes only one parameter: the shortcode of the post to be fetched.

This method will return a promise holding a `Post` class, containing getters for all the interesting properties of this class.

#### Available post properties

All the boolean values are accessed with the following methods: (the function names should be self explanatory of their return value)
- `isVideo()`
- `areCommentsDisabled()`
- `areLikesAndViewsCountDisabled()`
- `isPaidPartnership()`
- `isAd()`
- `hasAudio()`

All the non-boolean values are accessed with the following methods:
- `getId()`
- `getType()`
- `getShortcode()`
- `getDimensions()`
- `getDisplayUrl()`
- `getVariants()`
- `getAccessibilityCaption()`
- `getTaggedUsers()`
- `getCaption()`
- `getCommentsCount()`
- `getComments()`
- `getDate()`
- `getLikesCount()`
- `getLocation()`
- `getOwner()`
- `getChildren()`
- `getVideoViewsCount()`
- `getVideoPlaysCount()`

#### Generic properties shared across the module

Each Media from the `getMedias()` in the `User` class method is a `Media` class that has these getters:
- `getType()`
- `getId()`
- `getShortcode()`
- `getCaption()`
- `getDimensions()`
- `getDisplayUrl()`
- `getTaggedUsers()`
- `isVideo()`
- `getAccessibilityCaption()`
- `areCommentsDisabled()`
- `getCommentsCount()`
- `getLikesCount()`
- `getTimestamp()`
- `getLocation()`
- `getChildren()`
- `hasAudio()`
- `getViewsCount()`
- `getVideoUrl()`

Every `TaggerUser` from `getTaggedUsers()` in a `Post` or a `User.getMedias()` hold the following getters:
- `getTagXPosition()`
- `getTagYPosition()`
- `getFullName()`
- `getId()`
- `isVerified()`
- `getProfilePictureUrl()`
- `getUsername()`

Every dimension value from `getDimensions()` from a `Media` or a `Post` is a `Dimension` class with a bult-in aspect-ratio calculator:
- `getHeight()`
- `getWidth()`
- `getAspectRatio()`

© Edouard Courty - 2021
7 changes: 4 additions & 3 deletions app/services/BasicRequestHandler.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const axios = require('axios');

const applicationData = require('../data.json');

const CacheStorage = require('./CacheStorage');
const NoSessionError = require('../../src/Instagram/Domain/errors/NoSessionError');

const InstagramRepository = require('../../src/Instagram/Infrastructure/InstagramRepository');
const applicationData = require('../data.json');
const axios = require('axios');

class BasicRequestHandler {
static async handle(queryUrl) {
Expand Down
10 changes: 5 additions & 5 deletions app/services/CookieReader.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
class CookieReader {
/**
* @param {string} cookie
* @param {string} key
* @param {string} cookieKey
* @returns Promise<String>
*/
static read(cookie, key) {
key = key.trim();
static read(cookie, cookieKey) {
const key = cookieKey.trim();
return new Promise((resolve, reject) => {
cookie
.split('=')
.map((splitted) => splitted.split(';'))
.flat(1)
.forEach((value, index, array) => {
value = value.trim();
.forEach((arrayValue, index, array) => {
const value = arrayValue.trim();
if (index > 0 && array[index - 1].trim() === key) {
return resolve(value);
}
Expand Down
1 change: 0 additions & 1 deletion app/services/InstagramHelper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class InstagramHelper {

static BASE_URL = 'https://www.instagram.com/';
static AUTH_URL = 'https://www.instagram.com/accounts/login/ajax/';
static DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36';
Expand Down
Loading

0 comments on commit 5c852a0

Please sign in to comment.