Merge pull request #631 from automatisch/add-flickr-auth
feat(flickr): add authentication
This commit is contained in:
31
packages/backend/src/apps/flickr/auth/create-auth-data.ts
Normal file
31
packages/backend/src/apps/flickr/auth/create-auth-data.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { IJSONObject, IField, IGlobalVariable } from '@automatisch/types';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
export default async function createAuthData($: IGlobalVariable) {
|
||||||
|
try {
|
||||||
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
|
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||||
|
);
|
||||||
|
|
||||||
|
const callbackUrl = oauthRedirectUrlField.value;
|
||||||
|
const requestPath = '/oauth/request_token';
|
||||||
|
const data = { oauth_callback: callbackUrl };
|
||||||
|
|
||||||
|
const response = await $.http.post(requestPath, data);
|
||||||
|
const responseData = Object.fromEntries(new URLSearchParams(response.data));
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
url: `${$.app.apiBaseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}&perms=delete`,
|
||||||
|
accessToken: responseData.oauth_token,
|
||||||
|
accessSecret: responseData.oauth_token_secret,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessages = error.response.data.errors
|
||||||
|
.map((error: IJSONObject) => error.message)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Error occured while verifying credentials: ${errorMessages}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
221
packages/backend/src/apps/flickr/auth/index.ts
Normal file
221
packages/backend/src/apps/flickr/auth/index.ts
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
import createAuthData from './create-auth-data';
|
||||||
|
import verifyCredentials from './verify-credentials';
|
||||||
|
import isStillVerified from './is-still-verified';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'oAuthRedirectUrl',
|
||||||
|
label: 'OAuth Redirect URL',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: true,
|
||||||
|
value: '{WEB_APP_URL}/app/flickr/connections/add',
|
||||||
|
placeholder: null,
|
||||||
|
description: 'When asked to input an OAuth callback or redirect URL in Flickr OAuth, enter the URL above.',
|
||||||
|
docUrl: 'https://automatisch.io/docs/flickr#oauth-redirect-url',
|
||||||
|
clickToCopy: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'consumerKey',
|
||||||
|
label: 'Consumer Key',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
docUrl: 'https://automatisch.io/docs/flickr#consumer-key',
|
||||||
|
clickToCopy: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'consumerSecret',
|
||||||
|
label: 'Consumer Secret',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
docUrl: 'https://automatisch.io/docs/flickr#consumer-secret',
|
||||||
|
clickToCopy: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
authenticationSteps: [
|
||||||
|
{
|
||||||
|
step: 1,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: '{key}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'consumerKey',
|
||||||
|
value: '{fields.consumerKey}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'consumerSecret',
|
||||||
|
value: '{fields.consumerSecret}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 2,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createAuthData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 3,
|
||||||
|
type: 'openWithPopup',
|
||||||
|
name: 'openAuthPopup',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
value: '{createAuthData.url}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 4,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'oauthVerifier',
|
||||||
|
value: '{openAuthPopup.oauth_verifier}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 5,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'verifyConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
reconnectionSteps: [
|
||||||
|
{
|
||||||
|
step: 1,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'resetConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 2,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'consumerKey',
|
||||||
|
value: '{fields.consumerKey}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'consumerSecret',
|
||||||
|
value: '{fields.consumerSecret}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 3,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createAuthData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 4,
|
||||||
|
type: 'openWithPopup',
|
||||||
|
name: 'openAuthPopup',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
value: '{createAuthData.url}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 5,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'oauthVerifier',
|
||||||
|
value: '{openAuthPopup.oauth_verifier}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 6,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'verifyConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
createAuthData,
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
};
|
17
packages/backend/src/apps/flickr/auth/is-still-verified.ts
Normal file
17
packages/backend/src/apps/flickr/auth/is-still-verified.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
|
||||||
|
const isStillVerified = async ($: IGlobalVariable) => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
method: 'flickr.test.login',
|
||||||
|
format: 'json',
|
||||||
|
nojsoncallback: 1,
|
||||||
|
}
|
||||||
|
const response = await $.http.get('/rest', { params });
|
||||||
|
return !!response.data.user.id;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
26
packages/backend/src/apps/flickr/auth/verify-credentials.ts
Normal file
26
packages/backend/src/apps/flickr/auth/verify-credentials.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||||
|
try {
|
||||||
|
const response = await $.http.post(
|
||||||
|
`/oauth/access_token?oauth_verifier=${$.auth.data.oauthVerifier}&oauth_token=${$.auth.data.accessToken}`,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
const responseData = Object.fromEntries(new URLSearchParams(response.data));
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
consumerKey: $.auth.data.consumerKey,
|
||||||
|
consumerSecret: $.auth.data.consumerSecret,
|
||||||
|
accessToken: responseData.oauth_token,
|
||||||
|
accessSecret: responseData.oauth_token_secret,
|
||||||
|
userId: responseData.user_nsid,
|
||||||
|
screenName: responseData.fullname,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error.response.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
@@ -1,82 +0,0 @@
|
|||||||
import type {
|
|
||||||
IAuthentication,
|
|
||||||
IApp,
|
|
||||||
IField,
|
|
||||||
IJSONObject,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
|
|
||||||
export default class Authentication implements IAuthentication {
|
|
||||||
appData: IApp;
|
|
||||||
connectionData: IJSONObject;
|
|
||||||
client: typeof FlickrApi;
|
|
||||||
oauthClient: typeof FlickrApi;
|
|
||||||
|
|
||||||
constructor(appData: IApp, connectionData: IJSONObject) {
|
|
||||||
this.oauthClient = new FlickrApi.OAuth(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret
|
|
||||||
);
|
|
||||||
|
|
||||||
if (connectionData.accessToken && connectionData.accessSecret) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
this.appData = appData;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createAuthData() {
|
|
||||||
const appFields = this.appData.fields.find(
|
|
||||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
|
||||||
);
|
|
||||||
const callbackUrl = appFields.value;
|
|
||||||
|
|
||||||
const oauthData = (await this.oauthClient.request(callbackUrl)).body;
|
|
||||||
const url = await this.oauthClient.authorizeUrl(
|
|
||||||
oauthData.oauth_token,
|
|
||||||
'delete'
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
accessToken: oauthData.oauth_token,
|
|
||||||
accessSecret: oauthData.oauth_token_secret,
|
|
||||||
url: url,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async verifyCredentials() {
|
|
||||||
const verifiedCredentials = (
|
|
||||||
await this.oauthClient.verify(
|
|
||||||
this.connectionData.accessToken,
|
|
||||||
this.connectionData.oauthVerifier,
|
|
||||||
this.connectionData.accessSecret
|
|
||||||
)
|
|
||||||
).body;
|
|
||||||
|
|
||||||
return {
|
|
||||||
consumerKey: this.connectionData.consumerKey,
|
|
||||||
consumerSecret: this.connectionData.consumerSecret,
|
|
||||||
accessToken: verifiedCredentials.oauth_token,
|
|
||||||
accessSecret: verifiedCredentials.oauth_token_secret,
|
|
||||||
userId: verifiedCredentials.user_nsid,
|
|
||||||
screenName: verifiedCredentials.fullname,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async isStillVerified() {
|
|
||||||
try {
|
|
||||||
await this.client.test.login();
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
41
packages/backend/src/apps/flickr/common/add-auth-header.ts
Normal file
41
packages/backend/src/apps/flickr/common/add-auth-header.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Token } from 'oauth-1.0a';
|
||||||
|
import { IJSONObject, TBeforeRequest } from '@automatisch/types';
|
||||||
|
import oauthClient from './oauth-client';
|
||||||
|
|
||||||
|
type RequestDataType = {
|
||||||
|
url: string;
|
||||||
|
method: string;
|
||||||
|
data?: IJSONObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||||
|
const { url, method, data, params } = requestConfig;
|
||||||
|
|
||||||
|
const token: Token = {
|
||||||
|
key: $.auth.data?.accessToken as string,
|
||||||
|
secret: $.auth.data?.accessSecret as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const requestData: RequestDataType = {
|
||||||
|
url: `${requestConfig.baseURL}${url}`,
|
||||||
|
method,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (url === '/oauth/request_token') {
|
||||||
|
requestData.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method === 'get') {
|
||||||
|
requestData.data = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
const authHeader = oauthClient($).toHeader(
|
||||||
|
oauthClient($).authorize(requestData, token)
|
||||||
|
);
|
||||||
|
|
||||||
|
requestConfig.headers.Authorization = authHeader.Authorization;
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addAuthHeader;
|
23
packages/backend/src/apps/flickr/common/oauth-client.ts
Normal file
23
packages/backend/src/apps/flickr/common/oauth-client.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import OAuth from 'oauth-1.0a';
|
||||||
|
|
||||||
|
const oauthClient = ($: IGlobalVariable) => {
|
||||||
|
const consumerData = {
|
||||||
|
key: $.auth.data.consumerKey as string,
|
||||||
|
secret: $.auth.data.consumerSecret as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new OAuth({
|
||||||
|
consumer: consumerData,
|
||||||
|
signature_method: 'HMAC-SHA1',
|
||||||
|
hash_function(base_string, key) {
|
||||||
|
return crypto
|
||||||
|
.createHmac('sha1', key)
|
||||||
|
.update(base_string)
|
||||||
|
.digest('base64');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default oauthClient;
|
@@ -1,10 +0,0 @@
|
|||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
import ListAlbums from './data/list-albums';
|
|
||||||
|
|
||||||
export default class Data {
|
|
||||||
listAlbums: ListAlbums;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
this.listAlbums = new ListAlbums(connectionData);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
import type { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class ListAlbums {
|
|
||||||
client?: typeof FlickrApi;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken &&
|
|
||||||
connectionData.accessSecret
|
|
||||||
) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
const { photosets } = (await this.client.photosets.getList()).body;
|
|
||||||
const allPhotosets = [...photosets.photoset];
|
|
||||||
|
|
||||||
for (let page = photosets.page + 1; page <= photosets.pages; page++) {
|
|
||||||
const { photosets } = (await this.client.photosets.getList({ page, })).body;
|
|
||||||
allPhotosets.push(...photosets.photoset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allPhotosets.map((photoset) => ({
|
|
||||||
value: photoset.id,
|
|
||||||
name: photoset.title._content,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
1
packages/backend/src/apps/flickr/index.d.ts
vendored
1
packages/backend/src/apps/flickr/index.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
declare module 'flickr-sdk';
|
|
||||||
|
@@ -1,25 +1,15 @@
|
|||||||
import {
|
import defineApp from '../../helpers/define-app';
|
||||||
IService,
|
import addAuthHeader from './common/add-auth-header';
|
||||||
IAuthentication,
|
|
||||||
IApp,
|
|
||||||
IJSONObject,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import Authentication from './authentication';
|
|
||||||
import Triggers from './triggers';
|
|
||||||
import Data from './data';
|
|
||||||
|
|
||||||
export default class Flickr implements IService {
|
export default defineApp({
|
||||||
authenticationClient: IAuthentication;
|
name: 'Flickr',
|
||||||
triggers: Triggers;
|
key: 'flickr',
|
||||||
data: Data;
|
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
||||||
|
authDocUrl: 'https://automatisch.io/docs/connections/flickr',
|
||||||
constructor(
|
docUrl: 'https://automatisch.io/docs/flickr',
|
||||||
appData: IApp,
|
primaryColor: '000000',
|
||||||
connectionData: IJSONObject,
|
supportsConnections: true,
|
||||||
parameters: IJSONObject
|
baseUrl: 'https://www.flickr.com/',
|
||||||
) {
|
apiBaseUrl: 'https://www.flickr.com/services',
|
||||||
this.authenticationClient = new Authentication(appData, connectionData);
|
beforeRequest: [addAuthHeader],
|
||||||
this.data = new Data(connectionData);
|
});
|
||||||
this.triggers = new Triggers(connectionData, parameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,304 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Flickr",
|
|
||||||
"key": "flickr",
|
|
||||||
"iconUrl": "{BASE_URL}/apps/flickr/assets/favicon.svg",
|
|
||||||
"docUrl": "https://automatisch.io/docs/flickr",
|
|
||||||
"primaryColor": "000000",
|
|
||||||
"supportsConnections": true,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"key": "oAuthRedirectUrl",
|
|
||||||
"label": "OAuth Redirect URL",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": true,
|
|
||||||
"value": "{WEB_APP_URL}/app/flickr/connections/add",
|
|
||||||
"placeholder": null,
|
|
||||||
"description": "When asked to input an OAuth callback or redirect URL in Flickr OAuth, enter the URL above.",
|
|
||||||
"docUrl": "https://automatisch.io/docs/flickr#oauth-redirect-url",
|
|
||||||
"clickToCopy": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "consumerKey",
|
|
||||||
"label": "Consumer Key",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/flickr#consumer-key",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "consumerSecret",
|
|
||||||
"label": "Consumer Secret",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/flickr#consumer-secret",
|
|
||||||
"clickToCopy": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authenticationSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "{key}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "consumerKey",
|
|
||||||
"value": "{fields.consumerKey}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "consumerSecret",
|
|
||||||
"value": "{fields.consumerSecret}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createAuthData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 3,
|
|
||||||
"type": "openWithPopup",
|
|
||||||
"name": "openAuthPopup",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "url",
|
|
||||||
"value": "{createAuthData.url}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 4,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "oauthVerifier",
|
|
||||||
"value": "{openAuthPopup.oauth_verifier}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 5,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"reconnectionSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "resetConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "consumerKey",
|
|
||||||
"value": "{fields.consumerKey}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "consumerSecret",
|
|
||||||
"value": "{fields.consumerSecret}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 3,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createAuthData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 4,
|
|
||||||
"type": "openWithPopup",
|
|
||||||
"name": "openAuthPopup",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "url",
|
|
||||||
"value": "{createAuthData.url}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 5,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "oauthVerifier",
|
|
||||||
"value": "{openAuthPopup.oauth_verifier}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 6,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"triggers": [
|
|
||||||
{
|
|
||||||
"name": "New favorite photo",
|
|
||||||
"key": "newFavoritePhoto",
|
|
||||||
"description": "Triggers when you favorite a photo.",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New photo in album",
|
|
||||||
"key": "newPhotoInAlbum",
|
|
||||||
"description": "Triggers when you add a new photo in an album.",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Album",
|
|
||||||
"key": "album",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listAlbums"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New photo",
|
|
||||||
"key": "newPhoto",
|
|
||||||
"description": "Triggers when you add a new photo.",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New album",
|
|
||||||
"key": "newAlbum",
|
|
||||||
"description": "Triggers when you create a new album.",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
import NewFavoritePhoto from './triggers/new-favorite-photo';
|
|
||||||
import NewPhotoInAlbum from './triggers/new-photo-in-album';
|
|
||||||
import NewPhoto from './triggers/new-photo';
|
|
||||||
import NewAlbum from './triggers/new-album';
|
|
||||||
|
|
||||||
export default class Triggers {
|
|
||||||
newFavoritePhoto: NewFavoritePhoto;
|
|
||||||
newPhotoInAlbum: NewPhotoInAlbum;
|
|
||||||
newPhoto: NewPhoto;
|
|
||||||
newAlbum: NewAlbum;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
this.newFavoritePhoto = new NewFavoritePhoto(connectionData);
|
|
||||||
this.newPhotoInAlbum = new NewPhotoInAlbum(connectionData, parameters);
|
|
||||||
this.newPhoto = new NewPhoto(connectionData);
|
|
||||||
this.newAlbum = new NewAlbum(connectionData);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,103 +0,0 @@
|
|||||||
import { DateTime } from 'luxon';
|
|
||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewAlbum {
|
|
||||||
client?: typeof FlickrApi;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
primaryPhotoExtraFields = [
|
|
||||||
'description',
|
|
||||||
'license',
|
|
||||||
'date_upload',
|
|
||||||
'date_taken',
|
|
||||||
'owner_name',
|
|
||||||
'icon_server',
|
|
||||||
'original_format',
|
|
||||||
'last_update',
|
|
||||||
'geo',
|
|
||||||
'tags',
|
|
||||||
'machine_tags',
|
|
||||||
'o_dims',
|
|
||||||
'views',
|
|
||||||
'media',
|
|
||||||
'path_alias',
|
|
||||||
'url_sq',
|
|
||||||
'url_t',
|
|
||||||
'url_s',
|
|
||||||
'url_q',
|
|
||||||
'url_m',
|
|
||||||
'url_n',
|
|
||||||
'url_z',
|
|
||||||
'url_c',
|
|
||||||
'url_l',
|
|
||||||
'url_o',
|
|
||||||
].join(',');
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken &&
|
|
||||||
connectionData.accessSecret
|
|
||||||
) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAlbums(options: { perPage?: number, page?: number } = {}) {
|
|
||||||
const { perPage, page } = options;
|
|
||||||
const payload = {
|
|
||||||
page,
|
|
||||||
per_page: perPage,
|
|
||||||
primary_photo_extras: this.primaryPhotoExtraFields,
|
|
||||||
};
|
|
||||||
const { photosets } = (await this.client.photosets.getList(payload)).body;
|
|
||||||
|
|
||||||
return photosets;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const albums = await this.getAlbums({ page: 1 });
|
|
||||||
const allAlbums = [...albums.photoset];
|
|
||||||
const newAlbums = [];
|
|
||||||
|
|
||||||
let page = 1;
|
|
||||||
for (const album of allAlbums) {
|
|
||||||
const createdAtInSeconds = DateTime.fromSeconds(parseInt(album.date_create, 10));
|
|
||||||
const createdAt = createdAtInSeconds.toMillis();
|
|
||||||
|
|
||||||
if (createdAt <= startTime.getTime()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
newAlbums.push(album);
|
|
||||||
|
|
||||||
const currentIndex = allAlbums.indexOf(album);
|
|
||||||
const totalAlbums = allAlbums.length;
|
|
||||||
const isLastItem = currentIndex + 1 === totalAlbums;
|
|
||||||
|
|
||||||
if (isLastItem && page < albums.pages) {
|
|
||||||
page = page + 1;
|
|
||||||
const { photoset } = await this.getAlbums({ page, });
|
|
||||||
allAlbums.push(...photoset.photoset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newAlbums;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const { photoset } = await this.getAlbums({ perPage: 1 });
|
|
||||||
|
|
||||||
return photoset;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,62 +0,0 @@
|
|||||||
import { DateTime } from 'luxon';
|
|
||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewFavoritePhoto {
|
|
||||||
client?: typeof FlickrApi;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken &&
|
|
||||||
connectionData.accessSecret
|
|
||||||
) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const { photos } = (await this.client.favorites.getList()).body;
|
|
||||||
const favPhotos = [...photos.photo];
|
|
||||||
const newFavPhotos = [];
|
|
||||||
|
|
||||||
let page = 1;
|
|
||||||
for (const photo of favPhotos) {
|
|
||||||
const markedFavoriteAt = DateTime.fromSeconds(parseInt(photo.date_faved, 10));
|
|
||||||
const markedFavoriteAtInMillis = markedFavoriteAt.toMillis();
|
|
||||||
|
|
||||||
if (markedFavoriteAtInMillis <= startTime.getTime()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
newFavPhotos.push(photo);
|
|
||||||
|
|
||||||
const currentIndex = favPhotos.indexOf(photo);
|
|
||||||
const totalFavPhotos = favPhotos.length;
|
|
||||||
const isLastItem = currentIndex + 1 === totalFavPhotos;
|
|
||||||
|
|
||||||
if (isLastItem && page < photos.pages) {
|
|
||||||
page = page + 1;
|
|
||||||
const { photos } = (await this.client.favorites.getList({ page, })).body;
|
|
||||||
favPhotos.push(...photos.photo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newFavPhotos;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const { photos } = (await this.client.favorites.getList({ per_page: 1, })).body;
|
|
||||||
|
|
||||||
return photos.photo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,80 +0,0 @@
|
|||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewPhotoInAlbum {
|
|
||||||
client?: typeof FlickrApi;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
albumId?: string;
|
|
||||||
extraFields = [
|
|
||||||
'license',
|
|
||||||
'date_upload',
|
|
||||||
'date_taken',
|
|
||||||
'owner_name',
|
|
||||||
'icon_server',
|
|
||||||
'original_format',
|
|
||||||
'last_update',
|
|
||||||
'geo',
|
|
||||||
'tags',
|
|
||||||
'machine_tags',
|
|
||||||
'o_dims',
|
|
||||||
'views',
|
|
||||||
'media',
|
|
||||||
'path_alias',
|
|
||||||
'url_sq',
|
|
||||||
'url_t',
|
|
||||||
'url_s',
|
|
||||||
'url_m',
|
|
||||||
'url_o'
|
|
||||||
].join(',');
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken &&
|
|
||||||
connectionData.accessSecret
|
|
||||||
) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameters?.album) {
|
|
||||||
this.albumId = parameters.album as string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAlbumPhotos(options: { perPage?: number, page?: number } = {}) {
|
|
||||||
const { perPage, page } = options;
|
|
||||||
const payload = {
|
|
||||||
page,
|
|
||||||
per_page: perPage,
|
|
||||||
photoset_id: this.albumId,
|
|
||||||
user_id: this.connectionData.userId,
|
|
||||||
extras: this.extraFields,
|
|
||||||
};
|
|
||||||
const { photoset } = (await this.client.photosets.getPhotos(payload)).body;
|
|
||||||
|
|
||||||
return photoset;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entries
|
|
||||||
const { photo } = await this.getAlbumPhotos({ page: 1 });
|
|
||||||
|
|
||||||
return photo;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const { photo } = await this.getAlbumPhotos({ perPage: 1 });
|
|
||||||
|
|
||||||
return photo;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,88 +0,0 @@
|
|||||||
import { DateTime } from 'luxon';
|
|
||||||
import FlickrApi from 'flickr-sdk';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewPhoto {
|
|
||||||
client?: typeof FlickrApi;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
extraFields = [
|
|
||||||
'description',
|
|
||||||
'license',
|
|
||||||
'date_upload',
|
|
||||||
'date_taken',
|
|
||||||
'owner_name',
|
|
||||||
'icon_server',
|
|
||||||
'original_format',
|
|
||||||
'last_update',
|
|
||||||
'geo',
|
|
||||||
'tags',
|
|
||||||
'machine_tags',
|
|
||||||
'o_dims',
|
|
||||||
'views',
|
|
||||||
'media',
|
|
||||||
'path_alias',
|
|
||||||
'url_sq',
|
|
||||||
'url_t',
|
|
||||||
'url_s',
|
|
||||||
'url_q',
|
|
||||||
'url_m',
|
|
||||||
'url_n',
|
|
||||||
'url_z',
|
|
||||||
'url_c',
|
|
||||||
'url_l',
|
|
||||||
'url_o',
|
|
||||||
].join(',');
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken &&
|
|
||||||
connectionData.accessSecret
|
|
||||||
) {
|
|
||||||
this.client = new FlickrApi(
|
|
||||||
FlickrApi.OAuth.createPlugin(
|
|
||||||
connectionData.consumerKey,
|
|
||||||
connectionData.consumerSecret,
|
|
||||||
connectionData.accessToken,
|
|
||||||
connectionData.accessSecret
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPhotos(options: { perPage?: number, page?: number, minUploadDate?: string } = {}) {
|
|
||||||
const { perPage, page, minUploadDate } = options;
|
|
||||||
const payload = {
|
|
||||||
page,
|
|
||||||
per_page: perPage,
|
|
||||||
user_id: this.connectionData.userId,
|
|
||||||
extras: this.extraFields,
|
|
||||||
min_upload_date: minUploadDate,
|
|
||||||
};
|
|
||||||
const { photos } = (await this.client.photos.search(payload)).body;
|
|
||||||
|
|
||||||
return photos;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const minUploadDate = DateTime.fromJSDate(startTime).toSeconds().toString();
|
|
||||||
const photos = await this.getPhotos({ page: 1, minUploadDate });
|
|
||||||
const allPhotos = [...photos.photo];
|
|
||||||
|
|
||||||
for (let page = photos.page + 1; page <= photos.pages; page++) {
|
|
||||||
const photos = (await this.getPhotos({ page, minUploadDate }));
|
|
||||||
allPhotos.push(...photos.photo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allPhotos;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun(startTime: Date) {
|
|
||||||
const { photo } = await this.getPhotos({ perPage: 1 });
|
|
||||||
|
|
||||||
return photo;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -10,7 +10,13 @@ class App {
|
|||||||
|
|
||||||
// Temporaryly restrict the apps we expose until
|
// Temporaryly restrict the apps we expose until
|
||||||
// their actions/triggers are implemented!
|
// their actions/triggers are implemented!
|
||||||
static temporaryList = ['github', 'scheduler', 'slack', 'twitter'];
|
static temporaryList = [
|
||||||
|
'flickr',
|
||||||
|
'github',
|
||||||
|
'scheduler',
|
||||||
|
'slack',
|
||||||
|
'twitter',
|
||||||
|
];
|
||||||
|
|
||||||
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
||||||
if (!name)
|
if (!name)
|
||||||
|
@@ -25,7 +25,6 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"src/apps/discord",
|
"src/apps/discord",
|
||||||
"src/apps/firebase",
|
"src/apps/firebase",
|
||||||
"src/apps/flickr",
|
|
||||||
"src/apps/gitlab",
|
"src/apps/gitlab",
|
||||||
"src/apps/twitch",
|
"src/apps/twitch",
|
||||||
"src/apps/typeform"
|
"src/apps/typeform"
|
||||||
|
@@ -35,6 +35,7 @@ export default defineConfig({
|
|||||||
text: 'Connections',
|
text: 'Connections',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
items: [
|
items: [
|
||||||
|
{ text: 'Flickr', link: '/connections/flickr' },
|
||||||
{ text: 'Github', link: '/connections/github' },
|
{ text: 'Github', link: '/connections/github' },
|
||||||
{ text: 'Scheduler', link: '/connections/scheduler' },
|
{ text: 'Scheduler', link: '/connections/scheduler' },
|
||||||
{ text: 'Slack', link: '/connections/slack' },
|
{ text: 'Slack', link: '/connections/slack' },
|
||||||
|
22
packages/docs/pages/connections/flickr.md
Normal file
22
packages/docs/pages/connections/flickr.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Flickr
|
||||||
|
|
||||||
|
:::info
|
||||||
|
This page explains the steps you need to follow to set up the Flickr
|
||||||
|
connection in Automatisch. If any of the steps are outdated, please let us know!
|
||||||
|
:::
|
||||||
|
|
||||||
|
1. Go to the [link](https://www.flickr.com/services/apps/create/) to **create an
|
||||||
|
app** on Flickr API.
|
||||||
|
2. Click **Request an API key**.
|
||||||
|
3. Apply for a non-commercial key.
|
||||||
|
4. Fill the field of **What is the name of your app?**.
|
||||||
|
5. Fill the field of **What are you building?**.
|
||||||
|
6. Check the checkboxes.
|
||||||
|
7. Click on **Submit** button.
|
||||||
|
8. Copy **Key** and **Key Secret** values and save them to use later.
|
||||||
|
9. Click **Edit auth flow for this app** to configure "Callback URL".
|
||||||
|
10. Copy **OAuth Redirect URL** from Automatisch and paste it to the **Callback URL** field.
|
||||||
|
11. Click **Save changes**.
|
||||||
|
12. Paste **Key** and **Secret** values you have saved from the 8th step and paste them into Automatisch as **Consumer Key** and **Consumer Secret**, respectively.
|
||||||
|
13. Click **Submit** button on Automatisch.
|
||||||
|
14. Now, you can start using the Flickr connection with Automatisch. **Consumer Key** and **Consumer Secret**, respectively.
|
Reference in New Issue
Block a user