feat: bug fixes
This commit is contained in:
parent
e47094fbf4
commit
f1dfce9f1d
|
|
@ -38,8 +38,7 @@ const authenticatedController = [
|
|||
BillingController,
|
||||
NotificationsController,
|
||||
MarketplaceController,
|
||||
MessagesController,
|
||||
CopilotController,
|
||||
MessagesController
|
||||
];
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -60,7 +59,7 @@ const authenticatedController = [
|
|||
]
|
||||
: []),
|
||||
],
|
||||
controllers: [StripeController, AuthController, ...authenticatedController],
|
||||
controllers: [StripeController, AuthController, CopilotController, ...authenticatedController],
|
||||
providers: [
|
||||
AuthService,
|
||||
StripeService,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
import { Controller, Post, Req, Res } from '@nestjs/common';
|
||||
import { CopilotRuntime, OpenAIAdapter } from '@copilotkit/backend';
|
||||
import {
|
||||
CopilotRuntime,
|
||||
OpenAIAdapter,
|
||||
copilotRuntimeNestEndpoint,
|
||||
} from '@copilotkit/runtime';
|
||||
|
||||
@Controller('/copilot')
|
||||
export class CopilotController {
|
||||
@Post('/chat')
|
||||
chat(@Req() req: Request, @Res() res: Response) {
|
||||
const copilotKit = new CopilotRuntime({});
|
||||
return copilotKit.streamHttpServerResponse(
|
||||
req,
|
||||
res,
|
||||
new OpenAIAdapter({ model: 'gpt-4o' })
|
||||
);
|
||||
const copilotRuntimeHandler = copilotRuntimeNestEndpoint({
|
||||
endpoint: '/copilot/chat',
|
||||
runtime: new CopilotRuntime(),
|
||||
serviceAdapter: new OpenAIAdapter({ model: 'gpt-4o' }),
|
||||
});
|
||||
|
||||
return copilotRuntimeHandler(req, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -142,17 +142,33 @@ export const PickPlatforms: FC<{
|
|||
await timer(500);
|
||||
await Promise.all(promises);
|
||||
},
|
||||
[selectedAccounts]
|
||||
[onChange, props.singleSelect, selectedAccounts, setSelectedAccounts]
|
||||
);
|
||||
|
||||
const handler = useCallback(
|
||||
async ({ integrationId }: { integrationId: string }) => {
|
||||
console.log('setSelectedIntegration', integrations, integrationId, dayjs().unix());
|
||||
const findIntegration = integrations.find((p) => p.id === integrationId)!;
|
||||
await addPlatform(findIntegration)();
|
||||
},
|
||||
[selectedAccounts, integrations, selectedAccounts]
|
||||
);
|
||||
const handler = async ({ integrationsId }: { integrationsId: string[] }) => {
|
||||
console.log(
|
||||
'setSelectedIntegration',
|
||||
integrations,
|
||||
integrationsId,
|
||||
dayjs().unix()
|
||||
);
|
||||
|
||||
const selected = selectedIntegrations.map((p) => p.id);
|
||||
const notToRemove = selected.filter((p) => integrationsId.includes(p));
|
||||
const toAdd = integrationsId.filter((p) => !selected.includes(p));
|
||||
|
||||
const newIntegrations = [...notToRemove, ...toAdd]
|
||||
.map((id) => integrations.find((p) => p.id === id)!)
|
||||
.filter((p) => p);
|
||||
|
||||
setSelectedAccounts(newIntegrations, () => {
|
||||
console.log('changed')
|
||||
});
|
||||
|
||||
onChange(newIntegrations, () => {
|
||||
console.log('changed')
|
||||
});
|
||||
};
|
||||
|
||||
useCopilotReadable({
|
||||
description: isMain
|
||||
|
|
@ -165,19 +181,26 @@ export const PickPlatforms: FC<{
|
|||
{
|
||||
name: isMain ? `addOrRemovePlatform` : 'setSelectedIntegration',
|
||||
description: isMain
|
||||
? `Add or remove one channel to schedule your post to, always pass the id`
|
||||
: 'Set selected integration',
|
||||
? `Add or remove channels to schedule your post to, pass all the ids as array`
|
||||
: 'Set selected integrations',
|
||||
parameters: [
|
||||
{
|
||||
name: 'integrationId',
|
||||
type: 'string',
|
||||
description: 'The id of the integration',
|
||||
name: 'integrationsId',
|
||||
type: 'string[]',
|
||||
description: 'List of integrations id to set as selected',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler,
|
||||
},
|
||||
[addPlatform, selectedAccounts, integrations]
|
||||
[
|
||||
addPlatform,
|
||||
selectedAccounts,
|
||||
integrations,
|
||||
onChange,
|
||||
props.singleSelect,
|
||||
setSelectedAccounts,
|
||||
]
|
||||
);
|
||||
|
||||
if (hide) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const DribbblePreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<ImageFile
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -53,6 +53,13 @@ const DribbblePreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<ImageFile
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -85,7 +92,7 @@ const DribbblePreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<ImageFile
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -93,6 +100,13 @@ const DribbblePreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<ImageFile
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const FacebookPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -40,6 +40,13 @@ const FacebookPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -72,7 +79,7 @@ const FacebookPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -80,6 +87,13 @@ const FacebookPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const InstagramPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -40,6 +40,13 @@ const InstagramPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -71,7 +78,7 @@ const InstagramPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -79,6 +86,13 @@ const InstagramPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const LinkedinPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -40,6 +40,13 @@ const LinkedinPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -72,7 +79,7 @@ const LinkedinPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -80,6 +87,13 @@ const LinkedinPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const PinterestPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<ImageFile
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -60,6 +60,13 @@ const PinterestPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<ImageFile
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -92,7 +99,7 @@ const PinterestPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<ImageFile
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -100,6 +107,13 @@ const PinterestPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<ImageFile
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ const RedditPreview: FC = (props) => {
|
|||
>
|
||||
{restOfPosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[32px] h-[32px]">
|
||||
<div className="w-[32px] h-[32px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -126,6 +126,13 @@ const RedditPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] w-full pr-[64px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const ThreadsPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -40,6 +40,13 @@ const ThreadsPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -71,7 +78,7 @@ const ThreadsPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -79,6 +86,13 @@ const ThreadsPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ const TikTokPreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -167,6 +167,13 @@ const TikTokPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -199,7 +206,7 @@ const TikTokPreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -207,6 +214,13 @@ const TikTokPreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const YoutubePreview: FC = (props) => {
|
|||
return (
|
||||
<div className="rounded-[8px] flex flex-col gap-[8px] border border-black/90 w-[555px] pt-[12px] pl-[16px] pb-[12px] pr-[40px] bg-white text-black font-['helvetica']">
|
||||
<div className="flex gap-[8px]">
|
||||
<div className="w-[48px] h-[48px]">
|
||||
<div className="w-[48px] h-[48px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -76,6 +76,13 @@ const YoutubePreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col leading-[16px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
@ -108,7 +115,7 @@ const YoutubePreview: FC = (props) => {
|
|||
</div>
|
||||
{morePosts.map((p, index) => (
|
||||
<div className="flex gap-[8px]" key={index}>
|
||||
<div className="w-[40px] h-[40px]">
|
||||
<div className="w-[40px] h-[40px] relative">
|
||||
<Image
|
||||
width={48}
|
||||
height={48}
|
||||
|
|
@ -116,6 +123,13 @@ const YoutubePreview: FC = (props) => {
|
|||
alt="x"
|
||||
className="rounded-full w-full h-full relative z-[2]"
|
||||
/>
|
||||
<Image
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/icons/platforms/${integration?.identifier!}.png`}
|
||||
alt="x"
|
||||
className="rounded-full absolute -right-[5px] -bottom-[5px] z-[2]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col leading-[16px] bg-[#F2F2F2] w-full pt-[8px] pr-[64px] pl-[12px] pb-[8px] rounded-[8px]">
|
||||
<div className="text-[14px] font-[600]">{integration?.name}</div>
|
||||
|
|
|
|||
|
|
@ -205,10 +205,7 @@ export class IntegrationRepository {
|
|||
where: {
|
||||
organizationId: org,
|
||||
integrationId: id,
|
||||
deletedAt: null,
|
||||
state: {
|
||||
in: ['QUEUE', 'DRAFT'],
|
||||
},
|
||||
deletedAt: null
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,13 +68,14 @@ export class PostsService {
|
|||
}
|
||||
|
||||
async getPost(orgId: string, id: string) {
|
||||
const posts = await this.getPostsRecursively(id, false, orgId, true);
|
||||
const posts = await this.getPostsRecursively(id, true, orgId, true);
|
||||
return {
|
||||
group: posts?.[0]?.group,
|
||||
posts: posts.map((post) => ({
|
||||
...post,
|
||||
image: JSON.parse(post.image || '[]'),
|
||||
})),
|
||||
integrationPicture: posts[0]?.integration?.picture,
|
||||
integration: posts[0].integrationId,
|
||||
settings: JSON.parse(posts[0].settings || '{}'),
|
||||
};
|
||||
|
|
@ -148,7 +149,7 @@ export class PostsService {
|
|||
`Error posting on ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name}`,
|
||||
`An error occurred while posting on ${
|
||||
firstPost.integration?.providerIdentifier
|
||||
} ${JSON.stringify(err)}`,
|
||||
} ${err}`,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ export abstract class SocialAbstract {
|
|||
async fetch(url: string, options: RequestInit = {}) {
|
||||
const request = await fetch(url, options);
|
||||
console.log(request.status);
|
||||
if (request.status !== 200 && request.status !== 201) {
|
||||
try {
|
||||
console.log(await request.json());
|
||||
}
|
||||
catch (err) {
|
||||
console.log('skip');
|
||||
}
|
||||
}
|
||||
if (request.status === 401) {
|
||||
throw new RefreshToken();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,22 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
|
|||
};
|
||||
}
|
||||
|
||||
private async checkLoaded(mediaContainerId: string, accessToken: string): Promise<boolean> {
|
||||
const {status, id, error_message} = await (await this.fetch(`https://graph.threads.net/v1.0/${mediaContainerId}?fields=status,error_message&access_token=${accessToken}`)).json();
|
||||
console.log(status, error_message);
|
||||
if (status === 'ERROR') {
|
||||
throw new Error(id);
|
||||
}
|
||||
|
||||
if (status === 'FINISHED') {
|
||||
await timer(2000);
|
||||
return true;
|
||||
}
|
||||
|
||||
await timer(2200);
|
||||
return this.checkLoaded(mediaContainerId, accessToken);
|
||||
}
|
||||
|
||||
async fetchPageInformation(accessToken: string) {
|
||||
const { id, username, threads_profile_picture_url, access_token } = await (
|
||||
await this.fetch(
|
||||
|
|
@ -163,6 +179,8 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
|
|||
)
|
||||
).json();
|
||||
|
||||
await this.checkLoaded(containerId, accessToken);
|
||||
|
||||
const { id: threadId } = await (
|
||||
await this.fetch(
|
||||
`https://graph.threads.net/v1.0/${id}/threads_publish?creation_id=${containerId}&access_token=${accessToken}`,
|
||||
|
|
@ -188,10 +206,10 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
|
|||
|
||||
const media = new URLSearchParams({
|
||||
...(type === 'video_url'
|
||||
? { video_url: firstPost?.media![0].path }
|
||||
? { video_url: mediaLoad.path }
|
||||
: {}),
|
||||
...(type === 'image_url'
|
||||
? { image_url: firstPost?.media![0].path }
|
||||
? { image_url: mediaLoad.path }
|
||||
: {}),
|
||||
is_carousel_item: 'true',
|
||||
media_type:
|
||||
|
|
@ -216,6 +234,8 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
|
|||
medias.push(mediaId);
|
||||
}
|
||||
|
||||
await Promise.all(medias.map((p: string) => this.checkLoaded(p, accessToken)));
|
||||
|
||||
const { id: containerId } = await (
|
||||
await this.fetch(
|
||||
`https://graph.threads.net/v1.0/${id}/threads?text=${
|
||||
|
|
@ -229,6 +249,8 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
|
|||
)
|
||||
).json();
|
||||
|
||||
await this.checkLoaded(containerId, accessToken);
|
||||
|
||||
const { id: threadId } = await (
|
||||
await this.fetch(
|
||||
`https://graph.threads.net/v1.0/${id}/threads_publish?creation_id=${containerId}&access_token=${accessToken}`,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/provide
|
|||
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
|
||||
import * as process from 'node:process';
|
||||
import dayjs from 'dayjs';
|
||||
import { GaxiosError } from 'gaxios/build/src/common';
|
||||
|
||||
const clientAndYoutube = () => {
|
||||
const client = new google.auth.OAuth2({
|
||||
|
|
@ -154,16 +155,18 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider {
|
|||
snippet: {
|
||||
title: settings.title,
|
||||
description: firstPost?.message,
|
||||
tags: settings.tags.map((p) => p.label),
|
||||
...(settings?.thumbnail?.path
|
||||
? {
|
||||
thumbnails: {
|
||||
default: {
|
||||
url: settings?.thumbnail?.path,
|
||||
},
|
||||
},
|
||||
}
|
||||
...(settings?.tags?.length
|
||||
? { tags: settings.tags.map((p) => p.label) }
|
||||
: {}),
|
||||
// ...(settings?.thumbnail?.path
|
||||
// ? {
|
||||
// thumbnails: {
|
||||
// default: {
|
||||
// url: settings?.thumbnail?.path,
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// : {}),
|
||||
},
|
||||
status: {
|
||||
privacyStatus: settings.type,
|
||||
|
|
@ -174,16 +177,62 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider {
|
|||
},
|
||||
});
|
||||
|
||||
console.log(all);
|
||||
|
||||
if (settings?.thumbnail?.path) {
|
||||
try {
|
||||
const allb = await youtubeClient.thumbnails.set({
|
||||
videoId: all?.data?.id!,
|
||||
media: {
|
||||
body: (
|
||||
await axios({
|
||||
url: settings?.thumbnail?.path,
|
||||
method: 'GET',
|
||||
responseType: 'stream',
|
||||
})
|
||||
).data,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(allb);
|
||||
} catch (err: any) {
|
||||
if (
|
||||
err.response?.data?.error?.errors?.[0]?.domain ===
|
||||
'youtube.thumbnail'
|
||||
) {
|
||||
throw 'Your account is not verified, we have uploaded your video but we could not set the thumbnail. Please verify your account and try again.';
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(err?.response?.data, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: firstPost.id,
|
||||
releaseURL: `https://www.youtube.com/watch?v=${all.data.id}`,
|
||||
releaseURL: `https://www.youtube.com/watch?v=${all?.data?.id}`,
|
||||
postId: all?.data?.id!,
|
||||
status: 'success',
|
||||
},
|
||||
];
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
} catch (err: any) {
|
||||
if (
|
||||
err.response?.data?.error?.errors?.[0]?.reason === 'failedPrecondition'
|
||||
) {
|
||||
throw 'We have uploaded your video but we could not set the thumbnail. Thumbnail size is too large';
|
||||
}
|
||||
if (
|
||||
err.response?.data?.error?.errors?.[0]?.reason === 'uploadLimitExceeded'
|
||||
) {
|
||||
throw 'You have reached your daily upload limit, please try again tomorrow.';
|
||||
}
|
||||
if (
|
||||
err.response?.data?.error?.errors?.[0]?.reason ===
|
||||
'youtubeSignupRequired'
|
||||
) {
|
||||
console.log('nevo david!');
|
||||
throw 'You have to link your youtube account to your google account first.';
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -19,10 +19,10 @@
|
|||
"@aws-sdk/client-s3": "^3.410.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.410.0",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@copilotkit/backend": "0.37.0",
|
||||
"@copilotkit/react-core": "0.37.0",
|
||||
"@copilotkit/react-textarea": "0.37.0",
|
||||
"@copilotkit/react-ui": "0.37.0",
|
||||
"@copilotkit/react-core": "^1.0.9",
|
||||
"@copilotkit/react-textarea": "^1.0.9",
|
||||
"@copilotkit/react-ui": "^1.0.9",
|
||||
"@copilotkit/runtime": "^1.0.9",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mantine/core": "^5.10.5",
|
||||
"@mantine/dates": "^5.10.5",
|
||||
|
|
|
|||
Loading…
Reference in New Issue