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.
Files changed (34) hide show
  1. package/README.md +66 -1
  2. package/dist/actions/create-post/index.d.ts +1 -1
  3. package/dist/actions/create-post/index.js +1 -1
  4. package/dist/actions/create-post/put-post-caption.action.js +2 -2
  5. package/dist/actions/create-post/wait-for-post-configure.action.d.ts +3 -0
  6. package/dist/actions/create-post/wait-for-post-configure.action.js +32 -0
  7. package/dist/actions/create-reel/index.d.ts +3 -0
  8. package/dist/actions/create-reel/index.js +19 -0
  9. package/dist/actions/create-reel/select-ratio.action.d.ts +2 -0
  10. package/dist/actions/create-reel/select-ratio.action.js +49 -0
  11. package/dist/actions/create-reel/try-close-reel-info.action.d.ts +2 -0
  12. package/dist/actions/create-reel/try-close-reel-info.action.js +21 -0
  13. package/dist/actions/create-reel/wait-for-reel-configurate.action.d.ts +3 -0
  14. package/dist/actions/create-reel/wait-for-reel-configurate.action.js +26 -0
  15. package/dist/actions/delay.action.js +2 -2
  16. package/dist/configs/en.config.js +3 -0
  17. package/dist/configs/pt-br.config.js +3 -0
  18. package/dist/enums/index.d.ts +1 -0
  19. package/dist/enums/index.js +17 -0
  20. package/dist/enums/language.enum.d.ts +10 -0
  21. package/dist/enums/language.enum.js +14 -0
  22. package/dist/instagram.d.ts +14 -2
  23. package/dist/instagram.js +43 -9
  24. package/dist/interfaces/action.interface.d.ts +1 -1
  25. package/dist/interfaces/config.interface.d.ts +3 -0
  26. package/dist/utils/create-post-url.util.d.ts +1 -0
  27. package/dist/utils/create-post-url.util.js +6 -0
  28. package/dist/utils/create-reel-url.util.d.ts +1 -0
  29. package/dist/utils/create-reel-url.util.js +6 -0
  30. package/dist/utils/index.d.ts +4 -0
  31. package/dist/utils/index.js +4 -0
  32. package/dist/utils/require-vanilla-puppeteer.d.ts +1 -0
  33. package/dist/utils/require-vanilla-puppeteer.js +15 -0
  34. 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: https://www.instagram.com/p/${postData.code}`)
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-configmation.action";
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-configmation.action"), exports);
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, delay_util_1.delay)(300);
20
+ await (0, utils_1.delay)(300);
21
21
  logger.info("Post caption successfully entered");
22
22
  };
23
23
  };
@@ -0,0 +1,3 @@
1
+ import { PostData } from "../../interfaces/post-data.interface";
2
+ import { Action } from "../../interfaces";
3
+ export declare const waitForPostConfigureAction: Action<PostData>;
@@ -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,3 @@
1
+ export * from "./select-ratio.action";
2
+ export * from "./try-close-reel-info.action";
3
+ export * from "./wait-for-reel-configurate.action";
@@ -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,2 @@
1
+ import { Action } from "../../interfaces";
2
+ export declare const selectRatioAction: Action<void>;
@@ -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,2 @@
1
+ import { Action } from "../../interfaces";
2
+ export declare const tryCloseReelInfoAction: Action<void>;
@@ -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,3 @@
1
+ import { PostData } from "../../interfaces/post-data.interface";
2
+ import { Action } from "../../interfaces";
3
+ export declare const waitForReelConfigureAction: Action<PostData>;
@@ -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 delay_util_1 = require("../utils/delay.util");
4
+ const utils_1 = require("../utils");
5
5
  const delayAction = (delayTime) => {
6
6
  return async ({ logger }) => {
7
7
  logger.info("Delaying");
8
- await (0, delay_util_1.delay)(delayTime);
8
+ await (0, utils_1.delay)(delayTime);
9
9
  logger.debug("Delaying");
10
10
  };
11
11
  };
@@ -16,4 +16,7 @@ exports.enConfig = {
16
16
  nextButtonText: "Next",
17
17
  confirmationText: "Your post has been shared.",
18
18
  shareButtonText: "Share",
19
+ reelSelectRatioText: "Select crop",
20
+ reelSelectOriginalRatioText: "Original",
21
+ reelCloseInfoText: "Ok",
19
22
  };
@@ -16,4 +16,7 @@ exports.ptBrConfig = {
16
16
  nextButtonText: "Avançar",
17
17
  confirmationText: "Seu post foi compartilhado.",
18
18
  shareButtonText: "Compartilhar",
19
+ reelSelectRatioText: "Selecionar corte",
20
+ reelSelectOriginalRatioText: "Original",
21
+ reelCloseInfoText: "Ok",
19
22
  };
@@ -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,10 @@
1
+ export declare enum Language {
2
+ EN_US = "en-us",
3
+ EN_UK = "en-uk",
4
+ EN = "en",
5
+ PT_BR = "pt-br",
6
+ PT = "pt",
7
+ PT_PT = "pt-pt",
8
+ ES = "es",
9
+ ES_MX = "es-mx"
10
+ }
@@ -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 = {}));
@@ -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
- constructor({ browser, logLevel, screenshotOnError, htmlContentOnError, config, defaultTimeout: optionsDefaultTimeout, }: InstagramOptions);
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<PostData>;
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 = __importDefault(require("puppeteer-extra"));
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 browser = await puppeteer_extra_1.default.launch({
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({ width: 1920, height: 1080 });
64
- await page.goto(this.baseUrl, { waitUntil: "domcontentloaded" });
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.waitForConfirmationAction,
160
+ create_post_1.waitForPostConfigureAction,
151
161
  ]);
152
162
  this.logger.debug("Post created");
153
- return result;
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;
@@ -5,6 +5,6 @@ export type ActionOptions = {
5
5
  config: Config;
6
6
  logger: Logger;
7
7
  page: Page;
8
- defaultTimeout?: number;
8
+ defaultTimeout: number;
9
9
  };
10
10
  export type Action<T = void> = (options: ActionOptions) => Promise<T>;
@@ -13,4 +13,7 @@ export interface Config {
13
13
  nextButtonText: string;
14
14
  shareButtonText: string;
15
15
  confirmationText: string;
16
+ reelSelectRatioText: string;
17
+ reelSelectOriginalRatioText: string;
18
+ reelCloseInfoText: string;
16
19
  }
@@ -0,0 +1 @@
1
+ export declare function createPostUrl(code: string): string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPostUrl = createPostUrl;
4
+ function createPostUrl(code) {
5
+ return `https://www.instagram.com/p/${code}`;
6
+ }
@@ -0,0 +1 @@
1
+ export declare function createReelUrl(code: string): string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createReelUrl = createReelUrl;
4
+ function createReelUrl(code) {
5
+ return `https://www.instagram.com/reel/${code}`;
6
+ }
@@ -1 +1,5 @@
1
1
  export * from "./evaluated-click.util";
2
+ export * from "./create-post-url.util";
3
+ export * from "./create-reel-url.util";
4
+ export * from "./delay.util";
5
+ export * from "./require-vanilla-puppeteer";
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pupgram",
3
- "version": "0.1.5",
3
+ "version": "0.3.0",
4
4
  "type": "commonjs",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",