postiz/libraries/nestjs-libraries/src/integrations/social/linkedin.page.provider.ts

199 lines
5.4 KiB
TypeScript

import {
AuthTokenDetails,
PostDetails,
PostResponse,
SocialProvider,
} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import { LinkedinProvider } from '@gitroom/nestjs-libraries/integrations/social/linkedin.provider';
export class LinkedinPageProvider
extends LinkedinProvider
implements SocialProvider
{
override identifier = 'linkedin-page';
override name = 'LinkedIn Page';
override isBetweenSteps = true;
override async refreshToken(
refresh_token: string
): Promise<AuthTokenDetails> {
const { access_token: accessToken, refresh_token: refreshToken } = await (
await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token,
client_id: process.env.LINKEDIN_CLIENT_ID!,
client_secret: process.env.LINKEDIN_CLIENT_SECRET!,
}),
})
).json();
const { vanityName } = await (
await fetch('https://api.linkedin.com/v2/me', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
const {
name,
sub: id,
picture,
} = await (
await fetch('https://api.linkedin.com/v2/userinfo', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
return {
id,
accessToken,
refreshToken,
name,
picture,
username: vanityName,
};
}
override async generateAuthUrl(refresh?: string) {
const state = makeId(6);
const codeVerifier = makeId(30);
const url = `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${
process.env.LINKEDIN_CLIENT_ID
}&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/linkedin-page${
refresh ? `?refresh=${refresh}` : ''
}`
)}&state=${state}&scope=${encodeURIComponent(
'openid profile w_member_social r_basicprofile rw_organization_admin w_organization_social r_organization_social'
)}`;
return {
url,
codeVerifier,
state,
};
}
async companies(accessToken: string) {
const { elements } = await (
await fetch(
'https://api.linkedin.com/v2/organizationalEntityAcls?q=roleAssignee&role=ADMINISTRATOR&projection=(elements*(organizationalTarget~(localizedName,vanityName,logoV2(original~:playableStreams))))',
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
).json();
return (elements || []).map((e: any) => ({
id: e.organizationalTarget.split(':').pop(),
page: e.organizationalTarget.split(':').pop(),
username: e['organizationalTarget~'].vanityName,
name: e['organizationalTarget~'].localizedName,
picture:
e['organizationalTarget~'].logoV2?.['original~']?.elements?.[0]
?.identifiers?.[0]?.identifier,
}));
}
async fetchPageInformation(accessToken: string, pageId: string) {
const data = await (
await fetch(
`https://api.linkedin.com/v2/organizations/${pageId}?projection=(id,localizedName,vanityName,logoV2(original~:playableStreams))`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
).json();
return {
id: data.id,
name: data.localizedName,
access_token: accessToken,
picture: data?.logoV2?.['original~']?.elements?.[0]?.identifiers?.[0].identifier,
username: data.vanityName,
};
}
override async authenticate(params: {
code: string;
codeVerifier: string;
refresh?: string;
}) {
const body = new URLSearchParams();
body.append('grant_type', 'authorization_code');
body.append('code', params.code);
body.append(
'redirect_uri',
`${process.env.FRONTEND_URL}/integrations/social/linkedin-page${
params.refresh ? `?refresh=${params.refresh}` : ''
}`
);
body.append('client_id', process.env.LINKEDIN_CLIENT_ID!);
body.append('client_secret', process.env.LINKEDIN_CLIENT_SECRET!);
const {
access_token: accessToken,
expires_in: expiresIn,
refresh_token: refreshToken,
} = await (
await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body,
})
).json();
const {
name,
sub: id,
picture,
} = await (
await fetch('https://api.linkedin.com/v2/userinfo', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
const { vanityName } = await (
await fetch('https://api.linkedin.com/v2/me', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
return {
id,
accessToken,
refreshToken,
expiresIn,
name,
picture,
username: vanityName,
};
}
override async post(
id: string,
accessToken: string,
postDetails: PostDetails[]
): Promise<PostResponse[]> {
return super.post(id, accessToken, postDetails, 'company');
}
}