feat(disqus): add disqus integration
This commit is contained in:
16
packages/backend/src/apps/disqus/assets/favicon.svg
Normal file
16
packages/backend/src/apps/disqus/assets/favicon.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
|
||||||
|
<g id="background">
|
||||||
|
<rect fill="#2E9FFF" width="200" height="200"/>
|
||||||
|
</g>
|
||||||
|
<g id="Layer_2">
|
||||||
|
</g>
|
||||||
|
<path fill="#FFFFFF" d="M102.535,167.5c-16.518,0-31.621-6.036-43.298-16.021L30.5,155.405l11.102-27.401
|
||||||
|
c-3.868-8.535-6.038-18.01-6.038-28.004c0-37.277,29.984-67.5,66.971-67.5c36.984,0,66.965,30.223,66.965,67.5
|
||||||
|
C169.5,137.284,139.52,167.5,102.535,167.5z M139.102,99.807v-0.188c0-19.479-13.736-33.367-37.42-33.367h-25.58v67.5h25.201
|
||||||
|
C125.171,133.753,139.102,119.284,139.102,99.807L139.102,99.807z M101.964,117.168h-7.482V82.841h7.482
|
||||||
|
c10.989,0,18.283,6.265,18.283,17.07v0.188C120.247,110.995,112.953,117.168,101.964,117.168z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
21
packages/backend/src/apps/disqus/auth/generate-auth-url.js
Normal file
21
packages/backend/src/apps/disqus/auth/generate-auth-url.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
import authScope from '../common/auth-scope.js';
|
||||||
|
|
||||||
|
export default async function generateAuthUrl($) {
|
||||||
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
|
(field) => field.key == 'oAuthRedirectUrl'
|
||||||
|
);
|
||||||
|
const redirectUri = oauthRedirectUrlField.value;
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
client_id: $.auth.data.apiKey,
|
||||||
|
scope: authScope.join(','),
|
||||||
|
response_type: 'code',
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `https://disqus.com/api/oauth/2.0/authorize/?${searchParams.toString()}`;
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
}
|
48
packages/backend/src/apps/disqus/auth/index.js
Normal file
48
packages/backend/src/apps/disqus/auth/index.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import generateAuthUrl from './generate-auth-url.js';
|
||||||
|
import verifyCredentials from './verify-credentials.js';
|
||||||
|
import refreshToken from './refresh-token.js';
|
||||||
|
import isStillVerified from './is-still-verified.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'oAuthRedirectUrl',
|
||||||
|
label: 'OAuth Redirect URL',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: true,
|
||||||
|
value: '{WEB_APP_URL}/app/disqus/connections/add',
|
||||||
|
placeholder: null,
|
||||||
|
description:
|
||||||
|
'When asked to input a redirect URL in Disqus, enter the URL above.',
|
||||||
|
clickToCopy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'apiKey',
|
||||||
|
label: 'API Key',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'apiSecret',
|
||||||
|
label: 'API Secret',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
generateAuthUrl,
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
refreshToken,
|
||||||
|
};
|
@@ -0,0 +1,8 @@
|
|||||||
|
import getCurrentUser from '../common/get-current-user.js';
|
||||||
|
|
||||||
|
const isStillVerified = async ($) => {
|
||||||
|
const currentUser = await getCurrentUser($);
|
||||||
|
return !!currentUser.response.username;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
26
packages/backend/src/apps/disqus/auth/refresh-token.js
Normal file
26
packages/backend/src/apps/disqus/auth/refresh-token.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { URLSearchParams } from 'node:url';
|
||||||
|
import authScope from '../common/auth-scope.js';
|
||||||
|
|
||||||
|
const refreshToken = async ($) => {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
client_id: $.auth.data.apiKey,
|
||||||
|
client_secret: $.auth.data.apiSecret,
|
||||||
|
refresh_token: $.auth.data.refreshToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`https://disqus.com/api/oauth/2.0/access_token/`,
|
||||||
|
params.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
accessToken: data.access_token,
|
||||||
|
refreshToken: data.refresh_token,
|
||||||
|
expiresIn: data.expires_in,
|
||||||
|
scope: authScope.join(','),
|
||||||
|
tokenType: data.token_type,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default refreshToken;
|
34
packages/backend/src/apps/disqus/auth/verify-credentials.js
Normal file
34
packages/backend/src/apps/disqus/auth/verify-credentials.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
const verifyCredentials = async ($) => {
|
||||||
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
|
(field) => field.key == 'oAuthRedirectUrl'
|
||||||
|
);
|
||||||
|
const redirectUri = oauthRedirectUrlField.value;
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
client_id: $.auth.data.apiKey,
|
||||||
|
client_secret: $.auth.data.apiSecret,
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
code: $.auth.data.code,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`https://disqus.com/api/oauth/2.0/access_token/`,
|
||||||
|
params.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
accessToken: data.access_token,
|
||||||
|
tokenType: data.token_type,
|
||||||
|
apiKey: $.auth.data.apiKey,
|
||||||
|
apiSecret: $.auth.data.apiSecret,
|
||||||
|
scope: $.auth.data.scope,
|
||||||
|
userId: data.user_id,
|
||||||
|
expiresIn: data.expires_in,
|
||||||
|
refreshToken: data.refresh_token,
|
||||||
|
screenName: data.username,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
15
packages/backend/src/apps/disqus/common/add-auth-header.js
Normal file
15
packages/backend/src/apps/disqus/common/add-auth-header.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
const addAuthHeader = ($, requestConfig) => {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
access_token: $.auth.data.accessToken,
|
||||||
|
api_key: $.auth.data.apiKey,
|
||||||
|
api_secret: $.auth.data.apiSecret,
|
||||||
|
});
|
||||||
|
|
||||||
|
requestConfig.params = params;
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addAuthHeader;
|
3
packages/backend/src/apps/disqus/common/auth-scope.js
Normal file
3
packages/backend/src/apps/disqus/common/auth-scope.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
const authScope = ['read', 'write', 'admin', 'email'];
|
||||||
|
|
||||||
|
export default authScope;
|
10
packages/backend/src/apps/disqus/common/get-current-user.js
Normal file
10
packages/backend/src/apps/disqus/common/get-current-user.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
const getCurrentUser = async ($) => {
|
||||||
|
try {
|
||||||
|
const { data: currentUser } = await $.http.get('/3.0/users/details.json');
|
||||||
|
return currentUser;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('You are not authenticated.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCurrentUser;
|
16
packages/backend/src/apps/disqus/index.js
Normal file
16
packages/backend/src/apps/disqus/index.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import defineApp from '../../helpers/define-app.js';
|
||||||
|
import addAuthHeader from './common/add-auth-header.js';
|
||||||
|
import auth from './auth/index.js';
|
||||||
|
|
||||||
|
export default defineApp({
|
||||||
|
name: 'Disqus',
|
||||||
|
key: 'disqus',
|
||||||
|
baseUrl: 'https://disqus.com',
|
||||||
|
apiBaseUrl: 'https://disqus.com/api',
|
||||||
|
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
||||||
|
authDocUrl: 'https://automatisch.io/docs/apps/disqus/connection',
|
||||||
|
primaryColor: '2E9FFF',
|
||||||
|
supportsConnections: true,
|
||||||
|
beforeRequest: [addAuthHeader],
|
||||||
|
auth,
|
||||||
|
});
|
@@ -68,6 +68,12 @@ export default defineConfig({
|
|||||||
{ text: 'Connection', link: '/apps/discord/connection' },
|
{ text: 'Connection', link: '/apps/discord/connection' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Disqus',
|
||||||
|
collapsible: true,
|
||||||
|
collapsed: true,
|
||||||
|
items: [{ text: 'Connection', link: '/apps/disqus/connection' }],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Dropbox',
|
text: 'Dropbox',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
@@ -305,7 +311,7 @@ export default defineConfig({
|
|||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{ text: 'Actions', link: '/apps/removebg/actions' },
|
{ text: 'Actions', link: '/apps/removebg/actions' },
|
||||||
{ text: 'Connection', link: '/apps/removebg/connection' }
|
{ text: 'Connection', link: '/apps/removebg/connection' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
19
packages/docs/pages/apps/disqus/connection.md
Normal file
19
packages/docs/pages/apps/disqus/connection.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Disqus
|
||||||
|
|
||||||
|
:::info
|
||||||
|
This page explains the steps you need to follow to set up the Disqus
|
||||||
|
connection in Automatisch. If any of the steps are outdated, please let us know!
|
||||||
|
:::
|
||||||
|
|
||||||
|
1. Login to the [Disqus](https://disqus.com/).
|
||||||
|
2. Go to the [API applications page](https://disqus.com/api/applications/) and click on the **Register new application** button.
|
||||||
|
3. Fill the **Register Application** form fields.
|
||||||
|
4. Click on the **Register my application** button.
|
||||||
|
5. Go to the **Authentication** section and select **Read, Write, and Manage Forums** option.
|
||||||
|
6. Copy **OAuth Redirect URL** from Automatisch to **Callback URL** field.
|
||||||
|
7. Click on the **Save Changes** button.
|
||||||
|
8. Go to the **Details** tab.
|
||||||
|
9. Copy **API Key** to **API Key** field on Automatisch.
|
||||||
|
10. Copy **API Secret** to **API Secret** field on Automatisch.
|
||||||
|
11. Click **Submit** button on Automatisch.
|
||||||
|
12. Congrats! Start using your new Disqus connection within the flows.
|
16
packages/docs/pages/public/favicons/disqus.svg
Normal file
16
packages/docs/pages/public/favicons/disqus.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
|
||||||
|
<g id="background">
|
||||||
|
<rect fill="#2E9FFF" width="200" height="200"/>
|
||||||
|
</g>
|
||||||
|
<g id="Layer_2">
|
||||||
|
</g>
|
||||||
|
<path fill="#FFFFFF" d="M102.535,167.5c-16.518,0-31.621-6.036-43.298-16.021L30.5,155.405l11.102-27.401
|
||||||
|
c-3.868-8.535-6.038-18.01-6.038-28.004c0-37.277,29.984-67.5,66.971-67.5c36.984,0,66.965,30.223,66.965,67.5
|
||||||
|
C169.5,137.284,139.52,167.5,102.535,167.5z M139.102,99.807v-0.188c0-19.479-13.736-33.367-37.42-33.367h-25.58v67.5h25.201
|
||||||
|
C125.171,133.753,139.102,119.284,139.102,99.807L139.102,99.807z M101.964,117.168h-7.482V82.841h7.482
|
||||||
|
c10.989,0,18.283,6.265,18.283,17.07v0.188C120.247,110.995,112.953,117.168,101.964,117.168z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user