diff --git a/README.md b/README.md index c94dbcb..e531980 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ but in general, the steps are nano users/foobar/var/lib/storage.json # connect platform `bla` to user `foobar` -./fairpost.js @foobar setup-platform --platform=bla +./fairpost.js @foobar connect-platform --platform=bla ``` @@ -137,7 +137,7 @@ Access and refresh tokens for various platforms may expire sooner or later. Before you do anything, try `fairpost.js @userid refresh-platforms`. Eventually, even refresh tokens may expire, and you will have to run -`fairpost.js @userid setup-platform --platform=bla` again +`fairpost.js @userid connect-platform --platform=bla` again to get a new pair of tokens. @@ -156,7 +156,7 @@ fairpost: @userid get-platform --platform=xxx fairpost: @userid put-platform --platform=xxx << payload fairpost: @userid edit-platform --platform=xxx (cli only) fairpost: @userid get-platforms [--platforms=xxx,xxx] -fairpost: @userid setup-platform --platform=xxx +fairpost: @userid connect-platform --platform=xxx fairpost: @userid test-platform --platform=xxx fairpost: @userid test-platforms [--platforms=xxx,xxx] fairpost: @userid refresh-platform --platform=xxx diff --git a/docs/Facebook.md b/docs/Facebook.md index b54b84f..682919b 100644 --- a/docs/Facebook.md +++ b/docs/Facebook.md @@ -48,7 +48,7 @@ tokens, you can turn on Live mode and start posting. - go to https://developers.facebook.com/ - select your app, edit it - set App Mode to 'dev' -- call `./fairpost.js @userid setup-platform --platform=facebook` +- call `./fairpost.js @userid connect-platform --platform=facebook` - follow instructions from the command line ### Test the platform @@ -81,7 +81,7 @@ One fairpost user can only manage one page. If you create a second user, you can - go to https://developers.facebook.com/ - select your app, edit it - set App Mode to 'dev' -- call `./fairpost.js @foo setup-platform --platform=facebook` +- call `./fairpost.js @foo connect-platform --platform=facebook` - follow instructions from the command line - put your app back in live mode diff --git a/docs/Instagram.md b/docs/Instagram.md index 193a595..27501bf 100644 --- a/docs/Instagram.md +++ b/docs/Instagram.md @@ -59,7 +59,7 @@ tokens, you can turn on Live mode and start posting. - go to https://developers.facebook.com/ - select your app, edit it - set App Mode to 'dev' -- call `./fairpost.js @userid setup-platform --platform=instagram` +- call `./fairpost.js @userid connect-platform --platform=instagram` - follow instructions from the command line ### Test the platform @@ -94,7 +94,7 @@ One fairpost user can only manage one page. If you create a second user, you can - go to https://developers.facebook.com/ - select your app, edit it - set App Mode to 'dev' -- call `./fairpost.js @foo setup-platform --platform=instagram` +- call `./fairpost.js @foo connect-platform --platform=instagram` - follow instructions from the command line - put your app back in live mode diff --git a/docs/LinkedIn.md b/docs/LinkedIn.md index 353a57f..2a67233 100644 --- a/docs/LinkedIn.md +++ b/docs/LinkedIn.md @@ -32,7 +32,7 @@ https://www.linkedin.com/developers/apps/new This token last for 60 days and should be refreshed. The refresh token (if given) lasts for 1 year. - - call `./fairpost.js @userid setup-platform --platform=linkedin` + - call `./fairpost.js @userid connect-platform --platform=linkedin` - follow instructions from the command line ### Test the platform @@ -50,7 +50,7 @@ One fairpost user can only manage one page. If you create a second user, you can ### Get an OAuth2 Access Token for your other page - - call `./fairpost.js @foo setup-platform --platform=linkedin` + - call `./fairpost.js @foo connect-platform --platform=linkedin` - follow instructions from the command line ### Test the other installation diff --git a/docs/NewPlatform.md b/docs/NewPlatform.md index 90329ee..02ad42c 100644 --- a/docs/NewPlatform.md +++ b/docs/NewPlatform.md @@ -103,9 +103,9 @@ and party. This method allows you to call `fairpost.js test-platform --platform=foobar`. You can return anything. -#### FooBar.setup() +#### FooBar.connect() -This method allows you to call `fairpost.js setup-platform --platform=foobar`, +This method allows you to call `fairpost.js connect-platform --platform=foobar`, usually to get the access tokens and save them in Storage. #### FooBar.refresh() @@ -215,7 +215,7 @@ import { Another good approach to refactor is to take the Authentication flow out of your platform into a separate `FooBar/FooBarAuth.ts`. -Add a method `setup()` and link your `Foobar.setup()` there. +Add a method `connect()` and link your `Foobar.connect()` there. Optionally add a method `refresh()` and link your `Foobar.refresh()` there. Store the access tokens in `auth` Storage, so you can access them in your platform class. @@ -240,7 +240,7 @@ export default class FooBarAuth { /** * Set up FooBar platform */ - async setup() { + async connect() { const code = await this.requestCode(); const tokens = await this.exchangeCode(code); await this.store(tokens); diff --git a/docs/Reddit.md b/docs/Reddit.md index 82caac3..9552e4a 100644 --- a/docs/Reddit.md +++ b/docs/Reddit.md @@ -22,7 +22,7 @@ This token only lasts for 24 hours and should be refreshed. - - call `./fairpost.js @userid setup-platform --platform=reddit` + - call `./fairpost.js @userid connect-platform --platform=reddit` - follow instructions from the command line diff --git a/docs/Twitter.md b/docs/Twitter.md index 2f089ab..9a0874c 100644 --- a/docs/Twitter.md +++ b/docs/Twitter.md @@ -44,7 +44,7 @@ keys will not be needed anymore. This token should last forever (?) - - call `./fairpost.js @userid setup-platform --platform=twitter` + - call `./fairpost.js @userid connect-platform --platform=twitter` - follow instructions from the command line ### Test the platform @@ -60,7 +60,7 @@ account and requires you to specify an 'additional_owner' for the uploaded media ### Get an OAuth2 Access Token for your other page -- call `./fairpost.js @foo setup-platform --platform=twitter` +- call `./fairpost.js @foo connect-platform --platform=twitter` - follow instructions from the command line ### Test the other installation diff --git a/docs/Youtube.md b/docs/Youtube.md index 323ce79..2007af5 100644 --- a/docs/Youtube.md +++ b/docs/Youtube.md @@ -55,7 +55,7 @@ To have Fairpost publish **public** videos, your app has to be audited This token last for a few hours and should be refreshed. The refresh token (if given) lasts until it is revoked. - - call `./fairpost.js @userid setup-platform --platform=youtube` + - call `./fairpost.js @userid connect-platform --platform=youtube` - follow instructions from the command line ### Test the platform @@ -70,7 +70,7 @@ The refresh token (if given) lasts until it is revoked. ### Get an OAuth2 Access Token for your other page - - call `./fairpost.js @foo setup-platform --platform=youtube` + - call `./fairpost.js @foo connect-platform --platform=youtube` - follow instructions from the command line ### Test the other installation diff --git a/package.json b/package.json index bbf2bf3..3894721 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fairpost", - "version": "3.0.0", + "version": "4.0.0", "type": "module", "engines": { "node": "22.17.0" diff --git a/src/models/Platform.ts b/src/models/Platform.ts index 0128560..51e4d61 100644 --- a/src/models/Platform.ts +++ b/src/models/Platform.ts @@ -45,7 +45,7 @@ export default class Platform { } /** - * setup + * connect * * Set the platform up. Get the required keys and tokens. * This may involve starting a webserver and/or communicating @@ -55,9 +55,9 @@ export default class Platform { * @returns - any object */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setup(operator?: Operator, payload?: object): Promise { + async connect(operator?: Operator, payload?: object): Promise { throw this.user.log.error( - "No setup implemented for " + + "No connect implemented for " + this.id + ". Read the docs in the docs folder.", ); diff --git a/src/platforms/Bluesky/Bluesky.ts b/src/platforms/Bluesky/Bluesky.ts index 1a8d78c..2fa7090 100644 --- a/src/platforms/Bluesky/Bluesky.ts +++ b/src/platforms/Bluesky/Bluesky.ts @@ -52,20 +52,20 @@ export default class Bluesky extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Bluesky setup requires a payload"); + throw this.user.log.error("Bluesky connect requires a payload"); } - await this.auth.setupApi(payload); + await this.auth.connectApi(payload); return await this.test(); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/Bluesky/BlueskyAuth.ts b/src/platforms/Bluesky/BlueskyAuth.ts index 54aec72..52af017 100644 --- a/src/platforms/Bluesky/BlueskyAuth.ts +++ b/src/platforms/Bluesky/BlueskyAuth.ts @@ -18,7 +18,7 @@ export default class BlueskyAuth { * In 2025, this uses a service, user handle, app password */ - public async setupCli() { + public async connectCli() { const reader = readline.createInterface({ input: process.stdin, output: process.stdout, @@ -28,7 +28,9 @@ export default class BlueskyAuth { }; const currentid = this.user.data.get("settings", "BLUESKY_IDENTIFIER", ""); if (!currentid) { - throw this.user.log.error("BlueskyAuth:setupCli - set identifier first"); + throw this.user.log.error( + "BlueskyAuth:connectCli - set identifier first", + ); } tokens.password = await reader.question(`BlueSky app password: `); reader.close(); @@ -36,13 +38,17 @@ export default class BlueskyAuth { console.log("Credentials stored."); } - public async setupApi(payload: { password?: string }) { + public async connectApi(payload: { password?: string }) { const currentid = this.user.data.get("settings", "BLUESKY_IDENTIFIER", ""); if (!currentid) { - throw this.user.log.error("BlueskyAuth:setupApi - set identifier first"); + throw this.user.log.error( + "BlueskyAuth:connectApi - set identifier first", + ); } if (!payload.password) { - throw this.user.log.error("BlueskyAuth:setupApi - app password missing"); + throw this.user.log.error( + "BlueskyAuth:connectApi - app password missing", + ); } await this.store({ password: payload.password, diff --git a/src/platforms/Facebook/Facebook.ts b/src/platforms/Facebook/Facebook.ts index a7bf0d7..6238c7d 100644 --- a/src/platforms/Facebook/Facebook.ts +++ b/src/platforms/Facebook/Facebook.ts @@ -67,19 +67,19 @@ export default class Facebook extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - return this.auth.setupApi(payload); + return this.auth.connectApi(payload); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/Facebook/FacebookAuth.ts b/src/platforms/Facebook/FacebookAuth.ts index c1a168f..7bdf0c3 100644 --- a/src/platforms/Facebook/FacebookAuth.ts +++ b/src/platforms/Facebook/FacebookAuth.ts @@ -17,7 +17,7 @@ export default class FacebookAuth { this.user = user; } - async setupCli() { + async connectCli() { const code = await this.requestCode( this.user.data.get("app", "FACEBOOK_APP_ID"), ); @@ -40,8 +40,8 @@ export default class FacebookAuth { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - public async setupApi(payload: object) { - throw this.user.log.error("FacebookAuth:setupApi - not implemented"); + public async connectApi(payload: object) { + throw this.user.log.error("FacebookAuth:connectApi - not implemented"); } protected async requestCode(clientId: string): Promise { diff --git a/src/platforms/Instagram/Instagram.ts b/src/platforms/Instagram/Instagram.ts index 9f3d5f2..e27c439 100644 --- a/src/platforms/Instagram/Instagram.ts +++ b/src/platforms/Instagram/Instagram.ts @@ -71,19 +71,19 @@ export default class Instagram extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - return this.auth.setupApi(payload); + return this.auth.connectApi(payload); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/Instagram/InstagramAuth.ts b/src/platforms/Instagram/InstagramAuth.ts index 87384fb..a9b5ae5 100644 --- a/src/platforms/Instagram/InstagramAuth.ts +++ b/src/platforms/Instagram/InstagramAuth.ts @@ -7,7 +7,7 @@ export default class InstagramAuth extends FacebookAuth { super(user); } - async setup() { + async connect() { const code = await this.requestCode( this.user.data.get("app", "INSTAGRAM_APP_ID"), ); @@ -30,8 +30,8 @@ export default class InstagramAuth extends FacebookAuth { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - public async setupApi(payload: object) { - throw this.user.log.error("InstagramAuth:setupApi - not implemented"); + public async connectApi(payload: object) { + throw this.user.log.error("InstagramAuth:connectApi - not implemented"); } protected async requestCode(clientId: string): Promise { diff --git a/src/platforms/LinkedIn/LinkedIn.ts b/src/platforms/LinkedIn/LinkedIn.ts index 7ca6dd3..3ce6bc2 100644 --- a/src/platforms/LinkedIn/LinkedIn.ts +++ b/src/platforms/LinkedIn/LinkedIn.ts @@ -62,16 +62,16 @@ export default class LinkedIn extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - const result = await this.auth.setupApi(payload); + const result = await this.auth.connectApi(payload); const ready = "ready" in result && result.ready; if (!ready) return result; return { @@ -81,7 +81,7 @@ export default class LinkedIn extends Platform { } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/LinkedIn/LinkedInAuth.ts b/src/platforms/LinkedIn/LinkedInAuth.ts index e54f4ec..86afe1d 100644 --- a/src/platforms/LinkedIn/LinkedInAuth.ts +++ b/src/platforms/LinkedIn/LinkedInAuth.ts @@ -20,7 +20,7 @@ export default class LinkedInAuth { /** * Set up LinkedIn platform */ - async setupCli() { + async connectCli() { const clientHost = this.user.data.get("app", "OAUTH_HOSTNAME"); const clientPort = Number(this.user.data.get("app", "OAUTH_PORT")); const redirectUri = OAuth2Service.getCallbackUrl(clientHost, clientPort); @@ -29,7 +29,7 @@ export default class LinkedInAuth { await this.store(tokens); } - async setupApi(payload: { + async connectApi(payload: { state?: string; redirect_uri?: string; code?: string; @@ -42,7 +42,10 @@ export default class LinkedInAuth { throw this.user.log.error(msg, payload); } if (!payload.redirect_uri) { - throw this.user.log.error("LinkedInAuth.setup: Invalid payload", payload); + throw this.user.log.error( + "LinkedInAuth.connect: Invalid payload", + payload, + ); } if (!payload.code) { return { diff --git a/src/platforms/Reddit/Reddit.ts b/src/platforms/Reddit/Reddit.ts index bcb1767..e00d007 100644 --- a/src/platforms/Reddit/Reddit.ts +++ b/src/platforms/Reddit/Reddit.ts @@ -57,19 +57,19 @@ export default class Reddit extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - return this.auth.setupApi(payload); + return this.auth.connectApi(payload); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/Reddit/RedditAuth.ts b/src/platforms/Reddit/RedditAuth.ts index 9582f73..768716c 100644 --- a/src/platforms/Reddit/RedditAuth.ts +++ b/src/platforms/Reddit/RedditAuth.ts @@ -16,15 +16,15 @@ export default class RedditAuth { constructor(user: User) { this.user = user; } - async setupCli() { + async connectCli() { const code = await this.requestCode(); const tokens = await this.exchangeCode(code); await this.store(tokens); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setupApi(payload: object) { - throw this.user.log.error("RedditAuth:setupApi - not implemented"); + async connectApi(payload: object) { + throw this.user.log.error("RedditAuth:connectApi - not implemented"); } /** diff --git a/src/platforms/Twitter/Twitter.ts b/src/platforms/Twitter/Twitter.ts index 6d149d8..51586ae 100644 --- a/src/platforms/Twitter/Twitter.ts +++ b/src/platforms/Twitter/Twitter.ts @@ -62,19 +62,19 @@ export default class Twitter extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - return this.auth.setupApi(payload); + return this.auth.connectApi(payload); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/Twitter/TwitterAuth.ts b/src/platforms/Twitter/TwitterAuth.ts index dcc9271..76128dc 100644 --- a/src/platforms/Twitter/TwitterAuth.ts +++ b/src/platforms/Twitter/TwitterAuth.ts @@ -15,15 +15,15 @@ export default class TwitterAuth { /** * Set up Twitter platform */ - async setupCli() { + async connectCli() { const { code, verifier } = await this.requestCode(); const tokens = await this.exchangeCode(code, verifier); await this.store(tokens); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setupApi(payload: object) { - throw this.user.log.error("TwitterAuth:setupApi - not implemented"); + async connectApi(payload: object) { + throw this.user.log.error("TwitterAuth:connectApi - not implemented"); } /** diff --git a/src/platforms/YouTube/YouTube.ts b/src/platforms/YouTube/YouTube.ts index 85c55ae..8b037b2 100644 --- a/src/platforms/YouTube/YouTube.ts +++ b/src/platforms/YouTube/YouTube.ts @@ -62,19 +62,19 @@ export default class YouTube extends Platform { } /** @inheritdoc */ - async setup(operator: Operator, payload?: object) { + async connect(operator: Operator, payload?: object) { if (operator.ui === "cli") { - await this.auth.setupCli(); + await this.auth.connectCli(); return await this.test(); } if (operator.ui === "api") { if (!payload) { - throw this.user.log.error("Setup via api requires a payload"); + throw this.user.log.error("Connect via api requires a payload"); } - return this.auth.setupApi(payload); + return this.auth.connectApi(payload); } throw this.user.log.error( - `${this.id} setup: ui ${operator.ui} not supported`, + `${this.id} connect: ui ${operator.ui} not supported`, ); } diff --git a/src/platforms/YouTube/YouTubeAuth.ts b/src/platforms/YouTube/YouTubeAuth.ts index c3c1e1a..648e814 100644 --- a/src/platforms/YouTube/YouTubeAuth.ts +++ b/src/platforms/YouTube/YouTubeAuth.ts @@ -17,15 +17,15 @@ export default class YouTubeAuth { /** * Set up YouTube platform */ - async setupCli() { + async connectCli() { const code = await this.requestCode(); const tokens = await this.exchangeCode(code); await this.store(tokens); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setupApi(payload: object) { - throw this.user.log.error("YouTubeAuth:setupApi - not implemented"); + async connectApi(payload: object) { + throw this.user.log.error("YouTubeAuth:connectApi - not implemented"); } /** diff --git a/src/services/Fairpost.ts b/src/services/Fairpost.ts index f54b4a1..73751a6 100644 --- a/src/services/Fairpost.ts +++ b/src/services/Fairpost.ts @@ -281,7 +281,7 @@ class Fairpost { break; } - case "setup-platform": { + case "connect-platform": { if (!permissions.manageFeed) { throw new Error("Missing permissions for command " + command); } @@ -299,11 +299,14 @@ class Fairpost { ) { throw user.log.error( "CommandHandler " + command, - "Setup payload must be an object", + "Connect payload must be an object", ); } const platform = await user.addPlatform(args.platform); - const result = await platform.setup(operator, args.payload as object); + const result = await platform.connect( + operator, + args.payload as object, + ); output = { [args.platform]: { success: true, @@ -1061,7 +1064,7 @@ class Fairpost { `${cmd} @userid put-platform --platform=xxx << payload`, `${cmd} @userid edit-platform --platform=xxx (cli only)`, `${cmd} @userid get-platforms [--platforms=xxx,xxx]`, - `${cmd} @userid setup-platform --platform=xxx`, + `${cmd} @userid connect-platform --platform=xxx`, `${cmd} @userid test-platform --platform=xxx`, `${cmd} @userid test-platforms [--platforms=xxx,xxx]`, `${cmd} @userid refresh-platform --platform=xxx`,