postemi 1.0.0 → 1.0.1
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 +37 -5
- package/dist/index.js +50 -307
- package/dist/index.js.map +1 -1
- package/package.json +18 -6
package/dist/index.js
CHANGED
|
@@ -60,32 +60,12 @@ var import_helpers = require("yargs/helpers");
|
|
|
60
60
|
var import_crypto = require("crypto");
|
|
61
61
|
|
|
62
62
|
// src/brand.ts
|
|
63
|
-
var
|
|
64
|
-
var IS_POSTEMI = BRAND_ID === "postemi";
|
|
65
|
-
var POSTY = {
|
|
66
|
-
name: "Posty",
|
|
67
|
-
cli: "posty",
|
|
68
|
-
envPrefix: "POSTY",
|
|
69
|
-
configDirName: ".posty",
|
|
70
|
-
defaultApiUrl: "https://posty.hu/api",
|
|
71
|
-
defaultAuthServer: "https://posty.hu/api",
|
|
72
|
-
clientName: "Posty CLI",
|
|
73
|
-
homepage: "https://posty.hu",
|
|
74
|
-
termsUrl: "https://posty.hu/aszf",
|
|
75
|
-
privacyUrl: "https://posty.hu/adatvedelem",
|
|
76
|
-
signupUrl: "https://posty.hu/regisztracio",
|
|
77
|
-
exampleTimezone: "Europe/Budapest",
|
|
78
|
-
exampleTimezoneCity: "Budapest",
|
|
79
|
-
tierList: "alap, pro, kreator or csapat",
|
|
80
|
-
basicPlanName: "Alap"
|
|
81
|
-
};
|
|
82
|
-
var POSTEMI = {
|
|
63
|
+
var BRAND = {
|
|
83
64
|
name: "Postemi",
|
|
84
65
|
cli: "postemi",
|
|
85
66
|
envPrefix: "POSTEMI",
|
|
86
67
|
configDirName: ".postemi",
|
|
87
|
-
// api.postemi.com serves the API at the root (its proxy adds /api)
|
|
88
|
-
// same way api.posty.hu does.
|
|
68
|
+
// api.postemi.com serves the API at the root (its proxy adds /api).
|
|
89
69
|
defaultApiUrl: "https://api.postemi.com",
|
|
90
70
|
defaultAuthServer: "https://api.postemi.com",
|
|
91
71
|
clientName: "Postemi CLI",
|
|
@@ -98,30 +78,20 @@ var POSTEMI = {
|
|
|
98
78
|
tierList: "basic, pro, creator or team",
|
|
99
79
|
basicPlanName: "Basic"
|
|
100
80
|
};
|
|
101
|
-
var BRAND = IS_POSTEMI ? POSTEMI : POSTY;
|
|
102
81
|
var envName = (name) => `${BRAND.envPrefix}_${name}`;
|
|
103
82
|
function readEnv(name) {
|
|
104
|
-
|
|
105
|
-
if (own || !IS_POSTEMI) return own;
|
|
106
|
-
return process.env[`POSTY_${name}`];
|
|
107
|
-
}
|
|
108
|
-
function envSourceName(name) {
|
|
109
|
-
if (IS_POSTEMI && !process.env[envName(name)] && process.env[`POSTY_${name}`]) {
|
|
110
|
-
return `POSTY_${name}`;
|
|
111
|
-
}
|
|
112
|
-
return envName(name);
|
|
83
|
+
return process.env[envName(name)];
|
|
113
84
|
}
|
|
114
85
|
function writeEnv(name, value) {
|
|
115
86
|
process.env[envName(name)] = value;
|
|
116
87
|
}
|
|
117
|
-
var
|
|
88
|
+
var TIER_ALIASES = {
|
|
118
89
|
basic: "alap",
|
|
119
90
|
team: "csapat"
|
|
120
91
|
};
|
|
121
92
|
function tierForApi(tier) {
|
|
122
93
|
var _a;
|
|
123
|
-
|
|
124
|
-
return (_a = POSTEMI_TIER_ALIASES[tier.trim().toLowerCase()]) != null ? _a : tier;
|
|
94
|
+
return (_a = TIER_ALIASES[tier.trim().toLowerCase()]) != null ? _a : tier;
|
|
125
95
|
}
|
|
126
96
|
var NETWORK_REASONS = {
|
|
127
97
|
ENOTFOUND: "the host name does not resolve",
|
|
@@ -136,7 +106,6 @@ var NETWORK_REASONS = {
|
|
|
136
106
|
function networkError(prefix, error, variable = "API_URL") {
|
|
137
107
|
var _a, _b, _c;
|
|
138
108
|
const plain = `${prefix}: ${error == null ? void 0 : error.message}`;
|
|
139
|
-
if (!IS_POSTEMI) return plain;
|
|
140
109
|
const code = (_b = (_a = error == null ? void 0 : error.cause) == null ? void 0 : _a.code) != null ? _b : error == null ? void 0 : error.code;
|
|
141
110
|
const reason = code ? (_c = NETWORK_REASONS[code]) != null ? _c : code : null;
|
|
142
111
|
return reason ? `${prefix}: ${reason} (${code}). Check the connection, or point ${envName(variable)} at another server.` : plain;
|
|
@@ -227,7 +196,7 @@ var ApiError = class extends Error {
|
|
|
227
196
|
return this.status === 403 && this.body.includes("spans several workspaces");
|
|
228
197
|
}
|
|
229
198
|
};
|
|
230
|
-
var
|
|
199
|
+
var PostemiAPI = class {
|
|
231
200
|
constructor(config) {
|
|
232
201
|
this.apiKey = config.apiKey;
|
|
233
202
|
this.workspaceId = config.workspaceId;
|
|
@@ -449,45 +418,6 @@ var PostyAPI = class {
|
|
|
449
418
|
method: "GET"
|
|
450
419
|
});
|
|
451
420
|
}
|
|
452
|
-
/*
|
|
453
|
-
FOTOAI (fotoai.hu). Generation with the key owner's OWN FotoAI account and
|
|
454
|
-
credits; the outputs are saved into this workspace's media library. A key
|
|
455
|
-
whose owner has not connected FotoAI gets 409 FOTOAI_NOT_CONNECTED with
|
|
456
|
-
`details.connect_url`, the page the person opens once. Needs media:write.
|
|
457
|
-
*/
|
|
458
|
-
async fotoAiStatus() {
|
|
459
|
-
return this.request("/public/v1/fotoai/status", { method: "GET" });
|
|
460
|
-
}
|
|
461
|
-
async fotoAiModels(category) {
|
|
462
|
-
const query = category ? `?category=${encodeURIComponent(category)}` : "";
|
|
463
|
-
return this.request(`/public/v1/fotoai/models${query}`, { method: "GET" });
|
|
464
|
-
}
|
|
465
|
-
/** Spends nothing: the price, the balance and a quote_id valid 10 minutes. */
|
|
466
|
-
async fotoAiQuote(body) {
|
|
467
|
-
return this.request("/public/v1/fotoai/quote", {
|
|
468
|
-
method: "POST",
|
|
469
|
-
body: JSON.stringify(body)
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
/** SPENDS the key owner's FotoAI credits, at most the quoted price. */
|
|
473
|
-
async fotoAiGenerate(body) {
|
|
474
|
-
return this.request("/public/v1/fotoai/generations", {
|
|
475
|
-
method: "POST",
|
|
476
|
-
body: JSON.stringify(body)
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
async fotoAiGeneration(id) {
|
|
480
|
-
return this.request(`/public/v1/fotoai/generations/${encodeURIComponent(id)}`, {
|
|
481
|
-
method: "GET"
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
/** Imports any FotoAI generation of the key owner into the media library; repeatable. */
|
|
485
|
-
async fotoAiImport(id) {
|
|
486
|
-
return this.request(
|
|
487
|
-
`/public/v1/fotoai/generations/${encodeURIComponent(id)}/import`,
|
|
488
|
-
{ method: "POST" }
|
|
489
|
-
);
|
|
490
|
-
}
|
|
491
421
|
};
|
|
492
422
|
|
|
493
423
|
// src/commands/auth.ts
|
|
@@ -600,14 +530,14 @@ function resolveTimezone(flagValue) {
|
|
|
600
530
|
if (env) {
|
|
601
531
|
return {
|
|
602
532
|
name: assertIanaTimezone(env, envName("TIMEZONE")),
|
|
603
|
-
source:
|
|
533
|
+
source: "POSTEMI_TIMEZONE"
|
|
604
534
|
};
|
|
605
535
|
}
|
|
606
536
|
const stored = getSetting("timezone");
|
|
607
537
|
if (stored) {
|
|
608
538
|
return {
|
|
609
539
|
name: assertIanaTimezone(stored, `~/${BRAND.configDirName}/config.json`),
|
|
610
|
-
source:
|
|
540
|
+
source: "config (postemi config:set timezone)"
|
|
611
541
|
};
|
|
612
542
|
}
|
|
613
543
|
return null;
|
|
@@ -777,7 +707,7 @@ Scheduling timezone: ${detected} \u2014 OK? [Y/n] `)).trim().toLowerCase();
|
|
|
777
707
|
async function chooseWorkspace(creds) {
|
|
778
708
|
let workspaces;
|
|
779
709
|
try {
|
|
780
|
-
workspaces = await new
|
|
710
|
+
workspaces = await new PostemiAPI({
|
|
781
711
|
apiKey: creds.accessToken,
|
|
782
712
|
apiUrl: creds.apiUrl
|
|
783
713
|
}).listWorkspaces();
|
|
@@ -822,9 +752,11 @@ async function authLogin(argv) {
|
|
|
822
752
|
headers: { "Content-Type": "application/json" },
|
|
823
753
|
// Shown on the approval page, so somebody can tell the login they just
|
|
824
754
|
// started from one they did not.
|
|
825
|
-
body: JSON.stringify(
|
|
826
|
-
client_name: readEnv("CLIENT_NAME") || BRAND.clientName
|
|
827
|
-
|
|
755
|
+
body: JSON.stringify({
|
|
756
|
+
client_name: readEnv("CLIENT_NAME") || BRAND.clientName,
|
|
757
|
+
// Asks for Postemi's approval page (postemi.com/app/device).
|
|
758
|
+
brand: "postemi"
|
|
759
|
+
})
|
|
828
760
|
});
|
|
829
761
|
if (!response.ok) {
|
|
830
762
|
const error = await response.text();
|
|
@@ -865,12 +797,11 @@ async function authLogin(argv) {
|
|
|
865
797
|
const creds = {
|
|
866
798
|
accessToken: data.access_token,
|
|
867
799
|
/*
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
makes the API answer as Postemi.
|
|
800
|
+
The host the login ran on (api.postemi.com), not the `api_url` in
|
|
801
|
+
the token response: the Postemi host is what makes the API answer
|
|
802
|
+
as Postemi.
|
|
872
803
|
*/
|
|
873
|
-
apiUrl:
|
|
804
|
+
apiUrl: String(authServer).replace(/\/+$/, ""),
|
|
874
805
|
organizationId: data.organization_id
|
|
875
806
|
};
|
|
876
807
|
saveCredentials(creds);
|
|
@@ -1095,7 +1026,7 @@ async function authStatus() {
|
|
|
1095
1026
|
source = "environment";
|
|
1096
1027
|
apiKey = envKey;
|
|
1097
1028
|
apiUrl = readEnv("API_URL") || DEFAULT_API_URL;
|
|
1098
|
-
status(`\u{1F511} Authentication method: ${label(method)} (${
|
|
1029
|
+
status(`\u{1F511} Authentication method: ${label(method)} (${envName("API_KEY")})`);
|
|
1099
1030
|
status(`\u{1F511} Credential: ${hint(envKey)}`);
|
|
1100
1031
|
} else {
|
|
1101
1032
|
status("\u274C Not authenticated.");
|
|
@@ -1113,7 +1044,7 @@ async function authStatus() {
|
|
|
1113
1044
|
const base = { method, source, apiUrl, workspace: workspaceId != null ? workspaceId : null };
|
|
1114
1045
|
let subscription;
|
|
1115
1046
|
try {
|
|
1116
|
-
subscription = await new
|
|
1047
|
+
subscription = await new PostemiAPI({
|
|
1117
1048
|
apiKey,
|
|
1118
1049
|
apiUrl,
|
|
1119
1050
|
workspaceId
|
|
@@ -1163,7 +1094,7 @@ async function authStatus() {
|
|
|
1163
1094
|
}
|
|
1164
1095
|
let integrations = null;
|
|
1165
1096
|
try {
|
|
1166
|
-
const list = await new
|
|
1097
|
+
const list = await new PostemiAPI({
|
|
1167
1098
|
apiKey,
|
|
1168
1099
|
apiUrl,
|
|
1169
1100
|
workspaceId
|
|
@@ -1270,7 +1201,7 @@ function echoInterpretation(input, resolved) {
|
|
|
1270
1201
|
}
|
|
1271
1202
|
async function getMissingContent(args) {
|
|
1272
1203
|
const config = getConfig();
|
|
1273
|
-
const api = new
|
|
1204
|
+
const api = new PostemiAPI(config);
|
|
1274
1205
|
try {
|
|
1275
1206
|
const res = await api.getMissingContent(args.id);
|
|
1276
1207
|
result(res);
|
|
@@ -1281,7 +1212,7 @@ async function getMissingContent(args) {
|
|
|
1281
1212
|
}
|
|
1282
1213
|
async function connectPost(args) {
|
|
1283
1214
|
const config = getConfig();
|
|
1284
|
-
const api = new
|
|
1215
|
+
const api = new PostemiAPI(config);
|
|
1285
1216
|
try {
|
|
1286
1217
|
const res = await api.updateReleaseId(args.id, args.releaseId);
|
|
1287
1218
|
status(`\u2705 Post ${args.id} connected to release ${args.releaseId}`);
|
|
@@ -1293,7 +1224,7 @@ async function connectPost(args) {
|
|
|
1293
1224
|
}
|
|
1294
1225
|
async function findSlot(args) {
|
|
1295
1226
|
const config = getConfig();
|
|
1296
|
-
const api = new
|
|
1227
|
+
const api = new PostemiAPI(config);
|
|
1297
1228
|
try {
|
|
1298
1229
|
const res = await api.findSlot(args.id);
|
|
1299
1230
|
result(res);
|
|
@@ -1304,7 +1235,7 @@ async function findSlot(args) {
|
|
|
1304
1235
|
}
|
|
1305
1236
|
async function createPost(args) {
|
|
1306
1237
|
const config = getConfig();
|
|
1307
|
-
const api = new
|
|
1238
|
+
const api = new PostemiAPI(config);
|
|
1308
1239
|
let postData;
|
|
1309
1240
|
if (args.json) {
|
|
1310
1241
|
try {
|
|
@@ -1401,7 +1332,7 @@ async function createPost(args) {
|
|
|
1401
1332
|
}
|
|
1402
1333
|
async function listPosts(args) {
|
|
1403
1334
|
const config = getConfig();
|
|
1404
|
-
const api = new
|
|
1335
|
+
const api = new PostemiAPI(config);
|
|
1405
1336
|
const defaultStartDate = /* @__PURE__ */ new Date();
|
|
1406
1337
|
defaultStartDate.setDate(defaultStartDate.getDate() - 30);
|
|
1407
1338
|
const defaultEndDate = /* @__PURE__ */ new Date();
|
|
@@ -1435,7 +1366,7 @@ async function listPosts(args) {
|
|
|
1435
1366
|
}
|
|
1436
1367
|
async function changePostStatus(args) {
|
|
1437
1368
|
const config = getConfig();
|
|
1438
|
-
const api = new
|
|
1369
|
+
const api = new PostemiAPI(config);
|
|
1439
1370
|
try {
|
|
1440
1371
|
const res = await api.changePostStatus(args.id, args.status);
|
|
1441
1372
|
status(`\u2705 Post ${args.id} status changed to ${args.status}`);
|
|
@@ -1447,7 +1378,7 @@ async function changePostStatus(args) {
|
|
|
1447
1378
|
}
|
|
1448
1379
|
async function deletePost(args) {
|
|
1449
1380
|
const config = getConfig();
|
|
1450
|
-
const api = new
|
|
1381
|
+
const api = new PostemiAPI(config);
|
|
1451
1382
|
try {
|
|
1452
1383
|
const res = await api.deletePost(args.id);
|
|
1453
1384
|
status(`\u2705 Post ${args.id} deleted successfully!`);
|
|
@@ -1459,7 +1390,7 @@ async function deletePost(args) {
|
|
|
1459
1390
|
}
|
|
1460
1391
|
async function deletePostGroup(args) {
|
|
1461
1392
|
const config = getConfig();
|
|
1462
|
-
const api = new
|
|
1393
|
+
const api = new PostemiAPI(config);
|
|
1463
1394
|
try {
|
|
1464
1395
|
const res = await api.deletePostGroup(args.group);
|
|
1465
1396
|
status(`\u2705 Post group ${args.group} deleted from every channel`);
|
|
@@ -1473,7 +1404,7 @@ async function deletePostGroup(args) {
|
|
|
1473
1404
|
// src/commands/integrations.ts
|
|
1474
1405
|
async function listIntegrations(args) {
|
|
1475
1406
|
const config = getConfig();
|
|
1476
|
-
const api = new
|
|
1407
|
+
const api = new PostemiAPI(config);
|
|
1477
1408
|
try {
|
|
1478
1409
|
const res = await api.listIntegrations(args == null ? void 0 : args.group);
|
|
1479
1410
|
result(res);
|
|
@@ -1484,7 +1415,7 @@ async function listIntegrations(args) {
|
|
|
1484
1415
|
}
|
|
1485
1416
|
async function listGroups() {
|
|
1486
1417
|
const config = getConfig();
|
|
1487
|
-
const api = new
|
|
1418
|
+
const api = new PostemiAPI(config);
|
|
1488
1419
|
try {
|
|
1489
1420
|
const res = await api.listGroups();
|
|
1490
1421
|
result(res);
|
|
@@ -1495,7 +1426,7 @@ async function listGroups() {
|
|
|
1495
1426
|
}
|
|
1496
1427
|
async function getIntegrationSettings(args) {
|
|
1497
1428
|
const config = getConfig();
|
|
1498
|
-
const api = new
|
|
1429
|
+
const api = new PostemiAPI(config);
|
|
1499
1430
|
try {
|
|
1500
1431
|
const res = await api.getIntegrationSettings(args.id);
|
|
1501
1432
|
result(res);
|
|
@@ -1506,7 +1437,7 @@ async function getIntegrationSettings(args) {
|
|
|
1506
1437
|
}
|
|
1507
1438
|
async function triggerIntegrationTool(args) {
|
|
1508
1439
|
const config = getConfig();
|
|
1509
|
-
const api = new
|
|
1440
|
+
const api = new PostemiAPI(config);
|
|
1510
1441
|
let data = {};
|
|
1511
1442
|
if (args.data) {
|
|
1512
1443
|
try {
|
|
@@ -1537,7 +1468,7 @@ function daysArg(args) {
|
|
|
1537
1468
|
}
|
|
1538
1469
|
async function getAnalytics(args) {
|
|
1539
1470
|
const config = getConfig();
|
|
1540
|
-
const api = new
|
|
1471
|
+
const api = new PostemiAPI(config);
|
|
1541
1472
|
try {
|
|
1542
1473
|
const res = await api.getAnalytics(args.id, daysArg(args));
|
|
1543
1474
|
result(res);
|
|
@@ -1548,7 +1479,7 @@ async function getAnalytics(args) {
|
|
|
1548
1479
|
}
|
|
1549
1480
|
async function getPostAnalytics(args) {
|
|
1550
1481
|
const config = getConfig();
|
|
1551
|
-
const api = new
|
|
1482
|
+
const api = new PostemiAPI(config);
|
|
1552
1483
|
try {
|
|
1553
1484
|
const res = await api.getPostAnalytics(args.id, daysArg(args));
|
|
1554
1485
|
result(res);
|
|
@@ -1563,7 +1494,7 @@ var import_fs4 = require("fs");
|
|
|
1563
1494
|
var import_path3 = require("path");
|
|
1564
1495
|
async function uploadFile(args) {
|
|
1565
1496
|
const config = getConfig();
|
|
1566
|
-
const api = new
|
|
1497
|
+
const api = new PostemiAPI(config);
|
|
1567
1498
|
if (!(0, import_fs4.existsSync)(args.file)) {
|
|
1568
1499
|
console.error(`\u274C File not found: ${args.file}`);
|
|
1569
1500
|
process.exit(1);
|
|
@@ -1581,7 +1512,7 @@ async function uploadFile(args) {
|
|
|
1581
1512
|
}
|
|
1582
1513
|
async function createUploadLink() {
|
|
1583
1514
|
const config = getConfig();
|
|
1584
|
-
const api = new
|
|
1515
|
+
const api = new PostemiAPI(config);
|
|
1585
1516
|
try {
|
|
1586
1517
|
const res = await api.createUploadLink();
|
|
1587
1518
|
status(
|
|
@@ -1595,7 +1526,7 @@ async function createUploadLink() {
|
|
|
1595
1526
|
}
|
|
1596
1527
|
async function listUploadLinkFiles(args) {
|
|
1597
1528
|
const config = getConfig();
|
|
1598
|
-
const api = new
|
|
1529
|
+
const api = new PostemiAPI(config);
|
|
1599
1530
|
try {
|
|
1600
1531
|
const res = await api.getUploadLinkFiles(args.id);
|
|
1601
1532
|
if (res.status === "empty") {
|
|
@@ -1648,7 +1579,7 @@ async function configGet(args) {
|
|
|
1648
1579
|
|
|
1649
1580
|
// src/commands/workspaces.ts
|
|
1650
1581
|
async function listWorkspaces() {
|
|
1651
|
-
const api = new
|
|
1582
|
+
const api = new PostemiAPI(getConfig());
|
|
1652
1583
|
try {
|
|
1653
1584
|
const res = await api.listWorkspaces();
|
|
1654
1585
|
result(res);
|
|
@@ -1662,7 +1593,7 @@ async function useWorkspace(args) {
|
|
|
1662
1593
|
if (!id) {
|
|
1663
1594
|
fail("Failed to select workspace", new Error(`Give the workspace id, from "${BRAND.cli} workspaces:list"`));
|
|
1664
1595
|
}
|
|
1665
|
-
const api = new
|
|
1596
|
+
const api = new PostemiAPI(__spreadProps(__spreadValues({}, getConfig()), { workspaceId: void 0 }));
|
|
1666
1597
|
let workspaces;
|
|
1667
1598
|
try {
|
|
1668
1599
|
workspaces = await api.listWorkspaces();
|
|
@@ -1690,7 +1621,7 @@ async function useWorkspace(args) {
|
|
|
1690
1621
|
}
|
|
1691
1622
|
async function currentWorkspace() {
|
|
1692
1623
|
const id = getWorkspaceId();
|
|
1693
|
-
const api = new
|
|
1624
|
+
const api = new PostemiAPI(getConfig());
|
|
1694
1625
|
try {
|
|
1695
1626
|
const workspaces = await api.listWorkspaces();
|
|
1696
1627
|
const current = workspaces.find((w) => w.current) || null;
|
|
@@ -1707,7 +1638,7 @@ async function currentWorkspace() {
|
|
|
1707
1638
|
|
|
1708
1639
|
// src/commands/billing.ts
|
|
1709
1640
|
async function billingPlans() {
|
|
1710
|
-
const api = new
|
|
1641
|
+
const api = new PostemiAPI(getConfig());
|
|
1711
1642
|
try {
|
|
1712
1643
|
result(await api.getPlans());
|
|
1713
1644
|
} catch (error) {
|
|
@@ -1729,7 +1660,7 @@ async function billingSubscribe(args) {
|
|
|
1729
1660
|
new Error("Give the period with --period monthly or --period yearly")
|
|
1730
1661
|
);
|
|
1731
1662
|
}
|
|
1732
|
-
const api = new
|
|
1663
|
+
const api = new PostemiAPI(getConfig());
|
|
1733
1664
|
try {
|
|
1734
1665
|
const checkout = await api.createSubscriptionCheckout(tierForApi(tier), period);
|
|
1735
1666
|
status(
|
|
@@ -1754,7 +1685,7 @@ async function billingSubscribe(args) {
|
|
|
1754
1685
|
}
|
|
1755
1686
|
}
|
|
1756
1687
|
async function billingStatus() {
|
|
1757
|
-
const api = new
|
|
1688
|
+
const api = new PostemiAPI(getConfig());
|
|
1758
1689
|
try {
|
|
1759
1690
|
const subscription = await api.getSubscription();
|
|
1760
1691
|
if (subscription.pendingCheckout) {
|
|
@@ -1770,7 +1701,7 @@ async function billingStatus() {
|
|
|
1770
1701
|
}
|
|
1771
1702
|
}
|
|
1772
1703
|
async function billingManage(args) {
|
|
1773
|
-
const api = new
|
|
1704
|
+
const api = new PostemiAPI(getConfig());
|
|
1774
1705
|
try {
|
|
1775
1706
|
const portal = await api.getSubscriptionPortal();
|
|
1776
1707
|
const _a = portal, { note } = _a, json = __objRest(_a, ["note"]);
|
|
@@ -1785,162 +1716,8 @@ async function billingManage(args) {
|
|
|
1785
1716
|
}
|
|
1786
1717
|
}
|
|
1787
1718
|
|
|
1788
|
-
// src/commands/fotoai.ts
|
|
1789
|
-
var import_crypto2 = require("crypto");
|
|
1790
|
-
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1791
|
-
var failFotoAi = (context, error) => {
|
|
1792
|
-
if (error instanceof ApiError) {
|
|
1793
|
-
let body = null;
|
|
1794
|
-
try {
|
|
1795
|
-
body = JSON.parse(error.body);
|
|
1796
|
-
} catch (e) {
|
|
1797
|
-
}
|
|
1798
|
-
if (error.status === 404 && !(body == null ? void 0 : body.code)) {
|
|
1799
|
-
status("\u274C FotoAI is not available on this Posty server yet.");
|
|
1800
|
-
process.exit(1);
|
|
1801
|
-
}
|
|
1802
|
-
if (body == null ? void 0 : body.code) {
|
|
1803
|
-
const details = body.details || {};
|
|
1804
|
-
status(`\u274C ${context}: ${body.msg || body.code} (${body.code})`);
|
|
1805
|
-
if (details.connect_url) {
|
|
1806
|
-
status(`Connect FotoAI in Posty once: ${details.connect_url}`);
|
|
1807
|
-
}
|
|
1808
|
-
if (details.topup_url) {
|
|
1809
|
-
status(`FotoAI credits can be bought at ${details.topup_url}`);
|
|
1810
|
-
}
|
|
1811
|
-
if (typeof details.quote === "number") {
|
|
1812
|
-
status(`The new price is ${details.quote / 1e3} credits. Quote again and confirm it.`);
|
|
1813
|
-
}
|
|
1814
|
-
if (body.retryAfter) {
|
|
1815
|
-
status(`Try again in ${body.retryAfter} seconds.`);
|
|
1816
|
-
}
|
|
1817
|
-
process.exit(1);
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
fail(context, error);
|
|
1821
|
-
};
|
|
1822
|
-
var paramsOf = (args) => {
|
|
1823
|
-
const params = {};
|
|
1824
|
-
if (args.aspect) params.aspect = String(args.aspect);
|
|
1825
|
-
if (args.duration) params.duration = Number(args.duration);
|
|
1826
|
-
if (args.resolution) params.resolution = String(args.resolution);
|
|
1827
|
-
return params;
|
|
1828
|
-
};
|
|
1829
|
-
async function fotoAiStatus() {
|
|
1830
|
-
const api = new PostyAPI(getConfig());
|
|
1831
|
-
try {
|
|
1832
|
-
const current = await api.fotoAiStatus();
|
|
1833
|
-
if (!current.connected) {
|
|
1834
|
-
status(
|
|
1835
|
-
current.needsReconnect ? `The FotoAI connection has expired. Connect again in Posty: ${current.connectUrl}` : `FotoAI is not connected. The person connects it once in Posty: ${current.connectUrl}`
|
|
1836
|
-
);
|
|
1837
|
-
}
|
|
1838
|
-
result(current);
|
|
1839
|
-
} catch (error) {
|
|
1840
|
-
failFotoAi("Failed to read the FotoAI status", error);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
async function fotoAiModels(args) {
|
|
1844
|
-
const api = new PostyAPI(getConfig());
|
|
1845
|
-
try {
|
|
1846
|
-
const catalog = await api.fotoAiModels(args.category);
|
|
1847
|
-
const models = (catalog.models || []).map((m) => {
|
|
1848
|
-
var _a, _b;
|
|
1849
|
-
return {
|
|
1850
|
-
id: m.id,
|
|
1851
|
-
name: m.name,
|
|
1852
|
-
category: m.category,
|
|
1853
|
-
can_use: !!m.can_use,
|
|
1854
|
-
estimated_seconds: (_a = m.estimated_seconds) != null ? _a : null,
|
|
1855
|
-
max_duration_seconds: (_b = m.max_duration_seconds) != null ? _b : null,
|
|
1856
|
-
base_price_credits: (() => {
|
|
1857
|
-
var _a2;
|
|
1858
|
-
const prices = (((_a2 = m.price) == null ? void 0 : _a2.configs) || []).map((c) => Number(c.millicredits)).filter((n) => Number.isFinite(n) && n > 0);
|
|
1859
|
-
return prices.length ? Math.min(...prices) / 1e3 : null;
|
|
1860
|
-
})(),
|
|
1861
|
-
params: (m.params || []).map((p) => {
|
|
1862
|
-
var _a2;
|
|
1863
|
-
return {
|
|
1864
|
-
key: p.key,
|
|
1865
|
-
default: (_a2 = p.default) != null ? _a2 : null,
|
|
1866
|
-
options: (p.options || []).map((o) => o.value)
|
|
1867
|
-
};
|
|
1868
|
-
})
|
|
1869
|
-
};
|
|
1870
|
-
});
|
|
1871
|
-
result({ catalog_version: catalog.catalog_version || null, models });
|
|
1872
|
-
} catch (error) {
|
|
1873
|
-
failFotoAi("Failed to list the FotoAI models", error);
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1876
|
-
async function fotoAiGet(args) {
|
|
1877
|
-
var _a, _b;
|
|
1878
|
-
const api = new PostyAPI(getConfig());
|
|
1879
|
-
const deadline = Date.now() + Math.max(0, Number(args.wait) || 0) * 1e3;
|
|
1880
|
-
try {
|
|
1881
|
-
let current = await api.fotoAiImport(String(args.id));
|
|
1882
|
-
while ((["queued", "running"].includes(current.status) || current.status === "completed" && !((_a = current.media) == null ? void 0 : _a.length) && !current.import_error) && Date.now() < deadline) {
|
|
1883
|
-
await sleep2(3e3);
|
|
1884
|
-
current = await api.fotoAiImport(String(args.id));
|
|
1885
|
-
}
|
|
1886
|
-
if ((_b = current.media) == null ? void 0 : _b.length) {
|
|
1887
|
-
status(`Saved in the media library. Attach each media[].path with posts:create.`);
|
|
1888
|
-
} else if (["queued", "running"].includes(current.status)) {
|
|
1889
|
-
status(`Still ${current.status}. Run "${BRAND.cli} fotoai:get ${current.id} --wait 60" again.`);
|
|
1890
|
-
}
|
|
1891
|
-
result(current);
|
|
1892
|
-
} catch (error) {
|
|
1893
|
-
failFotoAi("Failed to read the FotoAI generation", error);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
async function fotoAiGenerate(args) {
|
|
1897
|
-
var _a;
|
|
1898
|
-
const api = new PostyAPI(getConfig());
|
|
1899
|
-
const request = {
|
|
1900
|
-
model: String(args.model),
|
|
1901
|
-
prompt: String(args.prompt),
|
|
1902
|
-
params: paramsOf(args)
|
|
1903
|
-
};
|
|
1904
|
-
let quote;
|
|
1905
|
-
try {
|
|
1906
|
-
quote = await api.fotoAiQuote(request);
|
|
1907
|
-
} catch (error) {
|
|
1908
|
-
failFotoAi("Failed to price the FotoAI generation", error);
|
|
1909
|
-
}
|
|
1910
|
-
const balance = typeof quote.available_millicredits === "number" ? `, balance ${quote.available_millicredits / 1e3} credits` : "";
|
|
1911
|
-
if (quote.insufficient) {
|
|
1912
|
-
status(
|
|
1913
|
-
`Not enough FotoAI credits: this costs ${quote.credits} credits${balance}.${quote.topup_url ? ` Buy credits at ${quote.topup_url}` : ""}`
|
|
1914
|
-
);
|
|
1915
|
-
result({ generated: false, quote });
|
|
1916
|
-
process.exit(1);
|
|
1917
|
-
}
|
|
1918
|
-
if (!args.yes) {
|
|
1919
|
-
status(
|
|
1920
|
-
`This costs ${quote.credits} FotoAI credits${balance}. Nothing was spent. Run the same command with --yes to generate.`
|
|
1921
|
-
);
|
|
1922
|
-
result({ generated: false, quote });
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
try {
|
|
1926
|
-
const started = await api.fotoAiGenerate(__spreadProps(__spreadValues({}, request), {
|
|
1927
|
-
quote_id: quote.quote_id,
|
|
1928
|
-
idempotency_key: args.idempotencyKey || (0, import_crypto2.randomUUID)()
|
|
1929
|
-
}));
|
|
1930
|
-
status(`Generating (about ${(_a = started.estimated_seconds) != null ? _a : "?"} seconds), id ${started.id}.`);
|
|
1931
|
-
if (!Number(args.wait)) {
|
|
1932
|
-
status(`Run "${BRAND.cli} fotoai:get ${started.id} --wait 60" for the media paths.`);
|
|
1933
|
-
result(started);
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
await fotoAiGet({ id: started.id, wait: args.wait });
|
|
1937
|
-
} catch (error) {
|
|
1938
|
-
failFotoAi("Failed to start the FotoAI generation", error);
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
1719
|
// src/index.ts
|
|
1943
|
-
|
|
1720
|
+
(0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).scriptName(BRAND.cli).usage("$0 <command> [options]").option("workspace", {
|
|
1944
1721
|
alias: "w",
|
|
1945
1722
|
describe: `Workspace id this command acts on (overrides "${BRAND.cli} workspaces:use" and ${envName("WORKSPACE")})`,
|
|
1946
1723
|
type: "string",
|
|
@@ -2299,7 +2076,7 @@ var cli = (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).s
|
|
|
2299
2076
|
currentWorkspace
|
|
2300
2077
|
).command(
|
|
2301
2078
|
"billing:plans",
|
|
2302
|
-
|
|
2079
|
+
"Show the Postemi plans: prices, limits, the trial rule and the current tier",
|
|
2303
2080
|
{},
|
|
2304
2081
|
billingPlans
|
|
2305
2082
|
).command(
|
|
@@ -2344,39 +2121,7 @@ var cli = (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).s
|
|
|
2344
2121
|
});
|
|
2345
2122
|
},
|
|
2346
2123
|
billingManage
|
|
2347
|
-
);
|
|
2348
|
-
if (!IS_POSTEMI) cli.command(
|
|
2349
|
-
"fotoai:status",
|
|
2350
|
-
"Show whether FotoAI (fotoai.hu) is connected for the key owner, as whom, and the FotoAI credit balance",
|
|
2351
|
-
{},
|
|
2352
|
-
fotoAiStatus
|
|
2353
2124
|
).command(
|
|
2354
|
-
"fotoai:models",
|
|
2355
|
-
"List the FotoAI image and video models with their parameters and prices",
|
|
2356
|
-
(yargs2) => {
|
|
2357
|
-
return yargs2.option("category", {
|
|
2358
|
-
describe: "Only image or only video models",
|
|
2359
|
-
type: "string",
|
|
2360
|
-
choices: ["image", "video"]
|
|
2361
|
-
});
|
|
2362
|
-
},
|
|
2363
|
-
fotoAiModels
|
|
2364
|
-
).command(
|
|
2365
|
-
"fotoai:generate",
|
|
2366
|
-
"Price, and with --yes generate, an image or video with the key owner's own FotoAI credits; the result is saved into the media library",
|
|
2367
|
-
(yargs2) => {
|
|
2368
|
-
return yargs2.option("model", { alias: "m", describe: `A model id from "${BRAND.cli} fotoai:models"`, type: "string", demandOption: true }).option("prompt", { alias: "p", describe: "What to generate", type: "string", demandOption: true }).option("aspect", { describe: "Aspect ratio, e.g. 1:1, 4:5, 9:16, 16:9", type: "string" }).option("duration", { describe: "Video length in seconds (video models)", type: "number" }).option("resolution", { describe: "Resolution, when the model offers one (e.g. 2K)", type: "string" }).option("yes", { describe: "Spend the credits. Without it only the price is shown", type: "boolean", default: false }).option("wait", { describe: "Wait up to this many seconds for the result", type: "number", default: 0 }).option("idempotency-key", { describe: "Reuse on a retry so nothing is charged twice", type: "string" }).example('$0 fotoai:generate -m image.seedream-5-lite -p "k\xE1v\xE9 a teraszon" --aspect 4:5', "Show the price only").example('$0 fotoai:generate -m image.seedream-5-lite -p "k\xE1v\xE9 a teraszon" --aspect 4:5 --yes --wait 60', "Generate and print the media paths");
|
|
2369
|
-
},
|
|
2370
|
-
fotoAiGenerate
|
|
2371
|
-
).command(
|
|
2372
|
-
"fotoai:get <id>",
|
|
2373
|
-
"Show a FotoAI generation; once done, its outputs saved into the media library with paths for posts:create",
|
|
2374
|
-
(yargs2) => {
|
|
2375
|
-
return yargs2.positional("id", { describe: "The generation id", type: "string" }).option("wait", { describe: "Wait up to this many seconds while it runs", type: "number", default: 0 });
|
|
2376
|
-
},
|
|
2377
|
-
fotoAiGet
|
|
2378
|
-
);
|
|
2379
|
-
cli.command(
|
|
2380
2125
|
"config:set <key> <value>",
|
|
2381
2126
|
`Save a CLI setting to ~/${BRAND.configDirName}/config.json`,
|
|
2382
2127
|
(yargs2) => {
|
|
@@ -2415,8 +2160,7 @@ cli.command(
|
|
|
2415
2160
|
);
|
|
2416
2161
|
},
|
|
2417
2162
|
authLogin
|
|
2418
|
-
)
|
|
2419
|
-
cli.command(
|
|
2163
|
+
).command(
|
|
2420
2164
|
"auth:signup",
|
|
2421
2165
|
`Create a NEW ${BRAND.name} account with a code sent to the e-mail address, and store its key. No free trial: the next step is billing:subscribe`,
|
|
2422
2166
|
(yargs2) => {
|
|
@@ -2448,13 +2192,12 @@ cli.command(
|
|
|
2448
2192
|
"$0 auth:signup --email anna@example.com",
|
|
2449
2193
|
"Send the code, then ask for it and for the terms on the terminal"
|
|
2450
2194
|
).example(
|
|
2451
|
-
`$0 auth:signup --email anna@example.com --code 123456 --accept-terms --workspace-name "
|
|
2195
|
+
`$0 auth:signup --email anna@example.com --code 123456 --accept-terms --workspace-name "Anna's Cafe"`,
|
|
2452
2196
|
"Finish in one run (an agent, after the person read the code and agreed)"
|
|
2453
2197
|
);
|
|
2454
2198
|
},
|
|
2455
2199
|
authSignup
|
|
2456
|
-
)
|
|
2457
|
-
cli.command(
|
|
2200
|
+
).command(
|
|
2458
2201
|
"auth:logout",
|
|
2459
2202
|
"Remove stored OAuth2 credentials",
|
|
2460
2203
|
{},
|