postiz/libraries/nestjs-libraries/src/integrations/social/reddit.provider.ts

218 lines
5.8 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';
export class RedditProvider implements SocialProvider {
identifier = 'reddit';
name = 'Reddit';
async refreshToken(refreshToken: string): Promise<AuthTokenDetails> {
const {
access_token: accessToken,
refresh_token: newRefreshToken,
expires_in: expiresIn,
} = await (
await fetch('https://www.reddit.com/api/v1/access_token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${Buffer.from(
`${process.env.REDDIT_CLIENT_ID}:${process.env.REDDIT_CLIENT_SECRET}`
).toString('base64')}`,
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
}),
})
).json();
const { name, id, icon_img } = await (
await fetch('https://oauth.reddit.com/api/v1/me', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
return {
id,
name,
accessToken,
refreshToken: newRefreshToken,
expiresIn,
picture: icon_img.split('?')[0],
};
}
async generateAuthUrl() {
const state = makeId(6);
const codeVerifier = makeId(30);
const url = `https://www.reddit.com/api/v1/authorize?client_id=${
process.env.REDDIT_CLIENT_ID
}&response_type=code&state=${state}&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/reddit`
)}&duration=permanent&scope=${encodeURIComponent(
'read identity submit flair'
)}`;
return {
url,
codeVerifier,
state,
};
}
async authenticate(params: { code: string; codeVerifier: string }) {
const {
access_token: accessToken,
refresh_token: refreshToken,
expires_in: expiresIn,
} = await (
await fetch('https://www.reddit.com/api/v1/access_token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${Buffer.from(
`${process.env.REDDIT_CLIENT_ID}:${process.env.REDDIT_CLIENT_SECRET}`
).toString('base64')}`,
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: params.code,
redirect_uri: `${process.env.FRONTEND_URL}/integrations/social/reddit`,
}),
})
).json();
const { name, id, icon_img } = await (
await fetch('https://oauth.reddit.com/api/v1/me', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
).json();
return {
id,
name,
accessToken,
refreshToken,
expiresIn,
picture: icon_img.split('?')[0],
};
}
async post(
id: string,
accessToken: string,
postDetails: PostDetails[]
): Promise<PostResponse[]> {
const [post, ...rest] = postDetails;
const response = await fetch('https://oauth.reddit.com/api/submit', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
title: 'test',
kind: 'self',
text: post.message,
sr: '/r/gitroom',
}),
});
return [];
}
async subreddits(accessToken: string, data: any) {
const {
data: { children },
} = await (
await fetch(
`https://oauth.reddit.com/subreddits/search?show=public&q=${data.word}&sort=activity&show_users=false&limit=10`,
{
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
}
)
).json();
console.log(children);
return children.filter(({data} : {data: any}) => data.subreddit_type === "public").map(({ data: { title, url, id } }: any) => ({
title,
name: url,
id,
}));
}
private getPermissions(submissionType: string, allow_images: string) {
const permissions = [];
if (['any', 'self'].indexOf(submissionType) > -1) {
permissions.push('self');
}
if (['any', 'link'].indexOf(submissionType) > -1) {
permissions.push('link');
}
if (submissionType === "any" || allow_images) {
permissions.push('media');
}
return permissions;
}
async restrictions(accessToken: string, data: { subreddit: string }) {
const {
data: { submission_type, allow_images },
} = await (
await fetch(`https://oauth.reddit.com/${data.subreddit}/about`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
})
).json();
const {
is_flair_required,
} = await (
await fetch(`https://oauth.reddit.com/api/v1/${data.subreddit.split('/r/')[1]}/post_requirements`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
})
).json();
const newData = await (
await fetch(`https://oauth.reddit.com/${data.subreddit}/api/link_flair_v2`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
})
).json();
return {
subreddit: data.subreddit,
allow: this.getPermissions(submission_type, allow_images),
is_flair_required,
flairs: newData?.map?.((p: any) => ({
id: p.id,
name: p.text
})) || []
}
}
}