diff --git a/src/connections/BattleNet/index.ts b/src/connections/BattleNet/index.ts index f7d08cbe8..30488e3c9 100644 --- a/src/connections/BattleNet/index.ts +++ b/src/connections/BattleNet/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { BattleNetSettings } from "./BattleNetSettings"; +import { GenericOAuthSettings as BattleNetSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface BattleNetConnectionUser { @@ -34,6 +34,10 @@ interface BattleNetConnectionUser { export default class BattleNetConnection extends Connection { public readonly id = "battlenet"; + public readonly friendlyName = "Battle.net"; + public readonly setupUrl = "(missing - contributions welcome)"; + public readonly requiredScopes = []; + public readonly authorizeUrl = "https://oauth.battle.net/authorize"; public readonly tokenUrl = "https://oauth.battle.net/token"; public readonly userInfoUrl = "https://us.battle.net/oauth/userinfo"; @@ -46,6 +50,10 @@ export default class BattleNetConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Discord/DiscordSettings.ts b/src/connections/Discord/DiscordSettings.ts deleted file mode 100644 index af0b8d6c9..000000000 --- a/src/connections/Discord/DiscordSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class DiscordSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Discord/index.ts b/src/connections/Discord/index.ts index f209a81bd..5a15f0978 100644 --- a/src/connections/Discord/index.ts +++ b/src/connections/Discord/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { DiscordSettings } from "./DiscordSettings"; +import { GenericOAuthSettings as DiscordSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface UserResponse { @@ -30,6 +30,10 @@ interface UserResponse { export default class DiscordConnection extends Connection { public readonly id = "discord"; + public readonly friendlyName = "Discord"; + public readonly setupUrl = "https://discord.com/developers/applications"; + public readonly requiredScopes = ["identify"]; + public readonly authorizeUrl = "https://discord.com/api/oauth2/authorize"; public readonly tokenUrl = "https://discord.com/api/oauth2/token"; public readonly userInfoUrl = "https://discord.com/api/users/@me"; @@ -42,6 +46,10 @@ export default class DiscordConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/EpicGames/EpicGamesSettings.ts b/src/connections/EpicGames/EpicGamesSettings.ts deleted file mode 100644 index fbe5c7a32..000000000 --- a/src/connections/EpicGames/EpicGamesSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class EpicGamesSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/EpicGames/index.ts b/src/connections/EpicGames/index.ts index 959192e64..5fc2701f4 100644 --- a/src/connections/EpicGames/index.ts +++ b/src/connections/EpicGames/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { EpicGamesSettings } from "./EpicGamesSettings"; +import { GenericOAuthSettings as EpicGamesSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; export interface UserResponse { @@ -38,6 +38,10 @@ export interface EpicTokenResponse extends ConnectedAccountCommonOAuthTokenRespo export default class EpicGamesConnection extends Connection { public readonly id = "epicgames"; + public readonly friendlyName = "Epic Games"; + public readonly setupUrl = "https://dev.epicgames.com/portal"; + public readonly requiredScopes = []; + public readonly authorizeUrl = "https://www.epicgames.com/id/authorize"; public readonly tokenUrl = "https://api.epicgames.dev/epic/oauth/v1/token"; public readonly userInfoUrl = "https://api.epicgames.dev/epic/id/v1/accounts"; @@ -50,6 +54,9 @@ export default class EpicGamesConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Facebook/FacebookSettings.ts b/src/connections/Facebook/FacebookSettings.ts deleted file mode 100644 index f130358a1..000000000 --- a/src/connections/Facebook/FacebookSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class FacebookSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Facebook/index.ts b/src/connections/Facebook/index.ts index 29317c2e6..3abd5669e 100644 --- a/src/connections/Facebook/index.ts +++ b/src/connections/Facebook/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { FacebookSettings } from "./FacebookSettings"; +import { GenericOAuthSettings as FacebookSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; export interface FacebookErrorResponse { @@ -37,6 +37,10 @@ interface UserResponse { export default class FacebookConnection extends Connection { public readonly id = "facebook"; + public readonly friendlyName = "Facebook"; + public readonly setupUrl = "(missing - contributions welcome)"; + public readonly requiredScopes = []; + public readonly authorizeUrl = "https://www.facebook.com/v14.0/dialog/oauth"; public readonly tokenUrl = "https://graph.facebook.com/v14.0/oauth/access_token"; public readonly userInfoUrl = "https://graph.facebook.com/v14.0/me"; @@ -49,6 +53,10 @@ export default class FacebookConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/BattleNet/BattleNetSettings.ts b/src/connections/GenericOAuthSettings.ts similarity index 89% rename from src/connections/BattleNet/BattleNetSettings.ts rename to src/connections/GenericOAuthSettings.ts index 661fdeb8e..d4ccb354e 100644 --- a/src/connections/BattleNet/BattleNetSettings.ts +++ b/src/connections/GenericOAuthSettings.ts @@ -1,22 +1,22 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - + Copyright (C) 2026 Spacebar and Spacebar Contributors + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -export class BattleNetSettings { +export class GenericOAuthSettings { enabled: boolean = false; clientId: string | null = null; clientSecret: string | null = null; diff --git a/src/connections/GitHub/GitHubSettings.ts b/src/connections/GitHub/GitHubSettings.ts deleted file mode 100644 index f744a77f0..000000000 --- a/src/connections/GitHub/GitHubSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class GitHubSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/GitHub/index.ts b/src/connections/GitHub/index.ts index df64912ae..a5e0f7041 100644 --- a/src/connections/GitHub/index.ts +++ b/src/connections/GitHub/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { GitHubSettings } from "./GitHubSettings"; +import { GenericOAuthSettings as GitHubSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface UserResponse { @@ -29,6 +29,10 @@ interface UserResponse { export default class GitHubConnection extends Connection { public readonly id = "github"; + public friendlyName = "GitHub"; + public setupUrl = "https://github.com/settings/developers"; + public requiredScopes: string[]; + public readonly authorizeUrl = "https://github.com/login/oauth/authorize"; public readonly tokenUrl = "https://github.com/login/oauth/access_token"; public readonly userInfoUrl = "https://api.github.com/user"; @@ -41,6 +45,10 @@ export default class GitHubConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Reddit/RedditSettings.ts b/src/connections/Reddit/RedditSettings.ts deleted file mode 100644 index 083af8e60..000000000 --- a/src/connections/Reddit/RedditSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class RedditSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Reddit/index.ts b/src/connections/Reddit/index.ts index 781e097a1..92f3737e1 100644 --- a/src/connections/Reddit/index.ts +++ b/src/connections/Reddit/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { RedditSettings } from "./RedditSettings"; +import { GenericOAuthSettings as RedditSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; export interface UserResponse { @@ -41,6 +41,10 @@ export interface ErrorResponse { export default class RedditConnection extends Connection { public readonly id = "reddit"; + public friendlyName = "Reddit"; + public setupUrl = "https://www.reddit.com/prefs/apps"; + public requiredScopes = []; // Does not seem to offer platform-side scope controls + public readonly authorizeUrl = "https://www.reddit.com/api/v1/authorize"; public readonly tokenUrl = "https://www.reddit.com/api/v1/access_token"; public readonly userInfoUrl = "https://oauth.reddit.com/api/v1/me"; @@ -53,6 +57,10 @@ export default class RedditConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Spotify/SpotifySettings.ts b/src/connections/Spotify/SpotifySettings.ts deleted file mode 100644 index e2db48625..000000000 --- a/src/connections/Spotify/SpotifySettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class SpotifySettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Spotify/index.ts b/src/connections/Spotify/index.ts index 2186396bb..e64626b17 100644 --- a/src/connections/Spotify/index.ts +++ b/src/connections/Spotify/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, ConnectionLoader, DiscordApiErrors, RefreshableConnection } from "@spacebar/util"; import wretch from "wretch"; -import { SpotifySettings } from "./SpotifySettings"; +import { GenericOAuthSettings as SpotifySettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; export interface UserResponse { @@ -40,6 +40,10 @@ export interface ErrorResponse { export default class SpotifyConnection extends RefreshableConnection { public readonly id = "spotify"; + public friendlyName = "Spotify"; + public setupUrl = "https://developer.spotify.com"; + public requiredScopes = ["Requires instance admin to have spotify premium"]; + public readonly authorizeUrl = "https://accounts.spotify.com/authorize"; public readonly tokenUrl = "https://accounts.spotify.com/api/token"; public readonly userInfoUrl = "https://api.spotify.com/v1/me"; @@ -58,6 +62,10 @@ export default class SpotifyConnection extends RefreshableConnection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Twitch/TwitchSettings.ts b/src/connections/Twitch/TwitchSettings.ts deleted file mode 100644 index fcd0a0d95..000000000 --- a/src/connections/Twitch/TwitchSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class TwitchSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Twitch/index.ts b/src/connections/Twitch/index.ts index 5952caf1a..116b31921 100644 --- a/src/connections/Twitch/index.ts +++ b/src/connections/Twitch/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, ConnectionLoader, DiscordApiErrors, RefreshableConnection } from "@spacebar/util"; import wretch from "wretch"; -import { TwitchSettings } from "./TwitchSettings"; +import { GenericOAuthSettings as TwitchSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface TwitchConnectionUserResponse { @@ -38,6 +38,10 @@ interface TwitchConnectionUserResponse { export default class TwitchConnection extends RefreshableConnection { public readonly id = "twitch"; + public friendlyName = "Twitch.tv"; + public setupUrl = "https://dev.twitch.tv/console/apps/create"; + public requiredScopes: string[]; + public readonly authorizeUrl = "https://id.twitch.tv/oauth2/authorize"; public readonly tokenUrl = "https://id.twitch.tv/oauth2/token"; public readonly userInfoUrl = "https://api.twitch.tv/helix/users"; @@ -50,6 +54,10 @@ export default class TwitchConnection extends RefreshableConnection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Twitter/TwitterSettings.ts b/src/connections/Twitter/TwitterSettings.ts deleted file mode 100644 index f9b2f5aba..000000000 --- a/src/connections/Twitter/TwitterSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class TwitterSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Twitter/index.ts b/src/connections/Twitter/index.ts index 3c79515be..7a56aa41c 100644 --- a/src/connections/Twitter/index.ts +++ b/src/connections/Twitter/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, ConnectionLoader, DiscordApiErrors, RefreshableConnection } from "@spacebar/util"; import wretch from "wretch"; -import { TwitterSettings } from "./TwitterSettings"; +import { GenericOAuthSettings as TwitterSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface TwitterUserResponse { @@ -41,6 +41,10 @@ interface TwitterUserResponse { export default class TwitterConnection extends RefreshableConnection { public readonly id = "twitter"; + public friendlyName = "Twitter"; + public setupUrl = "https://console.x.com"; + public requiredScopes = []; //no scopes nessecary + public readonly authorizeUrl = "https://twitter.com/i/oauth2/authorize"; public readonly tokenUrl = "https://api.twitter.com/2/oauth2/token"; public readonly userInfoUrl = "https://api.twitter.com/2/users/me?user.fields=created_at%2Cdescription%2Cid%2Cname%2Cusername%2Cverified%2Clocation%2Curl"; @@ -53,6 +57,10 @@ export default class TwitterConnection extends RefreshableConnection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Xbox/XboxSettings.ts b/src/connections/Xbox/XboxSettings.ts deleted file mode 100644 index b7e97de30..000000000 --- a/src/connections/Xbox/XboxSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class XboxSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Xbox/index.ts b/src/connections/Xbox/index.ts index 59d4a0054..95cd6ecb0 100644 --- a/src/connections/Xbox/index.ts +++ b/src/connections/Xbox/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { XboxSettings } from "./XboxSettings"; +import { GenericOAuthSettings as XboxSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface XboxUserResponse { @@ -45,6 +45,10 @@ interface XboxUserResponse { export default class XboxConnection extends Connection { public readonly id = "xbox"; + public readonly friendlyName = "Xbox Live"; + public readonly setupUrl = "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade"; + public readonly requiredScopes = []; // these are part of the URL and don't need to be assigned + public readonly authorizeUrl = "https://login.live.com/oauth20_authorize.srf"; public readonly tokenUrl = "https://login.live.com/oauth20_token.srf"; public readonly userInfoUrl = "https://xsts.auth.xboxlive.com/xsts/authorize"; @@ -58,6 +62,10 @@ export default class XboxConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/connections/Youtube/YoutubeSettings.ts b/src/connections/Youtube/YoutubeSettings.ts deleted file mode 100644 index b2f7c1ba8..000000000 --- a/src/connections/Youtube/YoutubeSettings.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -export class YoutubeSettings { - enabled: boolean = false; - clientId: string | null = null; - clientSecret: string | null = null; -} diff --git a/src/connections/Youtube/index.ts b/src/connections/Youtube/index.ts index 2db9289f3..64debb83b 100644 --- a/src/connections/Youtube/index.ts +++ b/src/connections/Youtube/index.ts @@ -18,7 +18,7 @@ import { ConnectedAccount, Connection, ConnectionLoader, DiscordApiErrors } from "@spacebar/util"; import wretch from "wretch"; -import { YoutubeSettings } from "./YoutubeSettings"; +import { GenericOAuthSettings as YoutubeSettings } from "../GenericOAuthSettings"; import { ConnectedAccountCommonOAuthTokenResponse, ConnectionCallbackSchema } from "@spacebar/schemas"; interface YouTubeConnectionChannelListResult { @@ -45,6 +45,10 @@ interface YouTubeConnectionChannelListResult { export default class YoutubeConnection extends Connection { public readonly id = "youtube"; + public readonly friendlyName = "YouTube"; + public readonly setupUrl = "https://console.cloud.google.com/apis/api/youtube.googleapis.com"; + public readonly requiredScopes = ["/auth/youtube.readonly"]; + public readonly authorizeUrl = "https://accounts.google.com/o/oauth2/v2/auth"; public readonly tokenUrl = "https://oauth2.googleapis.com/token"; public readonly userInfoUrl = "https://www.googleapis.com/youtube/v3/channels?mine=true&part=snippet"; @@ -57,6 +61,10 @@ export default class YoutubeConnection extends Connection { if (this.settings.enabled && (!this.settings.clientId || !this.settings.clientSecret)) throw new Error(`Invalid settings for connection ${this.id}`); } + public get isConfigured(): boolean { + return !!this.settings.clientId && !!this.settings.clientSecret; + } + getAuthorizationUrl(userId: string): string { const state = this.createState(userId); const url = new URL(this.authorizeUrl); diff --git a/src/util/connections/Connection.ts b/src/util/connections/Connection.ts index e48b13a11..d59341647 100644 --- a/src/util/connections/Connection.ts +++ b/src/util/connections/Connection.ts @@ -29,8 +29,17 @@ export abstract class Connection { settings: { enabled: boolean }; states: Map = new Map(); + public abstract readonly friendlyName: string; + public abstract readonly setupUrl: string; + public abstract readonly requiredScopes: string[]; + abstract init(): void; + /** + * Returns whether a connection has all the required settings + */ + public abstract get isConfigured(): boolean; + /** * Generates an authorization url for the connection. * @param userId the user id to generate the url for diff --git a/src/util/connections/ConnectionLoader.ts b/src/util/connections/ConnectionLoader.ts index f75b430f5..021ef3a66 100644 --- a/src/util/connections/ConnectionLoader.ts +++ b/src/util/connections/ConnectionLoader.ts @@ -21,6 +21,7 @@ import fs from "fs"; import path from "path"; import { ConnectionConfig } from "./ConnectionConfig"; import { ConnectionStore } from "./ConnectionStore"; +import { greenBright, redBright } from "picocolors"; const root = path.join(__dirname, "..", "..", "connections"); const connectionsLoaded = false; @@ -44,7 +45,15 @@ export class ConnectionLoader { ConnectionStore.connections.set(mod.id, mod); mod.init(); - // console.log(`[Connections] Loaded connection '${mod.id}'`); + console.log(`[Connections] Loaded connection '${mod.id}' (${mod.friendlyName}) -`, mod.settings.enabled ? greenBright("enabled") : redBright("disabled")); + if (mod.settings.enabled && !mod.isConfigured) { + console.log(`[Connections/${mod.id}] Connection is enabled, but not configured! Users will not be able to successfully link with ${mod.friendlyName}!`); + if (mod.requiredScopes.length > 0) { + console.log(`[Connections/${mod.id}] Configuring this connection requires setting scopes, or has additional requirements:`); + for (const scope in mod.requiredScopes) console.log(`[Connections/${mod.id}] - ${scope}`); + console.log(`[Connections/${mod.id}] You can obtain the required credentials here: ${mod.setupUrl}`); + } + } }); }