@gannochenko/staticstripes 0.0.12 → 0.0.15
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/Makefile +20 -0
- package/dist/asset-manager.d.ts +1 -0
- package/dist/asset-manager.d.ts.map +1 -1
- package/dist/asset-manager.js +3 -0
- package/dist/asset-manager.js.map +1 -1
- package/dist/cli/ai-generation-strategy-factory.d.ts +23 -0
- package/dist/cli/ai-generation-strategy-factory.d.ts.map +1 -0
- package/dist/cli/ai-generation-strategy-factory.js +44 -0
- package/dist/cli/ai-generation-strategy-factory.js.map +1 -0
- package/dist/cli/ai-generation-strategy.d.ts +33 -0
- package/dist/cli/ai-generation-strategy.d.ts.map +1 -0
- package/dist/cli/ai-generation-strategy.js +3 -0
- package/dist/cli/ai-generation-strategy.js.map +1 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.d.ts +38 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.d.ts.map +1 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.js +174 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.js.map +1 -0
- package/dist/cli/auth-strategy-factory.d.ts +31 -0
- package/dist/cli/auth-strategy-factory.d.ts.map +1 -0
- package/dist/cli/auth-strategy-factory.js +61 -0
- package/dist/cli/auth-strategy-factory.js.map +1 -0
- package/dist/cli/auth-strategy.d.ts +31 -0
- package/dist/cli/auth-strategy.d.ts.map +1 -0
- package/dist/cli/auth-strategy.js +3 -0
- package/dist/cli/auth-strategy.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +6 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +103 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +69 -2
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/instagram/instagram-auth-strategy.d.ts +31 -0
- package/dist/cli/instagram/instagram-auth-strategy.d.ts.map +1 -0
- package/dist/cli/instagram/instagram-auth-strategy.js +505 -0
- package/dist/cli/instagram/instagram-auth-strategy.js.map +1 -0
- package/dist/cli/instagram/instagram-upload-strategy.d.ts +45 -0
- package/dist/cli/instagram/instagram-upload-strategy.d.ts.map +1 -0
- package/dist/cli/instagram/instagram-upload-strategy.js +303 -0
- package/dist/cli/instagram/instagram-upload-strategy.js.map +1 -0
- package/dist/cli/s3/s3-upload-strategy.d.ts.map +1 -1
- package/dist/cli/s3/s3-upload-strategy.js +7 -3
- package/dist/cli/s3/s3-upload-strategy.js.map +1 -1
- package/dist/cli/upload-strategy-factory.d.ts +1 -1
- package/dist/cli/upload-strategy-factory.d.ts.map +1 -1
- package/dist/cli/upload-strategy-factory.js +5 -5
- package/dist/cli/upload-strategy-factory.js.map +1 -1
- package/dist/cli/youtube/youtube-auth-strategy.d.ts +11 -0
- package/dist/cli/youtube/youtube-auth-strategy.d.ts.map +1 -0
- package/dist/cli/youtube/youtube-auth-strategy.js +320 -0
- package/dist/cli/youtube/youtube-auth-strategy.js.map +1 -0
- package/dist/cli/youtube/youtube-upload-strategy.d.ts +10 -3
- package/dist/cli/youtube/youtube-upload-strategy.d.ts.map +1 -1
- package/dist/cli/youtube/youtube-upload-strategy.js +96 -16
- package/dist/cli/youtube/youtube-upload-strategy.js.map +1 -1
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/html-project-parser.d.ts +40 -1
- package/dist/html-project-parser.d.ts.map +1 -1
- package/dist/html-project-parser.js +343 -9
- package/dist/html-project-parser.js.map +1 -1
- package/dist/lib/file.d.ts +2 -0
- package/dist/lib/file.d.ts.map +1 -0
- package/dist/lib/file.js +13 -0
- package/dist/lib/file.js.map +1 -0
- package/dist/lib/net.d.ts +19 -0
- package/dist/lib/net.d.ts.map +1 -0
- package/dist/lib/net.js +101 -0
- package/dist/lib/net.js.map +1 -0
- package/dist/project.d.ts +5 -2
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +9 -1
- package/dist/project.js.map +1 -1
- package/dist/type.d.ts +17 -0
- package/dist/type.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/asset-manager.ts +4 -0
- package/src/cli/ai-generation-strategy-factory.ts +48 -0
- package/src/cli/ai-generation-strategy.ts +35 -0
- package/src/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.ts +266 -0
- package/src/cli/auth-strategy-factory.ts +67 -0
- package/src/cli/auth-strategy.ts +37 -0
- package/src/cli/commands/auth.ts +120 -0
- package/src/cli/commands/generate.ts +55 -2
- package/src/cli/instagram/instagram-auth-strategy.ts +569 -0
- package/src/cli/instagram/instagram-upload-strategy.ts +398 -0
- package/src/cli/s3/s3-upload-strategy.ts +7 -3
- package/src/cli/upload-strategy-factory.ts +6 -9
- package/src/cli/youtube/youtube-auth-strategy.ts +323 -0
- package/src/cli/youtube/youtube-upload-strategy.ts +147 -16
- package/src/cli.ts +2 -4
- package/src/html-project-parser.ts +429 -8
- package/src/lib/file.ts +11 -0
- package/src/lib/net.ts +120 -0
- package/src/project.ts +10 -0
- package/src/type.ts +19 -0
- package/dist/cli/youtube/auth-commands.d.ts +0 -3
- package/dist/cli/youtube/auth-commands.d.ts.map +0 -1
- package/dist/cli/youtube/auth-commands.js +0 -273
- package/dist/cli/youtube/auth-commands.js.map +0 -1
- package/dist/cli/youtube/cli.d.ts +0 -7
- package/dist/cli/youtube/cli.d.ts.map +0 -1
- package/dist/cli/youtube/cli.js +0 -13
- package/dist/cli/youtube/cli.js.map +0 -1
- package/dist/cli/youtube/upload-handler.d.ts +0 -12
- package/dist/cli/youtube/upload-handler.d.ts.map +0 -1
- package/dist/cli/youtube/upload-handler.js +0 -66
- package/dist/cli/youtube/upload-handler.js.map +0 -1
- package/src/cli/youtube/auth-commands.ts +0 -312
- package/src/cli/youtube/cli.ts +0 -11
- package/src/cli/youtube/upload-handler.ts +0 -101
|
@@ -0,0 +1,505 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.InstagramAuthStrategy = void 0;
|
|
40
|
+
const fs_1 = require("fs");
|
|
41
|
+
const path_1 = require("path");
|
|
42
|
+
const open_1 = __importDefault(require("open"));
|
|
43
|
+
const http_1 = __importDefault(require("http"));
|
|
44
|
+
const url_1 = require("url");
|
|
45
|
+
const readline = __importStar(require("readline"));
|
|
46
|
+
/**
|
|
47
|
+
* Instagram authentication strategy
|
|
48
|
+
* Automatic OAuth flow with browser redirect (like YouTube)
|
|
49
|
+
*/
|
|
50
|
+
class InstagramAuthStrategy {
|
|
51
|
+
getTag() {
|
|
52
|
+
return 'instagram';
|
|
53
|
+
}
|
|
54
|
+
async execute(uploadName, projectPath, options) {
|
|
55
|
+
console.log(`🔐 Instagram Authentication Setup\n`);
|
|
56
|
+
const rl = readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
});
|
|
60
|
+
const question = (prompt) => {
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
rl.question(prompt, (answer) => {
|
|
63
|
+
resolve(answer);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
try {
|
|
68
|
+
console.log('━'.repeat(60));
|
|
69
|
+
console.log('STEP 1: Enter Instagram App Credentials');
|
|
70
|
+
console.log('━'.repeat(60));
|
|
71
|
+
console.log('');
|
|
72
|
+
console.log('💡 Run `staticstripes auth-help instagram` for setup instructions\n');
|
|
73
|
+
const appId = await question('Enter your Instagram App ID: ');
|
|
74
|
+
if (!appId || appId.trim().length < 5) {
|
|
75
|
+
throw new Error('Invalid App ID');
|
|
76
|
+
}
|
|
77
|
+
const appSecret = await question('Enter your Instagram App Secret: ');
|
|
78
|
+
if (!appSecret || appSecret.trim().length < 10) {
|
|
79
|
+
throw new Error('Invalid App Secret');
|
|
80
|
+
}
|
|
81
|
+
// Use provided redirect URL or default to localhost
|
|
82
|
+
const redirectUri = options?.oauthRedirectUrl || 'http://localhost:3000/oauth2callback';
|
|
83
|
+
console.log(`\n🔗 Using OAuth Redirect URI: ${redirectUri}`);
|
|
84
|
+
if (!redirectUri.includes('localhost')) {
|
|
85
|
+
console.log('✅ Using external URL (ngrok/Cloudflare)');
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.log('⚠️ Using localhost - this may not work with Instagram. Consider using --oauth-redirect-url with ngrok/Cloudflare');
|
|
89
|
+
}
|
|
90
|
+
console.log('\n━'.repeat(60));
|
|
91
|
+
console.log('STEP 2: Authorize with Instagram');
|
|
92
|
+
console.log('━'.repeat(60));
|
|
93
|
+
console.log('');
|
|
94
|
+
rl.close();
|
|
95
|
+
console.log('🌐 Starting local server on http://localhost:3000...\n');
|
|
96
|
+
// Wait for OAuth callback
|
|
97
|
+
const authCode = await this.waitForAuthCode(appId.trim(), redirectUri.trim());
|
|
98
|
+
console.log('🔑 Authorization code received\n');
|
|
99
|
+
console.log('🔄 Exchanging for access token...\n');
|
|
100
|
+
// Exchange code for short-lived token
|
|
101
|
+
const shortLivedToken = await this.exchangeCodeForToken(authCode, appId.trim(), appSecret.trim(), redirectUri.trim());
|
|
102
|
+
console.log('✅ Short-lived token received\n');
|
|
103
|
+
console.log('🔄 Exchanging for long-lived token (60 days)...\n');
|
|
104
|
+
// Exchange for long-lived token
|
|
105
|
+
const longLivedToken = await this.exchangeForLongLivedToken(shortLivedToken, appSecret.trim());
|
|
106
|
+
console.log('✅ Long-lived token received\n');
|
|
107
|
+
console.log('🔍 Fetching Instagram account info...\n');
|
|
108
|
+
// Get Instagram user ID
|
|
109
|
+
const { id, username } = await this.getInstagramUserId(longLivedToken);
|
|
110
|
+
console.log(`✅ Account: @${username}`);
|
|
111
|
+
console.log(`✅ Instagram User ID: ${id}\n`);
|
|
112
|
+
console.log('💾 Saving credentials...\n');
|
|
113
|
+
// Save credentials
|
|
114
|
+
const authDir = (0, path_1.resolve)(projectPath, '.auth');
|
|
115
|
+
if (!(0, fs_1.existsSync)(authDir)) {
|
|
116
|
+
(0, fs_1.mkdirSync)(authDir, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
const credentialsPath = (0, path_1.resolve)(authDir, `${uploadName}.json`);
|
|
119
|
+
const credentials = {
|
|
120
|
+
appId: appId.trim(),
|
|
121
|
+
appSecret: appSecret.trim(),
|
|
122
|
+
accessToken: longLivedToken,
|
|
123
|
+
igUserId: id,
|
|
124
|
+
};
|
|
125
|
+
(0, fs_1.writeFileSync)(credentialsPath, JSON.stringify(credentials, null, 2), 'utf-8');
|
|
126
|
+
console.log(`✅ Authentication complete for ${uploadName}!\n`);
|
|
127
|
+
console.log(`📁 Credentials saved to: ${credentialsPath}\n`);
|
|
128
|
+
console.log('⚠️ Token expires in 60 days - set a reminder to refresh!\n');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generates Instagram OAuth authorization URL
|
|
136
|
+
*/
|
|
137
|
+
getAuthUrl(appId, redirectUri) {
|
|
138
|
+
const params = new URLSearchParams({
|
|
139
|
+
client_id: appId,
|
|
140
|
+
redirect_uri: redirectUri,
|
|
141
|
+
scope: 'instagram_business_basic,instagram_business_content_publish',
|
|
142
|
+
response_type: 'code',
|
|
143
|
+
state: Math.random().toString(36).substring(7),
|
|
144
|
+
});
|
|
145
|
+
return `https://api.instagram.com/oauth/authorize?${params.toString()}`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Starts local HTTP server and waits for OAuth callback
|
|
149
|
+
*/
|
|
150
|
+
async waitForAuthCode(appId, redirectUri) {
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
const connections = new Set();
|
|
153
|
+
const server = http_1.default.createServer((req, res) => {
|
|
154
|
+
const url = (0, url_1.parse)(req.url || '', true);
|
|
155
|
+
if (url.pathname === '/oauth2callback') {
|
|
156
|
+
const code = url.query.code;
|
|
157
|
+
const error = url.query.error;
|
|
158
|
+
const closeServer = () => {
|
|
159
|
+
connections.forEach((socket) => socket.destroy());
|
|
160
|
+
connections.clear();
|
|
161
|
+
server.close();
|
|
162
|
+
};
|
|
163
|
+
if (error) {
|
|
164
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
165
|
+
res.end(`
|
|
166
|
+
<html>
|
|
167
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
168
|
+
<h1>❌ Authorization Failed</h1>
|
|
169
|
+
<p>Error: ${error}</p>
|
|
170
|
+
<p>${url.query.error_description || ''}</p>
|
|
171
|
+
<p>You can close this window.</p>
|
|
172
|
+
</body>
|
|
173
|
+
</html>
|
|
174
|
+
`);
|
|
175
|
+
res.on('finish', closeServer);
|
|
176
|
+
reject(new Error(`Authorization failed: ${error}`));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (code) {
|
|
180
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
181
|
+
res.end(`
|
|
182
|
+
<html>
|
|
183
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
184
|
+
<h1>Authorization Successful!</h1>
|
|
185
|
+
<p>You can close this window and return to the terminal.</p>
|
|
186
|
+
</body>
|
|
187
|
+
</html>
|
|
188
|
+
`);
|
|
189
|
+
res.on('finish', closeServer);
|
|
190
|
+
resolve(code);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
194
|
+
res.end(`
|
|
195
|
+
<html>
|
|
196
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
197
|
+
<h1>❌ No Authorization Code</h1>
|
|
198
|
+
<p>No code was received from Instagram.</p>
|
|
199
|
+
<p>You can close this window.</p>
|
|
200
|
+
</body>
|
|
201
|
+
</html>
|
|
202
|
+
`);
|
|
203
|
+
res.on('finish', closeServer);
|
|
204
|
+
reject(new Error('No authorization code received'));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
res.writeHead(404);
|
|
209
|
+
res.end('Not found');
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
server.on('connection', (socket) => {
|
|
213
|
+
connections.add(socket);
|
|
214
|
+
socket.on('close', () => connections.delete(socket));
|
|
215
|
+
});
|
|
216
|
+
server.listen(3000, async () => {
|
|
217
|
+
console.log('✅ Server started successfully\n');
|
|
218
|
+
console.log(`🌐 Opening browser for authorization, redirect url = ${redirectUri}\n`);
|
|
219
|
+
const authUrl = this.getAuthUrl(appId, redirectUri);
|
|
220
|
+
try {
|
|
221
|
+
await (0, open_1.default)(authUrl);
|
|
222
|
+
console.log('✅ Browser opened successfully\n');
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
console.log('⚠️ Could not open browser automatically');
|
|
226
|
+
console.log('🌐 Please visit this URL to authorize:\n');
|
|
227
|
+
console.log(authUrl);
|
|
228
|
+
console.log();
|
|
229
|
+
}
|
|
230
|
+
console.log('⏳ Waiting for authorization...\n');
|
|
231
|
+
});
|
|
232
|
+
setTimeout(() => {
|
|
233
|
+
connections.forEach((socket) => socket.destroy());
|
|
234
|
+
connections.clear();
|
|
235
|
+
server.close();
|
|
236
|
+
reject(new Error('Authentication timeout (5 minutes)'));
|
|
237
|
+
}, 5 * 60 * 1000);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Exchanges authorization code for short-lived access token
|
|
242
|
+
*/
|
|
243
|
+
async exchangeCodeForToken(code, appId, appSecret, redirectUri) {
|
|
244
|
+
const params = new URLSearchParams({
|
|
245
|
+
client_id: appId,
|
|
246
|
+
client_secret: appSecret,
|
|
247
|
+
grant_type: 'authorization_code',
|
|
248
|
+
redirect_uri: redirectUri,
|
|
249
|
+
code: code,
|
|
250
|
+
});
|
|
251
|
+
const response = await fetch('https://api.instagram.com/oauth/access_token', {
|
|
252
|
+
method: 'POST',
|
|
253
|
+
body: params,
|
|
254
|
+
});
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
const errorText = await response.text();
|
|
257
|
+
throw new Error(`Failed to exchange code for token: ${response.status} ${errorText}`);
|
|
258
|
+
}
|
|
259
|
+
const data = (await response.json());
|
|
260
|
+
if (!data.access_token) {
|
|
261
|
+
throw new Error('No access token in response');
|
|
262
|
+
}
|
|
263
|
+
return data.access_token;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Exchanges short-lived token for long-lived token (60 days)
|
|
267
|
+
*/
|
|
268
|
+
async exchangeForLongLivedToken(shortLivedToken, appSecret) {
|
|
269
|
+
const params = new URLSearchParams({
|
|
270
|
+
grant_type: 'ig_exchange_token',
|
|
271
|
+
client_secret: appSecret,
|
|
272
|
+
access_token: shortLivedToken,
|
|
273
|
+
});
|
|
274
|
+
const response = await fetch(`https://graph.instagram.com/access_token?${params.toString()}`);
|
|
275
|
+
if (!response.ok) {
|
|
276
|
+
const errorText = await response.text();
|
|
277
|
+
throw new Error(`Failed to exchange for long-lived token: ${response.status} ${errorText}`);
|
|
278
|
+
}
|
|
279
|
+
const data = (await response.json());
|
|
280
|
+
if (!data.access_token) {
|
|
281
|
+
throw new Error('No long-lived access token in response');
|
|
282
|
+
}
|
|
283
|
+
return data.access_token;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Gets the Instagram user ID and username from the /me endpoint
|
|
287
|
+
*/
|
|
288
|
+
async getInstagramUserId(accessToken) {
|
|
289
|
+
const params = new URLSearchParams({
|
|
290
|
+
fields: 'id,username',
|
|
291
|
+
access_token: accessToken,
|
|
292
|
+
});
|
|
293
|
+
const response = await fetch(`https://graph.instagram.com/me?${params.toString()}`);
|
|
294
|
+
if (!response.ok) {
|
|
295
|
+
const errorText = await response.text();
|
|
296
|
+
throw new Error(`Failed to get Instagram user info: ${response.status} ${errorText}`);
|
|
297
|
+
}
|
|
298
|
+
const data = (await response.json());
|
|
299
|
+
if (!data.id || !data.username) {
|
|
300
|
+
throw new Error('No user ID or username in response');
|
|
301
|
+
}
|
|
302
|
+
return { id: data.id, username: data.username };
|
|
303
|
+
}
|
|
304
|
+
getSetupInstructions() {
|
|
305
|
+
return `
|
|
306
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
307
|
+
Instagram Authentication Setup
|
|
308
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
309
|
+
|
|
310
|
+
Interactive OAuth flow with automatic token exchange.
|
|
311
|
+
|
|
312
|
+
⚠️ PREREQUISITES
|
|
313
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
314
|
+
✅ Instagram Business or Creator account (NOT personal)
|
|
315
|
+
✅ Facebook account (for creating the app)
|
|
316
|
+
✅ ngrok or Cloudflare Tunnel (Meta doesn't allow localhost)
|
|
317
|
+
|
|
318
|
+
Convert to Business/Creator if needed:
|
|
319
|
+
Instagram app → Profile → Menu → Settings → Account
|
|
320
|
+
→ "Switch to Professional Account" → Choose Business or Creator
|
|
321
|
+
|
|
322
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
323
|
+
STEP 1: Create Facebook App with Instagram Use Case
|
|
324
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
325
|
+
1. Go to: https://developers.facebook.com
|
|
326
|
+
2. Click "Get Started" → Log in → Complete registration
|
|
327
|
+
3. Click "My Apps" → "Create App"
|
|
328
|
+
4. When asked about use case, select:
|
|
329
|
+
⭐ "Manage messaging & content on Instagram"
|
|
330
|
+
5. Select app type: "Business"
|
|
331
|
+
6. Fill in:
|
|
332
|
+
• App name: "My Instagram Uploader"
|
|
333
|
+
• Contact email: your.email@example.com
|
|
334
|
+
7. Click "Create App"
|
|
335
|
+
|
|
336
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
337
|
+
STEP 2: Publish App to Production (IMPORTANT!)
|
|
338
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
339
|
+
Publishing to production avoids test environment limitations.
|
|
340
|
+
|
|
341
|
+
1. In app dashboard, look for "App Mode" toggle or similar
|
|
342
|
+
2. Switch from "Development" to "Live" mode
|
|
343
|
+
3. Or find "Publish" button and click it
|
|
344
|
+
|
|
345
|
+
Note: For personal use, you don't need Meta verification.
|
|
346
|
+
|
|
347
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
348
|
+
STEP 3: Navigate to Instagram Customize Wizard
|
|
349
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
350
|
+
1. Go to: Dashboard → Use Cases
|
|
351
|
+
2. Find "Manage messaging & content on Instagram"
|
|
352
|
+
3. Click "Customize" button
|
|
353
|
+
|
|
354
|
+
You'll see a wizard with several steps. Follow them in order:
|
|
355
|
+
|
|
356
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
357
|
+
STEP 4: Copy App Credentials
|
|
358
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
359
|
+
At the top of the Customize page, you'll see:
|
|
360
|
+
• Instagram App ID (copy this!)
|
|
361
|
+
• Instagram App Secret (click "Show" to reveal, copy this!)
|
|
362
|
+
|
|
363
|
+
Keep these handy - you'll need them for the auth wizard.
|
|
364
|
+
|
|
365
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
366
|
+
STEP 5: Add Required Permissions
|
|
367
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
368
|
+
In the wizard, find "Add required messaging permissions" section:
|
|
369
|
+
|
|
370
|
+
1. Look for permissions list
|
|
371
|
+
2. Enable these permissions:
|
|
372
|
+
• instagram_business_basic
|
|
373
|
+
• instagram_business_content_publish
|
|
374
|
+
3. Save changes
|
|
375
|
+
|
|
376
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
377
|
+
STEP 6: Generate Access Token & Add Account
|
|
378
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
379
|
+
In the wizard, find "Generate access token" section:
|
|
380
|
+
|
|
381
|
+
1. Click "Add account"
|
|
382
|
+
2. You'll be prompted to authenticate with Instagram
|
|
383
|
+
3. If you have a personal account, convert it to Business/Creator
|
|
384
|
+
4. Allow access for the app
|
|
385
|
+
5. Complete the authorization flow
|
|
386
|
+
|
|
387
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
388
|
+
STEP 7: Set Up Tunnel (ngrok or Cloudflare)
|
|
389
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
390
|
+
⚠️ IMPORTANT: Meta doesn't allow localhost:3000 as callback domain!
|
|
391
|
+
You MUST use ngrok or Cloudflare Tunnel BEFORE running auth.
|
|
392
|
+
|
|
393
|
+
Option A - Using ngrok (simpler but unstable domain):
|
|
394
|
+
1. Install ngrok: https://ngrok.com/download
|
|
395
|
+
2. Run: ngrok http 3000
|
|
396
|
+
3. Copy the HTTPS URL (e.g., https://abc123.ngrok-free.app)
|
|
397
|
+
4. Keep ngrok running!
|
|
398
|
+
|
|
399
|
+
⚠️ WARNING: ngrok URLs change on restart!
|
|
400
|
+
You'll need to update Meta redirect URI each time.
|
|
401
|
+
|
|
402
|
+
Option B - Using Cloudflare Tunnel (stable domain, recommended):
|
|
403
|
+
1. Set up Cloudflare Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/
|
|
404
|
+
2. Tunnel localhost:3000 to a stable domain
|
|
405
|
+
3. Your URL will be stable (e.g., https://your-domain.com)
|
|
406
|
+
|
|
407
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
408
|
+
STEP 8: Configure OAuth Redirect URI in Meta
|
|
409
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
410
|
+
In the wizard, find "Set up Instagram business login" → "Business login settings":
|
|
411
|
+
|
|
412
|
+
1. Add to "OAuth Redirect URIs":
|
|
413
|
+
https://your-tunnel-url/oauth2callback
|
|
414
|
+
|
|
415
|
+
Examples:
|
|
416
|
+
• ngrok: https://abc123.ngrok-free.app/oauth2callback
|
|
417
|
+
• Cloudflare: https://your-domain.com/oauth2callback
|
|
418
|
+
|
|
419
|
+
2. Click "Save"
|
|
420
|
+
|
|
421
|
+
⚠️ Make sure path ends with /oauth2callback (no trailing slash!)
|
|
422
|
+
|
|
423
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
424
|
+
STEP 9: Run Authentication Command
|
|
425
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
426
|
+
Make sure your tunnel (ngrok/Cloudflare) is running, then:
|
|
427
|
+
|
|
428
|
+
WITHOUT ngrok/Cloudflare (will likely fail with Instagram):
|
|
429
|
+
staticstripes auth --upload-name YOUR_UPLOAD_NAME
|
|
430
|
+
|
|
431
|
+
WITH ngrok/Cloudflare (recommended):
|
|
432
|
+
staticstripes auth --upload-name YOUR_UPLOAD_NAME \\
|
|
433
|
+
--oauth-redirect-url https://your-tunnel-url/oauth2callback
|
|
434
|
+
|
|
435
|
+
Example with ngrok:
|
|
436
|
+
staticstripes auth --upload-name ig_primary \\
|
|
437
|
+
--oauth-redirect-url https://abc123.ngrok-free.app/oauth2callback
|
|
438
|
+
|
|
439
|
+
Example with Cloudflare:
|
|
440
|
+
staticstripes auth --upload-name ig_primary \\
|
|
441
|
+
--oauth-redirect-url https://your-domain.com/oauth2callback
|
|
442
|
+
|
|
443
|
+
The command will:
|
|
444
|
+
1. Ask you to enter Instagram App ID
|
|
445
|
+
2. Ask you to enter Instagram App Secret
|
|
446
|
+
3. Use the redirect URL you specified (or default to localhost)
|
|
447
|
+
4. Start local server on port 3000
|
|
448
|
+
5. Open browser for Instagram authorization
|
|
449
|
+
6. Automatically exchange tokens (short-lived → long-lived)
|
|
450
|
+
7. Fetch your Instagram User ID
|
|
451
|
+
8. Save ALL credentials to .auth/YOUR_UPLOAD_NAME.json
|
|
452
|
+
|
|
453
|
+
Done! Your credentials are saved locally.
|
|
454
|
+
|
|
455
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
456
|
+
TOKEN REFRESH (Every 60 Days)
|
|
457
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
458
|
+
Tokens expire after 60 days. To refresh:
|
|
459
|
+
|
|
460
|
+
curl -X GET "https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=YOUR_CURRENT_TOKEN"
|
|
461
|
+
|
|
462
|
+
💡 Set a calendar reminder for 50 days!
|
|
463
|
+
|
|
464
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
465
|
+
TROUBLESHOOTING
|
|
466
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
467
|
+
❌ "redirect_uri_mismatch"
|
|
468
|
+
→ Meta doesn't accept localhost - use ngrok/Cloudflare
|
|
469
|
+
→ Make sure redirect URI in Meta matches redirectUri in code
|
|
470
|
+
→ Check for typos (no trailing slash!)
|
|
471
|
+
→ If using ngrok, domain changes on restart - update everywhere!
|
|
472
|
+
|
|
473
|
+
❌ "Can't find the wizard or Customize button"
|
|
474
|
+
→ Dashboard → Use Cases → "Manage messaging & content on Instagram"
|
|
475
|
+
→ If you don't see "Customize", your app might not have the right use case
|
|
476
|
+
|
|
477
|
+
❌ "Insufficient permissions" error
|
|
478
|
+
→ Make sure you completed Step 5 (Add required permissions)
|
|
479
|
+
→ Enable: instagram_business_basic, instagram_business_content_publish
|
|
480
|
+
|
|
481
|
+
❌ "Invalid access token"
|
|
482
|
+
→ Token might be expired (60 days max)
|
|
483
|
+
→ Re-run: staticstripes auth --upload-name YOUR_UPLOAD_NAME
|
|
484
|
+
|
|
485
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
486
|
+
REFERENCE LINKS
|
|
487
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
488
|
+
• Facebook Apps Dashboard:
|
|
489
|
+
https://developers.facebook.com/apps/
|
|
490
|
+
|
|
491
|
+
• Instagram Graph API docs:
|
|
492
|
+
https://developers.facebook.com/docs/instagram-api/
|
|
493
|
+
|
|
494
|
+
• ngrok download:
|
|
495
|
+
https://ngrok.com/download
|
|
496
|
+
|
|
497
|
+
• Cloudflare Tunnel:
|
|
498
|
+
https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/
|
|
499
|
+
|
|
500
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
501
|
+
`;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
exports.InstagramAuthStrategy = InstagramAuthStrategy;
|
|
505
|
+
//# sourceMappingURL=instagram-auth-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instagram-auth-strategy.js","sourceRoot":"","sources":["../../../src/cli/instagram/instagram-auth-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { UploadStrategy } from '../upload-strategy';
|
|
2
|
+
import { Project } from '../../project';
|
|
3
|
+
import { Upload } from '../../type';
|
|
4
|
+
/**
|
|
5
|
+
* Instagram upload strategy implementation
|
|
6
|
+
* Uses Instagram Graph API to post Reels/Videos
|
|
7
|
+
*/
|
|
8
|
+
export declare class InstagramUploadStrategy implements UploadStrategy {
|
|
9
|
+
private readonly API_VERSION;
|
|
10
|
+
private readonly GRAPH_API_BASE;
|
|
11
|
+
constructor();
|
|
12
|
+
getTag(): string;
|
|
13
|
+
validate(): void;
|
|
14
|
+
execute(project: Project, upload: Upload, projectPath: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a media container for the Reel
|
|
17
|
+
*/
|
|
18
|
+
private createMediaContainer;
|
|
19
|
+
/**
|
|
20
|
+
* Waits for the container to be ready for publishing
|
|
21
|
+
* Polls the status endpoint until status_code is FINISHED
|
|
22
|
+
*/
|
|
23
|
+
private waitForContainerReady;
|
|
24
|
+
/**
|
|
25
|
+
* Publishes the media container
|
|
26
|
+
*/
|
|
27
|
+
private publishMedia;
|
|
28
|
+
/**
|
|
29
|
+
* Finds a corresponding S3 upload for the same output
|
|
30
|
+
*/
|
|
31
|
+
private findS3Upload;
|
|
32
|
+
/**
|
|
33
|
+
* Constructs the public S3 URL for a video
|
|
34
|
+
*/
|
|
35
|
+
private constructS3Url;
|
|
36
|
+
/**
|
|
37
|
+
* Converts a string to a URL-friendly slug
|
|
38
|
+
*/
|
|
39
|
+
private slugify;
|
|
40
|
+
/**
|
|
41
|
+
* Gets the permalink (URL) for the published media
|
|
42
|
+
*/
|
|
43
|
+
private getPermalink;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=instagram-upload-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instagram-upload-strategy.d.ts","sourceRoot":"","sources":["../../../src/cli/instagram/instagram-upload-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAcpC;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAC5D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiC;;IAIhE,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,IAAI;IAIV,OAAO,CACX,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IA2HhB;;OAEG;YACW,oBAAoB;IAsDlC;;;OAGG;YACW,qBAAqB;IAiDnC;;OAEG;YACW,YAAY;IAgC1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAcpB;;OAEG;IACH,OAAO,CAAC,cAAc;IA0BtB;;OAEG;IACH,OAAO,CAAC,OAAO;IAYf;;OAEG;YACW,YAAY;CA2B3B"}
|