pupgram 0.1.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -1
- package/dist/actions/create-post/index.d.ts +1 -1
- package/dist/actions/create-post/index.js +1 -1
- package/dist/actions/create-post/put-post-caption.action.js +2 -2
- package/dist/actions/create-post/wait-for-post-configure.action.d.ts +3 -0
- package/dist/actions/create-post/wait-for-post-configure.action.js +32 -0
- package/dist/actions/create-reel/index.d.ts +3 -0
- package/dist/actions/create-reel/index.js +19 -0
- package/dist/actions/create-reel/select-ratio.action.d.ts +2 -0
- package/dist/actions/create-reel/select-ratio.action.js +49 -0
- package/dist/actions/create-reel/try-close-reel-info.action.d.ts +2 -0
- package/dist/actions/create-reel/try-close-reel-info.action.js +21 -0
- package/dist/actions/create-reel/wait-for-reel-configurate.action.d.ts +3 -0
- package/dist/actions/create-reel/wait-for-reel-configurate.action.js +26 -0
- package/dist/actions/delay.action.js +2 -2
- package/dist/configs/en.config.js +3 -0
- package/dist/configs/pt-br.config.js +3 -0
- package/dist/enums/index.d.ts +1 -0
- package/dist/enums/index.js +17 -0
- package/dist/enums/language.enum.d.ts +10 -0
- package/dist/enums/language.enum.js +14 -0
- package/dist/instagram.d.ts +14 -2
- package/dist/instagram.js +43 -9
- package/dist/interfaces/action.interface.d.ts +1 -1
- package/dist/interfaces/config.interface.d.ts +3 -0
- package/dist/utils/create-post-url.util.d.ts +1 -0
- package/dist/utils/create-post-url.util.js +6 -0
- package/dist/utils/create-reel-url.util.d.ts +1 -0
- package/dist/utils/create-reel-url.util.js +6 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/require-vanilla-puppeteer.d.ts +1 -0
- package/dist/utils/require-vanilla-puppeteer.js +15 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ async function main() {
|
|
|
47
47
|
caption: "Hello from Pupgram! 🚀",
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
console.log(`Post created! URL:
|
|
50
|
+
console.log(`Post created! URL: ${postData.url}`)
|
|
51
51
|
console.log(postData)
|
|
52
52
|
|
|
53
53
|
// 4. Close the instance
|
|
@@ -57,6 +57,42 @@ async function main() {
|
|
|
57
57
|
main()
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### Creating a Reel
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { Instagram, enConfig } from "pupgram"
|
|
64
|
+
|
|
65
|
+
async function main() {
|
|
66
|
+
// 1. Initialize the Instagram instance
|
|
67
|
+
const instagram = await Instagram.create({
|
|
68
|
+
puppeteer: {
|
|
69
|
+
userDataDir: ".user-data",
|
|
70
|
+
headless: "shell",
|
|
71
|
+
},
|
|
72
|
+
config: enConfig,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// 2. Ensure you are logged in
|
|
76
|
+
await instagram.ensureLoggedIn({
|
|
77
|
+
username: "your-username",
|
|
78
|
+
password: "your-password",
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// 3. Create a Reel
|
|
82
|
+
const reelData = await instagram.createReel({
|
|
83
|
+
filePath: "./path/to/video.mp4",
|
|
84
|
+
caption: "My awesome Reel! 🎥",
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
console.log(`Reel created! URL: ${reelData.url}`)
|
|
88
|
+
|
|
89
|
+
// 4. Close the instance
|
|
90
|
+
await instagram.close()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
main()
|
|
94
|
+
```
|
|
95
|
+
|
|
60
96
|
---
|
|
61
97
|
|
|
62
98
|
### Features
|
|
@@ -76,10 +112,39 @@ Automate content publishing with support for:
|
|
|
76
112
|
- **Captions**: Add rich text captions to your posts.
|
|
77
113
|
- **Confirmation**: Waiting for server confirmation to ensure the post is live before proceeding.
|
|
78
114
|
|
|
115
|
+
#### 🎞️ Reel Creation
|
|
116
|
+
|
|
117
|
+
Automate reel publishing with support for:
|
|
118
|
+
- **Video Upload**: Upload video files.
|
|
119
|
+
- **Aspect Ratio**: Automatically handles ratio selection for Reels (Original/9:16).
|
|
120
|
+
- **Captions**: Add rich text captions.
|
|
121
|
+
|
|
79
122
|
#### ⚙️ Configurable
|
|
80
123
|
|
|
81
124
|
Pupgram is designed to be flexible. You can provide custom configurations for different locales or UI variations using the `config` option in `Instagram.create`.
|
|
82
125
|
|
|
126
|
+
#### 🌍 Forcing Language
|
|
127
|
+
|
|
128
|
+
You can force Instagram to load in a specific language using the `languageParam` option. This is useful to ensure the UI matches the selectors provided in your config.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { Instagram, enConfig, Language } from "pupgram"
|
|
132
|
+
|
|
133
|
+
const instagram = await Instagram.create({
|
|
134
|
+
// ... other options
|
|
135
|
+
config: enConfig,
|
|
136
|
+
languageParam: Language.EN_US // Forces ?hl=en-us
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### 🐞 Debugging
|
|
141
|
+
|
|
142
|
+
When things go wrong, Pupgram helps you diagnose the issue. If `screenshotOnError` or `htmlContentOnError` are enabled (default: `true`), Pupgram creates an `errors` directory in your project root.
|
|
143
|
+
|
|
144
|
+
Each error generates a timestamped folder containing:
|
|
145
|
+
- **error.png**: A screenshot of the page at the time of the error.
|
|
146
|
+
- **error.html**: The HTML content of the page.
|
|
147
|
+
|
|
83
148
|
---
|
|
84
149
|
|
|
85
150
|
## 🧪 Tests (Not included yet, CONTRIBUTE! :D)
|
|
@@ -4,4 +4,4 @@ export * from "./select-files.action";
|
|
|
4
4
|
export * from "./put-post-caption.action";
|
|
5
5
|
export * from "./click-on-next-button.action";
|
|
6
6
|
export * from "./click-on-share-button.action";
|
|
7
|
-
export * from "./wait-for-
|
|
7
|
+
export * from "./wait-for-post-configure.action";
|
|
@@ -20,4 +20,4 @@ __exportStar(require("./select-files.action"), exports);
|
|
|
20
20
|
__exportStar(require("./put-post-caption.action"), exports);
|
|
21
21
|
__exportStar(require("./click-on-next-button.action"), exports);
|
|
22
22
|
__exportStar(require("./click-on-share-button.action"), exports);
|
|
23
|
-
__exportStar(require("./wait-for-
|
|
23
|
+
__exportStar(require("./wait-for-post-configure.action"), exports);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.putPostCaptionAction = void 0;
|
|
4
|
-
const delay_util_1 = require("../../utils/delay.util");
|
|
5
4
|
const error_1 = require("../../error");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
6
|
const putPostCaptionAction = (caption) => {
|
|
7
7
|
return async ({ page, config, logger, defaultTimeout }) => {
|
|
8
8
|
logger.info("Starting to put post caption");
|
|
@@ -17,7 +17,7 @@ const putPostCaptionAction = (caption) => {
|
|
|
17
17
|
await captionElement.focus();
|
|
18
18
|
await page.keyboard.type(caption);
|
|
19
19
|
await page.keyboard.press("Tab");
|
|
20
|
-
await (0,
|
|
20
|
+
await (0, utils_1.delay)(300);
|
|
21
21
|
logger.info("Post caption successfully entered");
|
|
22
22
|
};
|
|
23
23
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForPostConfigureAction = void 0;
|
|
4
|
+
const error_1 = require("../../error");
|
|
5
|
+
const waitForPostConfigureAction = async ({ page, config, logger, defaultTimeout }) => {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
logger.info("Waiting for confirmation");
|
|
8
|
+
let result;
|
|
9
|
+
const configureEndpoints = ["/api/v1/media/configure/", "/api/v1/media/configure_sidecar/"];
|
|
10
|
+
logger.debug("Waiting for response");
|
|
11
|
+
const response = await page.waitForResponse((res) => configureEndpoints.some((endpoint) => res.url().includes(endpoint)) &&
|
|
12
|
+
res.status() === 200 &&
|
|
13
|
+
res.request().method() === "POST", { timeout: 60000 * 5 });
|
|
14
|
+
const json = await response.json();
|
|
15
|
+
if (json.status !== "ok" || !json.media) {
|
|
16
|
+
throw new error_1.InstagramError("Failed to create post");
|
|
17
|
+
}
|
|
18
|
+
const media = json.media;
|
|
19
|
+
result = {
|
|
20
|
+
id: (_a = media.id) !== null && _a !== void 0 ? _a : media.pk,
|
|
21
|
+
pk: media.pk,
|
|
22
|
+
code: media.code,
|
|
23
|
+
caption: ((_b = media.caption) === null || _b === void 0 ? void 0 : _b.text) || "",
|
|
24
|
+
};
|
|
25
|
+
logger.debug("Response received. Waiting for confirmation text message");
|
|
26
|
+
await page.waitForSelector(`xpath///*[contains(text(), "${config.confirmationText}")]`, {
|
|
27
|
+
timeout: defaultTimeout,
|
|
28
|
+
});
|
|
29
|
+
logger.debug("Confirmation text message found");
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
exports.waitForPostConfigureAction = waitForPostConfigureAction;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./select-ratio.action"), exports);
|
|
18
|
+
__exportStar(require("./try-close-reel-info.action"), exports);
|
|
19
|
+
__exportStar(require("./wait-for-reel-configurate.action"), exports);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.selectRatioAction = void 0;
|
|
4
|
+
const error_1 = require("../../error");
|
|
5
|
+
const selectRatioAction = async ({ page, config, logger, defaultTimeout }) => {
|
|
6
|
+
logger.info("Selecting ratio");
|
|
7
|
+
const selectRatioSelector = `xpath///button[.//*[name()='svg']//*[name()='title' and text()='${config.reelSelectRatioText}']]`;
|
|
8
|
+
const videoElement = await page.waitForSelector("video", { timeout: defaultTimeout });
|
|
9
|
+
if (!videoElement) {
|
|
10
|
+
throw new error_1.InstagramError("Video element not found");
|
|
11
|
+
}
|
|
12
|
+
logger.debug("Video element found");
|
|
13
|
+
await page.evaluate((videoElement) => {
|
|
14
|
+
const container = videoElement.closest("div");
|
|
15
|
+
if (container instanceof HTMLElement) {
|
|
16
|
+
container.dataset.__oldDisplay = container.style.display;
|
|
17
|
+
container.style.display = "none";
|
|
18
|
+
}
|
|
19
|
+
}, videoElement);
|
|
20
|
+
logger.debug("Video container display hidden");
|
|
21
|
+
try {
|
|
22
|
+
const selectRatioElement = await page.waitForSelector(selectRatioSelector, {
|
|
23
|
+
timeout: defaultTimeout,
|
|
24
|
+
});
|
|
25
|
+
if (!selectRatioElement) {
|
|
26
|
+
throw new error_1.InstagramError("Select ratio element not found");
|
|
27
|
+
}
|
|
28
|
+
await selectRatioElement.click();
|
|
29
|
+
logger.debug("Select ratio element clicked");
|
|
30
|
+
const originalRatioElement = await page.waitForSelector(`xpath///div[./span[contains(text(), '${config.reelSelectOriginalRatioText}')]]`, { timeout: defaultTimeout });
|
|
31
|
+
if (!originalRatioElement) {
|
|
32
|
+
throw new error_1.InstagramError("Original ratio element not found");
|
|
33
|
+
}
|
|
34
|
+
await originalRatioElement.click();
|
|
35
|
+
logger.debug("Original ratio element clicked");
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
logger.info("Restoring video container display");
|
|
39
|
+
await page.evaluate(() => {
|
|
40
|
+
document.querySelectorAll("div[data-__old-display]").forEach((el) => {
|
|
41
|
+
const oldDisplay = el.getAttribute("data-__old-display");
|
|
42
|
+
el.style.display = oldDisplay || "";
|
|
43
|
+
el.removeAttribute("data-__old-display");
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
logger.debug("Original ratio element clicked");
|
|
48
|
+
};
|
|
49
|
+
exports.selectRatioAction = selectRatioAction;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tryCloseReelInfoAction = void 0;
|
|
4
|
+
const tryCloseReelInfoAction = async ({ page, config, logger, defaultTimeout }) => {
|
|
5
|
+
logger.info("Closing reel info");
|
|
6
|
+
try {
|
|
7
|
+
const closeButton = await page.waitForSelector(`xpath///button[text()='${config.reelCloseInfoText}']`, {
|
|
8
|
+
timeout: defaultTimeout * 2,
|
|
9
|
+
});
|
|
10
|
+
if (!closeButton) {
|
|
11
|
+
logger.debug("Close button not found");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
await closeButton.click();
|
|
15
|
+
logger.debug("Close button clicked");
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
logger.debug("Close button not found");
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
exports.tryCloseReelInfoAction = tryCloseReelInfoAction;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForReelConfigureAction = void 0;
|
|
4
|
+
const waitForReelConfigureAction = async ({ page }) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const start = Date.now();
|
|
7
|
+
const timeout = 5 * 60000;
|
|
8
|
+
while (Date.now() - start < timeout) {
|
|
9
|
+
const response = await page.waitForResponse((res) => res.url().includes("/api/v1/media/configure_to_clips/") && res.request().method() === "POST", { timeout: timeout });
|
|
10
|
+
const json = await response.json();
|
|
11
|
+
if (json.media) {
|
|
12
|
+
return {
|
|
13
|
+
caption: (_a = json.caption.text) !== null && _a !== void 0 ? _a : "",
|
|
14
|
+
id: json.media.id,
|
|
15
|
+
pk: json.media.pk,
|
|
16
|
+
code: json.media.code,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (json.status === "fail" && json.message === "Transcode not finished yet.") {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`Unexpected response: ${JSON.stringify(json)}`);
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Timeout waiting for Reel configure");
|
|
25
|
+
};
|
|
26
|
+
exports.waitForReelConfigureAction = waitForReelConfigureAction;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.delayAction = void 0;
|
|
4
|
-
const
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
5
|
const delayAction = (delayTime) => {
|
|
6
6
|
return async ({ logger }) => {
|
|
7
7
|
logger.info("Delaying");
|
|
8
|
-
await (0,
|
|
8
|
+
await (0, utils_1.delay)(delayTime);
|
|
9
9
|
logger.debug("Delaying");
|
|
10
10
|
};
|
|
11
11
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./language.enum";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./language.enum"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Language = void 0;
|
|
4
|
+
var Language;
|
|
5
|
+
(function (Language) {
|
|
6
|
+
Language["EN_US"] = "en-us";
|
|
7
|
+
Language["EN_UK"] = "en-uk";
|
|
8
|
+
Language["EN"] = "en";
|
|
9
|
+
Language["PT_BR"] = "pt-br";
|
|
10
|
+
Language["PT"] = "pt";
|
|
11
|
+
Language["PT_PT"] = "pt-pt";
|
|
12
|
+
Language["ES"] = "es";
|
|
13
|
+
Language["ES_MX"] = "es-mx";
|
|
14
|
+
})(Language || (exports.Language = Language = {}));
|
package/dist/instagram.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Browser } from "puppeteer";
|
|
2
2
|
import { PostData } from "./interfaces/post-data.interface";
|
|
3
3
|
import { Config } from "./interfaces";
|
|
4
|
+
import { Language } from "./enums";
|
|
4
5
|
export declare const defaultTimeout = 10000;
|
|
5
6
|
export type CreateInstagramOptions = {
|
|
6
7
|
puppeteer: {
|
|
@@ -14,6 +15,7 @@ export type CreateInstagramOptions = {
|
|
|
14
15
|
htmlContentOnError?: boolean;
|
|
15
16
|
config: Config;
|
|
16
17
|
defaultTimeout?: number;
|
|
18
|
+
languageParam?: Language;
|
|
17
19
|
};
|
|
18
20
|
export type InstagramOptions = {
|
|
19
21
|
browser: Browser;
|
|
@@ -22,6 +24,7 @@ export type InstagramOptions = {
|
|
|
22
24
|
htmlContentOnError: boolean;
|
|
23
25
|
config: Config;
|
|
24
26
|
defaultTimeout?: number;
|
|
27
|
+
languageParam?: Language;
|
|
25
28
|
};
|
|
26
29
|
export type LogInOptions = {
|
|
27
30
|
username: string;
|
|
@@ -31,6 +34,13 @@ export type CreatePostOptions = {
|
|
|
31
34
|
filePaths: string[];
|
|
32
35
|
caption: string;
|
|
33
36
|
};
|
|
37
|
+
export type CreateReelOptions = {
|
|
38
|
+
filePath: string;
|
|
39
|
+
caption: string;
|
|
40
|
+
};
|
|
41
|
+
export type CreatePostResult = PostData & {
|
|
42
|
+
url: string;
|
|
43
|
+
};
|
|
34
44
|
export declare class Instagram {
|
|
35
45
|
readonly baseUrl = "https://www.instagram.com";
|
|
36
46
|
private readonly browser;
|
|
@@ -40,7 +50,8 @@ export declare class Instagram {
|
|
|
40
50
|
private readonly htmlContentOnError;
|
|
41
51
|
readonly config: Config;
|
|
42
52
|
readonly defaultTimeout: number;
|
|
43
|
-
|
|
53
|
+
readonly languageParam?: Language;
|
|
54
|
+
constructor({ browser, logLevel, screenshotOnError, htmlContentOnError, config, defaultTimeout: optionsDefaultTimeout, languageParam, }: InstagramOptions);
|
|
44
55
|
static create(options: CreateInstagramOptions): Promise<Instagram>;
|
|
45
56
|
close(): Promise<void>;
|
|
46
57
|
private initalizePage;
|
|
@@ -48,5 +59,6 @@ export declare class Instagram {
|
|
|
48
59
|
needsLogin(): Promise<boolean>;
|
|
49
60
|
logIn({ username, password }: LogInOptions): Promise<void>;
|
|
50
61
|
ensureLoggedIn({ username, password }: LogInOptions): Promise<void>;
|
|
51
|
-
createPost({ caption, filePaths }: CreatePostOptions): Promise<
|
|
62
|
+
createPost({ caption, filePaths }: CreatePostOptions): Promise<CreatePostResult>;
|
|
63
|
+
createReel({ caption, filePath }: CreateReelOptions): Promise<CreatePostResult>;
|
|
52
64
|
}
|
package/dist/instagram.js
CHANGED
|
@@ -5,18 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Instagram = exports.defaultTimeout = void 0;
|
|
7
7
|
const puppeteer_extra_plugin_stealth_1 = __importDefault(require("puppeteer-extra-plugin-stealth"));
|
|
8
|
-
const puppeteer_extra_1 =
|
|
8
|
+
const puppeteer_extra_1 = require("puppeteer-extra");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
11
|
const create_post_1 = require("./actions/create-post");
|
|
11
12
|
const login_1 = require("./actions/login");
|
|
13
|
+
const create_reel_1 = require("./actions/create-reel");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
12
15
|
const needs_login_action_1 = require("./actions/needs-login.action");
|
|
13
16
|
const logger_helper_1 = require("./helpers/logger.helper");
|
|
14
17
|
const delay_action_1 = require("./actions/delay.action");
|
|
15
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
16
|
-
puppeteer_extra_1.default.use((0, puppeteer_extra_plugin_stealth_1.default)());
|
|
17
18
|
exports.defaultTimeout = 10000;
|
|
18
19
|
class Instagram {
|
|
19
|
-
constructor({ browser, logLevel, screenshotOnError, htmlContentOnError, config, defaultTimeout: optionsDefaultTimeout, }) {
|
|
20
|
+
constructor({ browser, logLevel, screenshotOnError, htmlContentOnError, config, defaultTimeout: optionsDefaultTimeout, languageParam, }) {
|
|
20
21
|
this.baseUrl = "https://www.instagram.com";
|
|
21
22
|
this.browser = browser;
|
|
22
23
|
this.logLevel = logLevel;
|
|
@@ -25,10 +26,13 @@ class Instagram {
|
|
|
25
26
|
this.htmlContentOnError = htmlContentOnError;
|
|
26
27
|
this.config = config;
|
|
27
28
|
this.defaultTimeout = optionsDefaultTimeout !== null && optionsDefaultTimeout !== void 0 ? optionsDefaultTimeout : exports.defaultTimeout;
|
|
29
|
+
this.languageParam = languageParam;
|
|
28
30
|
}
|
|
29
31
|
static async create(options) {
|
|
30
32
|
var _a, _b, _c, _d;
|
|
31
|
-
const
|
|
33
|
+
const puppeteer = new puppeteer_extra_1.PuppeteerExtra(...(0, utils_1.requireVanillaPuppeteer)());
|
|
34
|
+
puppeteer.use((0, puppeteer_extra_plugin_stealth_1.default)());
|
|
35
|
+
const browser = await puppeteer.launch({
|
|
32
36
|
headless: options.puppeteer.headless,
|
|
33
37
|
executablePath: options.puppeteer.executablePath,
|
|
34
38
|
userDataDir: options.puppeteer.userDataDir,
|
|
@@ -50,6 +54,7 @@ class Instagram {
|
|
|
50
54
|
htmlContentOnError: (_d = options.htmlContentOnError) !== null && _d !== void 0 ? _d : true,
|
|
51
55
|
config: options.config,
|
|
52
56
|
defaultTimeout: options.defaultTimeout,
|
|
57
|
+
languageParam: options.languageParam,
|
|
53
58
|
});
|
|
54
59
|
}
|
|
55
60
|
async close() {
|
|
@@ -60,8 +65,13 @@ class Instagram {
|
|
|
60
65
|
async initalizePage() {
|
|
61
66
|
this.logger.info("Initalizing page");
|
|
62
67
|
const page = await this.browser.newPage();
|
|
63
|
-
await page.setViewport({
|
|
64
|
-
|
|
68
|
+
await page.setViewport({
|
|
69
|
+
width: 1920,
|
|
70
|
+
height: 919,
|
|
71
|
+
});
|
|
72
|
+
await page.goto(`${this.baseUrl}${this.languageParam ? `?hl=${this.languageParam}` : ""}`, {
|
|
73
|
+
waitUntil: "domcontentloaded",
|
|
74
|
+
});
|
|
65
75
|
this.logger.debug("Page initalized");
|
|
66
76
|
return page;
|
|
67
77
|
}
|
|
@@ -147,10 +157,34 @@ class Instagram {
|
|
|
147
157
|
create_post_1.clickOnNextButtonAction,
|
|
148
158
|
(0, create_post_1.putPostCaptionAction)(caption),
|
|
149
159
|
create_post_1.clickOnShareButtonAction,
|
|
150
|
-
create_post_1.
|
|
160
|
+
create_post_1.waitForPostConfigureAction,
|
|
151
161
|
]);
|
|
152
162
|
this.logger.debug("Post created");
|
|
153
|
-
return
|
|
163
|
+
return {
|
|
164
|
+
...result,
|
|
165
|
+
url: (0, utils_1.createPostUrl)(result.code),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async createReel({ caption, filePath }) {
|
|
169
|
+
this.logger.info("Creating reel");
|
|
170
|
+
const result = await this.executeWithDiagnostics([
|
|
171
|
+
(0, delay_action_1.delayAction)(1500),
|
|
172
|
+
create_post_1.clickOnCreateButtonAction,
|
|
173
|
+
create_post_1.clickOnPostButtonAction,
|
|
174
|
+
(0, create_post_1.selectFilesAction)([filePath]),
|
|
175
|
+
create_reel_1.tryCloseReelInfoAction,
|
|
176
|
+
create_reel_1.selectRatioAction,
|
|
177
|
+
create_post_1.clickOnNextButtonAction,
|
|
178
|
+
create_post_1.clickOnNextButtonAction,
|
|
179
|
+
(0, create_post_1.putPostCaptionAction)(caption),
|
|
180
|
+
create_post_1.clickOnShareButtonAction,
|
|
181
|
+
create_reel_1.waitForReelConfigureAction,
|
|
182
|
+
]);
|
|
183
|
+
this.logger.debug("Reel created");
|
|
184
|
+
return {
|
|
185
|
+
...result,
|
|
186
|
+
url: (0, utils_1.createReelUrl)(result.code),
|
|
187
|
+
};
|
|
154
188
|
}
|
|
155
189
|
}
|
|
156
190
|
exports.Instagram = Instagram;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createPostUrl(code: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createReelUrl(code: string): string;
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -15,3 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./evaluated-click.util"), exports);
|
|
18
|
+
__exportStar(require("./create-post-url.util"), exports);
|
|
19
|
+
__exportStar(require("./create-reel-url.util"), exports);
|
|
20
|
+
__exportStar(require("./delay.util"), exports);
|
|
21
|
+
__exportStar(require("./require-vanilla-puppeteer"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function requireVanillaPuppeteer(): any[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireVanillaPuppeteer = requireVanillaPuppeteer;
|
|
4
|
+
function requireVanillaPuppeteer() {
|
|
5
|
+
try {
|
|
6
|
+
return [require("puppeteer"), undefined];
|
|
7
|
+
}
|
|
8
|
+
catch (_) { }
|
|
9
|
+
try {
|
|
10
|
+
return [require("puppeteer-core"), undefined];
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
return [undefined, err];
|
|
14
|
+
}
|
|
15
|
+
}
|