diff --git a/apps/frontend/public/icons/platforms/instagram.png b/apps/frontend/public/icons/platforms/instagram.png new file mode 100644 index 00000000..389d7eb5 Binary files /dev/null and b/apps/frontend/public/icons/platforms/instagram.png differ diff --git a/apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx b/apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx new file mode 100644 index 00000000..e69de29b diff --git a/apps/frontend/src/components/launches/providers/continue-provider/list.tsx b/apps/frontend/src/components/launches/providers/continue-provider/list.tsx new file mode 100644 index 00000000..e69de29b diff --git a/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx b/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx new file mode 100644 index 00000000..a1e9c079 --- /dev/null +++ b/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx @@ -0,0 +1,107 @@ +import { FC } from 'react'; +import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use.formatting'; +import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; +import {afterLinkedinCompanyPreventRemove, linkedinCompanyPreventRemove} from "@gitroom/helpers/utils/linkedin.company.prevent.remove"; + +const LinkedinPreview: FC = (props) => { + const { value: topValue, integration } = useIntegration(); + const mediaDir = useMediaDirectory(); + const newValues = useFormatting(topValue, { + removeMarkdown: true, + saveBreaklines: true, + beforeSpecialFunc: (text: string) => { + return linkedinCompanyPreventRemove(text); + }, + specialFunc: (text: string) => { + return afterLinkedinCompanyPreventRemove(text.slice(0, 280)); + }, + }); + + const [firstPost, ...morePosts] = newValues; + if (!firstPost) { + return null; + } + + return ( +
+
+
+ x +
+
+
{integration?.name}
+
+ CEO @ Gitroom +
+
1m
+
+
+
+
+
+        {!!firstPost?.images?.length && (
+          
+ {firstPost.images.map((image, index) => ( + + + + ))} +
+ )} +
+ {morePosts.map((p, index) => ( +
+
+ x +
+
+
{integration?.name}
+
+ CEO @ Gitroom +
+
+ {p.text} +
+ + {!!p?.images?.length && ( +
+ {p.images.map((image, index) => ( + + + + ))} +
+ )} +
+
+ ))} +
+ ); +}; + +export default withProvider(null, LinkedinPreview); diff --git a/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx b/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx new file mode 100644 index 00000000..759b8e88 --- /dev/null +++ b/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx @@ -0,0 +1,107 @@ +import { FC } from 'react'; +import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use.formatting'; +import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; +import {afterLinkedinCompanyPreventRemove, linkedinCompanyPreventRemove} from "@gitroom/helpers/utils/linkedin.company.prevent.remove"; + +const FacebookPreview: FC = (props) => { + const { value: topValue, integration } = useIntegration(); + const mediaDir = useMediaDirectory(); + const newValues = useFormatting(topValue, { + removeMarkdown: true, + saveBreaklines: true, + beforeSpecialFunc: (text: string) => { + return linkedinCompanyPreventRemove(text); + }, + specialFunc: (text: string) => { + return afterLinkedinCompanyPreventRemove(text.slice(0, 280)); + }, + }); + + const [firstPost, ...morePosts] = newValues; + if (!firstPost) { + return null; + } + + return ( +
+
+
+ x +
+
+
{integration?.name}
+
+ CEO @ Gitroom +
+
1m
+
+
+
+
+
+        {!!firstPost?.images?.length && (
+          
+ {firstPost.images.map((image, index) => ( + + + + ))} +
+ )} +
+ {morePosts.map((p, index) => ( +
+
+ x +
+
+
{integration?.name}
+
+ CEO @ Gitroom +
+
+ {p.text} +
+ + {!!p?.images?.length && ( +
+ {p.images.map((image, index) => ( + + + + ))} +
+ )} +
+
+ ))} +
+ ); +}; + +export default withProvider(null, FacebookPreview); diff --git a/apps/frontend/src/components/layout/continue.provider.tsx b/apps/frontend/src/components/layout/continue.provider.tsx new file mode 100644 index 00000000..e69de29b diff --git a/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts b/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts new file mode 100644 index 00000000..e69de29b diff --git a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts new file mode 100644 index 00000000..e591f9c2 --- /dev/null +++ b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts @@ -0,0 +1,116 @@ +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 FacebookProvider implements SocialProvider { + identifier = 'facebook'; + name = 'Facebook'; + async refreshToken(refresh_token: string): Promise { + const { access_token, expires_in, ...all } = await ( + await fetch( + 'https://graph.facebook.com/v19.0/oauth/access_token' + + '?grant_type=fb_exchange_token' + + `&client_id=${process.env.FACEBOOK_APP_ID}` + + `&client_secret=${process.env.FACEBOOK_APP_SECRET}` + + `&fb_exchange_token=${refresh_token}` + ) + ).json(); + + const { + id, + name, + picture: { + data: { url }, + }, + } = await ( + await fetch( + `https://graph.facebook.com/v19.0/me?fields=id,name,picture&access_token=${access_token}` + ) + ).json(); + + return { + id, + name, + accessToken: access_token, + refreshToken: access_token, + expiresIn: expires_in, + picture: url, + username: '', + }; + } + + async generateAuthUrl() { + const state = makeId(6); + return { + url: + 'https://www.facebook.com/v19.0/dialog/oauth' + + `?client_id=${process.env.FACEBOOK_APP_ID}` + + `&redirect_uri=${encodeURIComponent( + `${process.env.FRONTEND_URL}/integrations/social/facebook` + )}` + + `&state=${state}` + + '&scope=email,public_profile', + // '&scope=email,public_profile,pages_manage_posts,pages_read_engagement,publish_to_groups,groups_access_member_info', + codeVerifier: makeId(10), + state, + }; + } + + async authenticate(params: { code: string; codeVerifier: string }) { + const getAccessToken = await ( + await fetch( + 'https://graph.facebook.com/v19.0/oauth/access_token' + + `?client_id=${process.env.FACEBOOK_APP_ID}` + + `&redirect_uri=${encodeURIComponent( + `${process.env.FRONTEND_URL}/integrations/social/facebook` + )}` + + `&client_secret=${process.env.FACEBOOK_APP_SECRET}` + + `&code=${params.code}` + ) + ).json(); + + const { access_token, expires_in, ...all } = await ( + await fetch( + 'https://graph.facebook.com/v19.0/oauth/access_token' + + '?grant_type=fb_exchange_token' + + `&client_id=${process.env.FACEBOOK_APP_ID}` + + `&client_secret=${process.env.FACEBOOK_APP_SECRET}` + + `&fb_exchange_token=${getAccessToken.access_token}` + ) + ).json(); + + const { + id, + name, + picture: { + data: { url }, + }, + } = await ( + await fetch( + `https://graph.facebook.com/v19.0/me?fields=id,name,picture&access_token=${access_token}` + ) + ).json(); + + return { + id, + name, + accessToken: access_token, + refreshToken: access_token, + expiresIn: expires_in, + picture: url, + username: '', + }; + } + + async post( + id: string, + accessToken: string, + postDetails: PostDetails[] + ): Promise { + return []; + } +} diff --git a/libraries/react-shared-libraries/src/helpers/video.frame.tsx b/libraries/react-shared-libraries/src/helpers/video.frame.tsx new file mode 100644 index 00000000..e69de29b diff --git a/libraries/react-shared-libraries/src/helpers/video.or.image.tsx b/libraries/react-shared-libraries/src/helpers/video.or.image.tsx new file mode 100644 index 00000000..e69de29b